Rakefile - access variable defined in a prerequisite - ruby

Is there some way to access a variable defined in a prerequisite? e.g.
task :new_file do
filename = 'foobar.txt' # in reality I ask the user for the filename
File.write(filename, 'Some glorious content')
end
task :new_file! => [:new_file] do
exec "vim #{filename.inspect}"
end
I'd like rake new_file! to simply be a shorthand for rake new_file along with launching vim for whatever file I created in the new_file task.
All I can think of is populating a global variable FILENAME in :new_file and using it in new_file! and then clearing it, but if there is a "more Rake" way to do it, I'd like to know.

One way would be to define the variable outside the tasks like this:
filename = 'default.name'
task :new_file do
filename = 'foobar.txt' # in reality I ask the user for the filename
File.write(filename, 'Some glorious content')
end
task :new_file! => [:new_file] do
# filename will be visible here too, and its value was set in new_file
exec "vim #{filename.inspect}"
end

Related

How to pass command line parameters to capistrano

I am using Capistrano v2.9.0.
I run this command:
cap deploy:tryout -S testvar=thing
and my deploy.rb contains this:
namespace :deploy do
task :tryout do
if defined? testvar
puts "param: #{testvar}\n"
else
puts "no branch!\n"
end
end
end
The output is "no branch!". How do I pass values from the command line? I tried looking into the code, and I can see options.rb where it adds the passed parameter to options[:pre_vars], but that seems to be an instance variable, and I can't figure out how to access it from my deploy script.
Solution:
The options can be accessed via #parent.variables hash, so if the command line string is testvar=thing, then #parent.variables[:testvar] has the value string.
This seems really ugly and hacky, but it works.
Edit:
Turns out it is also available locally via variables[:testvar]

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.

How to force the execution of a task in Rake, even if prereqs are met?

is there any way to force the execution of task in Rake, even if the prerequisites are already met?
I am looking for the equivalent of the --always-make option for GNU/make (http://www.gnu.org/software/make/manual/make.html#Options-Summary )
Example Rakefile:
file "myfile.txt" do
system "touch myfile.txt"
puts "myfile.txt created"
end
How would the --always-make option work:
# executing the rule for the first time creates a file:
$: rake myfile.txt
myfile.txt created
# executing the rule a second time returns no output
# because myfile.txt already exists and is up to date
$: rake myfile.txt
# if the --always-make option is on,
# the file is remade even if the prerequisites are met
$: rake myfile.txt --always-make
myfile.txt created
I am running Rake version 0.9.2.2, but I can't find any option in the --help and man pages.
If I undersand you correctly, you can manually execute the task using Rake::Task.
task "foo" do
puts "Doing something in foo"
end
task "bar" => "foo" do
puts "Doing something in bar"
Rake::Task["foo"].execute
end
When you run rake bar, you'll see:
Doing something in foo
Doing something in bar
Doing something in foo
If you use Rake::Task, it will be executed without checking any pre-requisites. Let me know if this doesn't help you.

Create a tempfile without opening it in Ruby

Is there a way to create a tempfile, without having it opened? I have to run an executable, redirect it's output to a file, and then read & parse that. Everything created by tempfile is already opened, and this triggers an error , because the file is locked.
You can also use Dir::Tmpname
Dir::Tmpname.create('your_application_prefix') { |path| puts path }
path will contain unique path
See https://github.com/ruby/ruby/blob/ruby_1_9_3/lib/tmpdir.rb#L116
I didn't get an error:
Andrew-Grimms-MacBook-Pro:~ agrimm$ irb
>> require "tempfile"
=> true
>> tempfile = Tempfile.new("temporary_file.txt", "/tmp")
=> #<File:/tmp/temporary_file.txt20110622-648-pkynjw-0>
>> tempfile.close
=> nil
>> system("echo foo > #{tempfile.path}")
=> true
>> system("cat #{tempfile.path}")
foo
=> true
>> tempfile.path
=> "/tmp/temporary_file.txt20110622-648-pkynjw-0"
>> exit
Andrew-Grimms-MacBook-Pro:~ agrimm$ cat /tmp/temporary_file.txt20110622-648-pkynjw-0
foo
Then again, the temporary file doesn't seem awfully temporary.
Does the error happen with all programs, or just a specific program? Also, can you post the code that causes the problem, and what error backtrace you get?
Is using FileUtils.touch acceptable solution? You can touch a file and delete it once you are done with whatever you want.
You may want to use pipes.
If the executable is started from your ruby program, consider using IO.popen.
If they're different processes, you can try named pipes.
The #timfjord's answer works. But if you don't need a block try:
Dir::Tmpname.create(['prefix-', '.ext']) {}
# => "/tmp/prefix-20190827-1-87n9iu.ext"

How to read an open file in Ruby

I want to be able to read a currently open file. The test.rb is sending its output to test.log which I want to be able to read and ultimately send via email.
I am running this using cron:
*/5 * * * /tmp/test.rb > /tmp/log/test.log 2>&1
I have something like this in test.rb:
#!/usr/bin/ruby
def read_file(file_name)
file = File.open(file_name, "r")
data = file.read
file.close
return data
end
puts "Start"
puts read_file("/tmp/log/test.log")
puts "End"
When I run this code, it only gives me this output:
Start
End
I would expect the output to be something like this:
Start
Start (from the reading of the test.log since it should have the word start already)
End
Ok, you're trying to do several things at once, and I suspect you didn't systematically test before moving from one step to the next.
First we're going to clean up your code:
def read_file(file_name)
file = File.open(file_name, "r")
data = file.read
file.close
return data
end
puts "Start"
puts read_file("/tmp/log/test.log")
puts "End"
can be replaced with:
puts "Start"
puts File.read("./test.log")
puts "End"
It's plain and simple; There's no need for a method or anything complicated... yet.
Note that for ease of testing I'm working with a file in the current directory. To put some content in it I'll simply do:
echo "foo" > ./test.log
Running the test code gives me...
Greg:Desktop greg$ ruby test.rb
Start
foo
End
so I know the code is reading and printing correctly.
Now we can test what would go into the crontab, before we deal with its madness:
Greg:Desktop greg$ ruby test.rb > ./test.log
Greg:Desktop greg$
Hmm. No output. Something is broken with that. We knew there was content in the file previously, so what happened?
Greg:Desktop greg$ cat ./test.log
Start
End
Cat'ing the file shows it has the "Start" and "End" output of the code, but the part that should have been read and output is now missing.
What happening is that the shell truncated "test.log" just before it passed control to Ruby, which then opened and executed the code, which opened the now empty file to print it. In other words, you're asking the shell to truncate (empty) it just before you read it.
The fix is to read from a different file than you're going to write to, if you're trying to do something with the contents of it. If you're not trying to do something with its contents then there's no point in reading it with Ruby just to write it to a different file: We have cp and/or mv to do those things for us witout Ruby being involved. So, this makes more sense if we're going to do something with the contents:
ruby test.rb > ./test.log.out
I'll reset the file contents using echo "foo" > ./test.log, and cat'ing it showed 'foo', so I'm ready to try the redirection test again:
Greg:Desktop greg$ ruby test.rb > ./test.log.out
Greg:Desktop greg$ cat test.log.out
Start
foo
End
That time it worked. Trying it again has the same result, so I won't show the results here.
If you're going to email the file you could add that code at this point. Replacing the puts in the puts File.read('./test.log') line with an assignment to a variable will store the file's content:
contents = File.read('./test.log')
Then you can use contents as the body of a email. (And, rather than use Ruby for all of this I'd probably do it using mail or mailx or pipe it directly to sendmail, using the command-line and shell, but that's your call.)
At this point things are in a good position to add the command to crontab, using the same command as used on the command-line. Because it's running in cron, and errors can happen that we'd want to know about, we'd add the 2>&1 redirect to capture STDERR also, just as you did before. Just remember that you can NOT write to the same file you're going to read from or you'll have an empty file to read.
That's enough to get your app working.
class FileLineRead
File.open("file_line_read.txt") do |file|
file.each do |line|
phone_number = line.gsub(/\n/,'')
user = User.find_by_phone_number(line)
user.destroy unless user.nil?
end
end
end
open file
read line
DB Select
DB Update
In the cron job you have already opened and cleared test.log (via redirection) before you have read it in the Ruby script.
Why not do both the read and write in Ruby?
It may be a permissions issue or the file may not exist.
f = File.open("test","r")
puts f.read()
f.close()
The above will read the file test. If the file exists in the current directory
The problem is, as I can see, already solved by Slomojo. I'll only add:
to read and print a text file in Ruby, just:
puts File.read("/tmp/log/test.log")

Resources