I saw in the pickaxe there’s a way to call methods dynamically, with
send(“method_name”):
“test”.send(“length”) # 4
What I want to do is set a variable this way. Is it possible?
I’m working on a translation tool for a website. rows returned
are of the form:
[“id”, “language”, “value”]
the value of the language field is the identical to the member variable
that will contain the row (wrapped in an object actually).
I thought of something like this:
class Term
attr :query, :fr, :nl, :en
def initialize(dbh, id) @query = "select * from translations where id=’#{id}’"
dbh.select_all(query) do |row|
self.send(row[1].to_s)=Translation.new(row)
end
end
def get_french() @fr.value
end
end
But that isn’t accepted.
Does anyone have the solution?
I saw in the pickaxe there’s a way to call methods dynamically, with
send(“method_name”):
“test”.send(“length”) # 4
What I want to do is set a variable this way. Is it possible?
I’m working on a translation tool for a website. rows returned
are of the form:
[“id”, “language”, “value”]
the value of the language field is the identical to the member variable
that will contain the row (wrapped in an object actually).
I thought of something like this:
class Term
attr :query, :fr, :nl, :en
def initialize(dbh, id) @query = “select * from translations where id=‘#{id}’”
dbh.select_all(query) do |row|
self.send(row[1].to_s)=Translation.new(row)
end
end
def get_french() @fr.value
end
end
But that isn’t accepted.
Does anyone have the solution?
class C
def initialize @a,@b=10,20
end
end
=> nil
ary=[‘a’,‘b’]
=> [“a”, “b”]
c=C.new
=> #<C:0x2810628 @b=20, @a=10>
c.send(“a”,10)
NoMethodError: undefined method a' for #<C:0x2810628 @b=20, @a=10> from (irb):8:in send’
from (irb):8
class C
def initialize @a,@b=10,20
end
attr_accessor :a, :b
end
=> nil
c.send(“a”,10)
ArgumentError: wrong number of arguments(1 for 0)
from (irb):15:in a' from (irb):15:in send’
from (irb):15
c.send(“a”+“=”,10)
=> 10
c.a
=> 10
you may even use instance_eval(“@a=”+value.to_s)
···
il Sun, 18 Jan 2004 18:26:22 +0100, Bauduin Raphael rb@raphinou.com ha scritto::
I saw in the pickaxe there’s a way to call methods dynamically, with
send(“method_name”):
“test”.send(“length”) # 4
What I want to do is set a variable this way. Is it possible?
Using the following
class Q
attr_accessor :field
end
q = Q.new
here are some times for looping 1000000 times setting the index:
i.e. 1.upto(1000000){|i| }
q.send(“field=”, i) took 2.203 seconds
q.send(:field=, i) took 1.251 seconds
q.instance_eval{field = i} took 4.187 seconds
q.instance_variable_set “@field”, i took 2.032 seconds
q.instance_variable_set :@field, i took 1.072 seconds
q.field = i took 0.921 seconds
P.S. These timings are for the PragProg installer
ruby 1.8.0 (2003-08-04) [i386-mswin32]
Walt
···
Walter Szewelanczyk
IS Director
M.W. Sewall & CO. email : walter@mwsewall.com
259 Front St. Phone : (207) 442-7994 x 128
Bath, ME 04530 Fax : (207) 443-6284
Be aware that this only works when “value” has valid string
representation that can be reliably converted back to an object. And
then you only get a copy, not the original object.
The following will work with arbitrary objects …
obj.instance_eval(“lambda { |v| @a = v }”).call(value)
At this point you must be thinking: “Why don’t I just use
instance_variable_set?”
class Term
attr :query, :fr, :nl, :en
def initialize(dbh, id) @query = “select * from translations where id=‘#{id}’”
dbh.select_all(query) do |row|
instance_variable_set “@”+row[1], Translation.new(row)
end
end
def get_french() @fr.value
end
end
Be aware that this only works when “value” has valid string
representation that can be reliably converted back to an object. And
then you only get a copy, not the original object.
The following will work with arbitrary objects …
obj.instance_eval(“lambda { |v| @a = v }”).call(value)
Well, you can do it simpler, even if you want to use instance_eval. No
need for a lambda:
irb(main):001:0> class Foo
irb(main):002:1> def test(obj)
irb(main):003:2> instance_eval(“@x=obj”)
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0> f=Foo.new
=> #Foo:0x10197f08
irb(main):007:0> f.test “fff”
=> “fff”
irb(main):008:0> f
=> #<Foo:0x10197f08 @x=“fff”>
irb(main):009:0> f.test “xx”
=> “xx”
irb(main):010:0> f
=> #<Foo:0x10197f08 @x=“xx”>
irb(main):011:0> x=“hu!”
=> “hu!”
irb(main):012:0> f.instance_eval “@y=x”
=> “hu!”
irb(main):013:0> f
=> #<Foo:0x10197f08 @x=“xx”, @y=“hu!”>
irb(main):014:0>
At this point you must be thinking: “Why don’t I just use
instance_variable_set?”
I’d love to see the answer to this question you’d suggest. :-))