I have tried the using backticks / system / %x but get the following
error:
./urls2.rb:41:in ``’: No such file or directory - t1.showURL
(Errno::ENOENT)
from ./urls2.rb:41:in block in <main>' from ./urls2.rb:40:ineach’
from ./urls2.rb:40:in `’
Beware that eval can execute any ruby code, which in turn can execute any shell code, e.g. via system(), so is dangerous if the data could
have come from an untrusted source.
Normally I would recommend using send() for something like this:
meth = :showURL # dynamic method name in variable
obj.send(meth) # call that method
However what’s dynamic in your case is that you’re trying to pick one of
12 local variables called “t1” to “t12”.
This is almost certainly the wrong design, as local variables aren’t
really supposed to be used in this way.
I’m guessing that earlier on you had 12 lines of code to assign to those
12 variables? What you probably want is an Array or Hash instead. Then
(a) you can create those 12 instances in better ways (e.g. in a loop);
and
(b) you can do your lookup directly without any eval tricks:
t = []
t[0] = …
t[1] = …
… later …
(0…11).each do |i|
t[i].showURL
end
Then you’ll find there’s an even cleaner way to iterate:
eval() works and can be used without thinking that it is the wrong
choice for the given problem.
It would be better to move from t1, t2, … t12 to an array t[1…12] (or
t[0…11]) and then use each on that. While legit, eval shows a bad
design
underneath that should be fixed instead.
Thank you all for the additional feedback and help. Whilst eval is
working, I will explore these other options as they sound like
potentially better practise.
It does not matter how they are “supposed” to be used.
Ruby does not impose it on him.
eval() is a perfectly legit way to solve the problem description he has
given.
It will solve the problem, yes, but in not using an array, you lose
the benefits of flexibility. Local variables with numbered suffixes is
just reinventing something you already have as part of the language.
Using eval instead of a basic language construct would be a pretty bad
habit to get into.
eval() works and can be used without thinking that it is the wrong
choice for the given problem.
It is the wrong choice, not because of security risks, but because it
means
you are using your binding as a hash, instead of using a hash as a hash
(though in this case, an array is probably the better choice).
For OP, here is an example of what it might look like
fyi, Rubyists usually try to pick more meaningful names
in this case, ts represents the plural of t
ts = [ …init code… ]
a direct mapping of your original idea
(0…12).each do |i|
t = ts[i]
puts t.showURL # also, convention in Ruby is snake_case not cameCase
end
probably what you really want
ts.each { |t| puts t.showURL }
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.