Forcing a copy with a Thor action - ruby

I'm using the Thor built-in action "copy_file" to copy a file from my template source, overwriting an existing file.
I always want to overwrite, and don't want to have to confirm this interactively.
The documentation doesn't suggest there is a force option in the config hash for this action, but http://textmate.rubyforge.org/thor/Thor/Actions.html does indicate that config[:behavior] can be set to force, but I can't see how to do this.
If anyone has an example of doing this that they could share, I'd be most grateful.
Thanks.

Look at the source of copy_file action at https://github.com/erikhuda/thor/blob/master/lib/thor/actions/file_manipulation.rb it uses create_file and passes config Hash to it. Ok, let us see specs for create_file https://github.com/erikhuda/thor/blob/master/spec/actions/create_file_spec.rb . Search the file for 'force', action can be invoked with:
create_file("doc/config.rb", :force => true)
Try that with your copy_file action, append :force => true at the end, it is treated as config hash, passed to create_file and it should work.

Related

Replacing variable value in ruby while setting the value using "set" command

I have a .properties files as below:
user:abcd
pwd:xyz
system:test
Next, I have a ruby script with Watir for browser automation. In this script, I have statements like
browser.text_field(:id => 'identifierId').set "#{user}:variable to be replaced by its value from .properties file".
Similarly, other values need to be replaced for "pwd" and "system".
I tried the solution per below posts:
Replace properties in one file from those in another in Ruby
However, "set" command is setting whatever has been paased as arguments to it instead of replacing the variable with its value.
Please help.
You have to read the information out of the file.
Most Watir users leverage yaml files for this.
config/properties.yml:
user: abcd
pwd: xyz
system: test
Then read the yaml file & parse your data:
properties = YAML.safe_load(IO.read('config/properties.yml'))
text_field = browser.text_field(id: 'identifierId')
text_field.set properties['user']
Alternately you can take a look at Cheezy's Fig Newton gem, which is designed to work with his Page Object gem

Ruby fileutils: Forcing symlink creation from within cp_r

I'm attempting to recursively copy directories with Ruby's cp_r method in fileutils. However, it crashes in the (silly but out of my control) case where in the directory I copy there is a file and a symbolic link to that file. I get the following error:
/usr/lib/ruby/1.8/fileutils.rb:1223:in `symlink': File exists - real_file_name or symbolic_link_filename (Errno::EEXIST)
Now, I might be wrong, but it seems like something that symlink's :force option should take care of; however, cp_r cannot take a :force option, and I see no way to make it pass that option to its internal calls to symlink. Also, catching the EEXISTS error doesn't seem to be a solution since the run of cp_r would still be interrupted.
Is there a clean way to get around this problem?
You can use FileUtils.cp_r and pass it the option remove_destination: true to accomplish this.

How to know whether a FileUtils command was successful?

I don't see any return value from FileUtils commands.
I'd like to do something like:
really=(gets.chomp=="y")
if really
success = FileUtils.rm_rf "./PROJECT_#{#name}" #does not work
end
puts "./PROJECT_#{#name} deleted" if success
I read the documentation for FileUtils, and also read a "Getting executed command from ruby FileUtils", but I cannot figure how to use the answer.
According to the documentation ( http://ruby-doc.org/stdlib-1.9.3/libdoc/fileutils/rdoc/FileUtils.html#method-c-rm_rf ) calls to #rm_rf will not echo anything relevant to the task they are taking. #rm_rf actually calls #rm_r with option :force => true. This options enables the method to ignore the StandardError Exception (which would then communicate you something about the operation or why it is not working). Now, back to why it is failing. As somebody already commented, try with the option :secure => true. More info about this here: http://ruby-doc.org/stdlib-1.9.3/libdoc/fileutils/rdoc/FileUtils.html#method-c-remove_entry_secure . This is probably a permission issue.
I think you need to check the return value:
irb(main):006:0> FileUtils.rm_rf 'test'
=> ["test"]
irb(main):007:0>
and check if an exception is raised in case of the directory doesn't exist.
If you need the return value, maybe your only option is to run the command inside ruby, please take a look at this blog post.

How to pass parameters to MiniTest::Unit::TestCase suite?

I'm using an external API that takes a key string, and would like to pass this key string to the test suite. Something like:
rake test [key=api_key]
The code together with the tests will be open sourced, but I'm not allowed to distribute my key string to other users, so I cannot put it in the test file. Can I pass it as a parameter?
You have two options. Pass it as an environment variable:
API_KEY='key' rake test
You can then access this through the ENV object in your test:
key = ENV['API_KEY']
Second option is to put this key in a file (e.g. key.txt) and you read it from that. To ensure that you don't distribute that file with your code, add it to your .gitignore file (or whatever is the ignore file used by your SCM)
Thank you very much!
I actually was thinking of putting it into a file and gitignoring it, but ended up passing a parameter to rake. May be, I will combine both (it's a long key).
Modify the Rakefile code for the :test task, such as adding a
parameter to it.
task :test, :key do |t, k|
result = system("ruby -Ilib -Itest -e 'ARGV.each { |f| load(f) if File.exists?(f)}' test/unit/* '#{k[:key]}'")
exit(result ? 0 : 1)
end
Call rake test['blah-blah']
It may take more then one key if needed.

System call in Ruby

I'm a beginner in ruby and in programming as well and need help with system call for moving a file from source to destination like this:
system(mv "#{#SOURCE_DIR}/#{my_file} #{#DEST_DIR}/#{file}")
Is it possible to do this in Ruby? If so, what is the correct syntax?
system("mv #{#SOURCE_DIR}/#{my_file} #{#DEST_DIR}/#{file})
can be replaced with
system("mv", "#{#SOURCE_DIR}/#{my_file}", "#{#DEST_DIR}/#{file}")
which reduces the chances of a command line injection attack.
Two ways
Recommended way
You can use the functions in the File Utils libary see here to move your files e.g
mv(src, dest, options = {})
Options: force noop verbose
Moves file(s) src to dest. If file and dest exist on the different disk
partition, the file is copied instead.
FileUtils.mv 'badname.rb', 'goodname.rb'
FileUtils.mv 'stuff.rb', '/notexist/lib/ruby', :force => true # no error
FileUtils.mv %w(junk.txt dust.txt), '/home/aamine/.trash/'
FileUtils.mv Dir.glob('test*.rb'), 'test', :noop => true, :verbose => true
Naughty way
Use the backticks approach (run any string as a command)
result = `mv "#{#SOURCE_DIR}/#{my_file} #{#DEST_DIR}/#{file}"`
Ok, that's just a variation of calling the system command but looks much naughtier!
system("mv #{#SOURCE_DIR}/#{my_file} #{#DEST_DIR}/#{file})
should be the correct call
I recommend you to use Tanaka akira's escape library
Here is example from one my app:
cmd = Escape.shell_command(['python', Rails::Configuration.new.root_path + '/script/grab.py']).to_s
system cmd

Resources