I am using ruby version 2.0.0 , I made some custom logo in text file named logo.txt like this:
_____
| |
|_____|
|
|
|
Now i made a gem with name of "custom" and placed this file under lib/logo.txt . Now i wants to print this file in my script under ruby gem so i wrote in this way.
file = File.open("lib/logo.txt")
contents = file.read
puts "#{contents}"
But above code produce errors, like:
/usr/local/rvm/rubies/ruby-2.0.0-p451/lib/ruby/gems/2.0.0/gems/custom-0.0.1/lib/custom/custom.rb:1551:in `initialize': No such file or directory - lib/logo.txt (Errno::ENOENT)
I include this logo.txt file in gemspec as per below:
Gem::Specification.new do |s|
s.name = "custom"
s.version = VERSION
s.author = "Custom Wear"
s.email = "custom#custom.com"
s.homepage = "http://custom.com"
s.summary = "custom wera"
s.description = File.read(File.join(File.dirname(__FILE__), 'README'))
s.license = 'ALL RIGHTS RESERVED'
s.files = [""lib/custom.rb", "lib/custom/custom.rb", "lib/custom /version.rb","lib/logo.txt"]
s.test_files = Dir["spec/**/*"]
s.executables = [ 'custom' ]
s.require_paths << 'lib/'
The file is opened relative to the current working directory, unless you specify the full path.
In order to avoid hard-coding full paths, you can get the full path of the current file from Ruby using __FILE__. In fact you can see in the custom.gemspec file something very similar going on:
File.join( File.dirname(__FILE__), 'README')
I think you can get to your logo file like this:
logo_path = File.join( File.dirname(__FILE__), '../logo.txt' )
file = File.open( logo_path )
In Ruby 2.0, you also have __dir__ (which can replace File.dirname(__FILE__)) but that would not be compatible with Ruby 1.9. Generally you are safer using backward-compatible syntax in gems in case you are not sure what someone has when they run your library.
Related
Objective : Rename the folder in directory with today's
date
I am using ruby file where I am using linux command to modify directory(ruby version is 2.2) and my code looks like this.
require 'date'
class BSDK
TDATE = Date.today.to_s
DEFAULT_PATH = "/home/cyborg/bsdk/"
VERSION = "bsdk-tk-4.2.71"
def bsdk_processing
bsdk_version = "#{DEFAULT_PATH}#{VERSION}"
bsdk_latest = "#{bsdk_version}(#{TDATE})"
system "mv #{bsdk_version} #{bsdk_latest}"
end
end
bsdk = BSDK.new
bsdk.bsdk_processing
Error:
mv: missing destination file operand after '/home/cyborg/bsdk/bsdk-tk-4.2.71'
When I tried printing bsdk_latest, it is giving me as
/home/cyborg/bsdk/bsdk-tk-4.2.71
2019-08-22
and not as /home/cyborg/bsdk/bsdk-tk-4.2.71(2019-08-22)
Note: we have directory named bsdk-tk-4.2.71 in the path /home/cyborg/bsdk/
The issue got resolved as pointed by #user1934428 , there was new line embedded in the VERSION
require 'date'
require 'fileutils'
class BSDK
TDATE = Date.today.to_s
DEFAULT_PATH = "/home/cyborg/bsdk/"
VERSION = "bsdk-tk-4.2.71"
VERSION.strip!
def bsdk_processing
bsdk_version = "#{DEFAULT_PATH}#{VERSION}"
bsdk_latest = "#{bsdk_version}""(#{TDATE})"
Fileutils.mv("#{bsdk_version}", "#{bsdk_latest}")
end
end
bsdk = BSDK.new
bsdk.bsdk_processing
My podspec file looks something like:
Pod::Spec.new do |s|
s.name = "MyLib"
s.version = "5.0.0"
...
s.resource_bundles = {'MyBundle' => ["sdk-ios/publickey/prod/ios-5.0.0/somebinary.bin"]}
end
I am picking some binary file and putting it in the resource bundle. There is a separate binary file for each version and is kept in a folder the name of which goes by the version. Now while releasing the new version, instead of making changes at two places - namely s.version and s.resources, is there a way I can use s.version in the value of s.resources? Something like:
s.resource_bundles = {'MyBundle' => ["sdk-ios/publickey/prod/ios-${s.version.to_s}/somebinary.bin"]}
You need to be using # instead of $:
s.resource_bundles = {'MyBundle' => ["sdk-ios/publickey/prod/ios-#{s.version}/somebinary.bin"]}
I am following the very basic tutorial found here: http://guides.rubygems.org/make-your-own-gem/
hola_username.rb:
class Hola
def self.hi
puts "Hello world!"
end
end
hola_username.gemspec:
Gem::Specification.new do |s|
s.name = 'hola_username'
s.version = '0.0.0'
s.date = '2010-04-28'
s.summary = "Hola!"
s.description = "A simple hello world gem"
s.authors = ["Surname Lastname"]
s.email = 'me.me#gmail.com'
s.files = ["lib/hola_username.rb"]
s.homepage =
'http://rubygems.org/gems/hola_username'
s.license = 'MIT'
end
That really is all there is to the project.
I can build my gem with
gem build .\hola_username.gemspec
I have also tested it by importing and executing the hi function of the Hola class and it works:
PS E:\hola_username> gem install .\hola_username-0.0.0.gem
Successfully installed hola_username-0.0.0
Parsing documentation for hola_username-0.0.0
Done installing documentation for hola_username after 0 seconds
1 gem installed
&
irb(main):001:0> require 'hola_username'
=> true
irb(main):002:0> Hola.hi
Hello world!
=> nil
irb(main):003:0>
But when I try to
gem push .\hola_username-0.0.0.gem
I get:
ERROR: While executing gem ... (Psych::SyntaxError)
(): control characters are not allowed at line 1 column 1
Any ideas?
Edit: I am on a windows 10 machine using ruby 2.0.0p598
Edit v01: Anything I put after gem push will result in the above error, doesn't seem to be a problem with the sample rubygem.
Edit v02: My credentials file that was generated in the .gem folder however stars with hex characters: fffe2d002d00.. Which might be the ones causing trouble?
My credentials file in .gem folder was encoded with UCS2 - Little Endian and converting it to UTF without BOM did the trick.
Although I have absolutey no idea why..
I've always used git to determine which files should go into the gem package:
gem.files = `git ls-files`.split "\n"
Unfortunately, this approach has recently proved to be inappropriate. I need a self-contained, pure-Ruby solution.
My first idea was to simply glob the entire directory, but that alone is likely to include unwanted files. So, after researching the problem, I came up with this:
# example.gemspec
directory = File.dirname File.expand_path __FILE__
dotfiles = %w(.gitignore .rvmrc)
ignore_file = '.gitignore'
file_list = []
Dir.chdir directory do
ignored = File.readlines(ignore_file).map(&:chomp).reject { |glob| glob =~ /\A(#|\s*\z)/ }
file_list.replace Dir['**/**'] + dotfiles
file_list.delete_if do |file|
File.directory?(file) or ignored.any? { |glob| File.fnmatch? glob, file }
end
end
# Later...
gem.files = file_list
That seems a bit complex for a gemspec. It also does not fully support gitignore's pattern format. It currently seems to work but I'd rather not run into problems later.
Is there a simpler but robust way to compute the gem's list of files? Most gems apparently use git ls-files, and the ones that don't either use a solution similar to mine or specify the files manually.
Hi,
You can list all files of your project with pure Ruby:
gem.files = Dir['**/*'].keep_if { |file| File.file?(file) }
Or you can do it manually, this solution is used by Ruby on Rails gems:
gem.files = Dir['lib/**/*'] + %w(.yardopts Gemfile LICENSE README.md Rakefile my_gem.gemspec)
With Rake
The easiest solution depending on rake to list all files from a directory, but exclude everything in the .gitignore file:
require 'rake/file_list'
Rake::FileList['**/*'].exclude(*File.read('.gitignore').split)
RubyGems
Official rubygems solution, list and exclude manually:
require 'rake'
spec.files = FileList['lib/*.rb',
'bin/*',
'[A-Z]*',
'test/*'].to_a
# or without Rake...
spec.files = Dir['lib/*.rb'] + Dir['bin/*']
spec.files += Dir['[A-Z]*'] + Dir['test/**/*']
spec.files.reject! { |fn| fn.include? "CVS" }
Bundler
Bundler solution, list manually:
s.files = Dir.glob("{lib,exe}/**/*", File::FNM_DOTMATCH).reject {|f| File.directory?(f) }
Note: rejecting directories is useless as gem will ignore them by default.
Vagrant
Vagrant solution to mimic git ls-files and taking care of .gitignore in pure ruby:
# The following block of code determines the files that should be included
# in the gem. It does this by reading all the files in the directory where
# this gemspec is, and parsing out the ignored files from the gitignore.
# Note that the entire gitignore(5) syntax is not supported, specifically
# the "!" syntax, but it should mostly work correctly.
root_path = File.dirname(__FILE__)
all_files = Dir.chdir(root_path) { Dir.glob("**/{*,.*}") }
all_files.reject! { |file| [".", ".."].include?(File.basename(file)) }
all_files.reject! { |file| file.start_with?("website/") }
all_files.reject! { |file| file.start_with?("test/") }
gitignore_path = File.join(root_path, ".gitignore")
gitignore = File.readlines(gitignore_path)
gitignore.map! { |line| line.chomp.strip }
gitignore.reject! { |line| line.empty? || line =~ /^(#|!)/ }
unignored_files = all_files.reject do |file|
# Ignore any directories, the gemspec only cares about files
next true if File.directory?(file)
# Ignore any paths that match anything in the gitignore. We do
# two tests here:
#
# - First, test to see if the entire path matches the gitignore.
# - Second, match if the basename does, this makes it so that things
# like '.DS_Store' will match sub-directories too (same behavior
# as git).
#
gitignore.any? do |ignore|
File.fnmatch(ignore, file, File::FNM_PATHNAME) ||
File.fnmatch(ignore, File.basename(file), File::FNM_PATHNAME)
end
end
Pathspec
Using pathspec gem Match Path Specifications, such as .gitignore, in Ruby!
See https://github.com/highb/pathspec-ruby
References
Ref:
Bundler
Vagrant
RubyGems
Rake easy solution
Here, I'm using a rubyzip and nokogiri to modify a .docx file.
RubyZip -> Unzip .docx file
Nokogiri -> Parse and change in content of the body of word/document.xml
As I wrote the sample code just below but code modify the file but others file were disturbed. In other words, updated file is not opening showing error the word processor is crashed. How can I resolve this issue ?
require 'zip/zipfilesystem'
require 'nokogiri'
zip = Zip::ZipFile.open("SecurityForms.docx")
doc = zip.find_entry("word/document.xml")
xml = Nokogiri::XML.parse(doc.get_input_stream)
wt = xml.root.xpath("//w:t", {"w" => "http://schemas.openxmlformats.org/wordprocessingml/2006/main"}).first
wt.content = "FinalStatement"
zip.get_output_stream("word/document.xml") {|f| f << xml.to_s}
zip.close
According to the official Github documentation, you should Use write_buffer instead open. There's also a code example at the link.
Following is the code that edit the content of a .docx template file.It first creae a new copy of your template.docx remember u will create this template file and keep this file in the same folder where you create your ruby class like you will create My_Class.rb and copy following code in it.It works perfectly for my case. Remember you need to install rubyzip and nokogiri gem in a gemset.(Google them to install).Thanks
require 'rubygems'
require 'zip/zipfilesystem'
require 'nokogiri'
class Edit_docx
def initialize
coupling = [('a'..'z'),('A'..'Z')].map{|i| i.to_a}.flatten
secure_string = (0...50).map{ coupling[rand(coupling.length)] }.join
FileUtils.cp 'template.docx', "#{secure_string}.docx"
zip = Zip::ZipFile.open("#{secure_string}.docx")
doc = zip.find_entry("word/document.xml")
xml = Nokogiri::XML.parse(doc.get_input_stream)
wt = xml.root.xpath("//w:t", {"w"=>"http://schemas.openxmlformats.org/wordprocessingml/2006/main"})
#puts wt
wt.each_with_index do |tag,i|
tag.content = i.to_s + ""
end
zip.get_output_stream("word/document.xml") {|f| f << xml.to_s}
zip.close
puts secure_string
#FileUtils.rm("#{secure_string}.docx")
end
N.new
end