Am I using -s + local variables incorrectly here?
task :log do
lines ||= 100
rails_env ||= 'production'
# lines = configuration.variables[:lines] || 100
# rails_env = configuration.variables[:rails_env] || 'production'
env = ENV['RAILS_ENV'] || 'production'
run "tail -n #{lines} #{deploy_to}/#{shared_dir}/log/
#{rails_env}.log" do |ch, stream, out|
puts out
end
end
Cheers
Nic
1. Capistrano variables are not local variables, but are actually
messages rerouted via method_missing.
2. Ruby auto-vivifies local variables, which can interfere
method_missing calls.
If in Ruby you do:
x = x || 5
The interpreter will see, before executing the line, that it sets a
local variable. Thus, it will first create that variable with a value
of nil.
In your task, then:
lines ||= 100
Ruby cannot know that method_missing will handle that 'lines'
message, so it assumes it is a local variable and dutifully creates a
new local variable with a value of nil, instead of calling
method_missing and getting the value you expect.
I hope that makes sense. Your solution accessing the variables hash
directly is what I'd recommend.
- Jamis
- Ruby/Rails/Javascript/Web2.0
skype: nicwilliams
(p) +61 7 3102 3237 (Finds me anywhere in the world, via Skype)
(m) +4673 768 1389 (Swedish mobile)
(f) +61 7 3305 7572 (sends fax to my email)
Björnsonsgatan 153, 16 844 Bromma, Sweden
> That's the odd part, the lines = lines || 100 doesn't seem to work
> either.
Right, it won't, because it is semantically identical to "lines ||=
100".
> BUT,
>
> lines = lines || foobar || 100
>
> works if I pass -s foobar=10, so lines might be a variable defined
> elsewhere perhaps.
Right, because foobar isn't being assigned to, Ruby won't autovivify
a local variable by that name, so when it comes time to evaluate
'foobar', the method_missing hook gets called for it.
> At least I now know how it works, so I'll just keep trying variable
> names til it works in future :)
Yeah, this is a nasty gotcha, unfortunately. :( It would be fixed if
I actually defined a method for every time a variable is
created...but I'm not sure that I like that.
- Jamis
What I do is something like this:
task :log do
run "tail -n #{lines || 100} #{deploy_to}/#{shared_dir}/log/
#{rails_env || ENV["RAILS_ENV"] || "production"}.log" do
|ch, stream, out|
puts out
end
end
Not only does it work great with the -s option, it has the benefit of
being much shorter codewise.
run "tail -n #{lines || 100} #{shared_path}/log/...
~Wayne