Hi,
I have a class Page with attribute ‘title’. I want Project objects to
call Page methods when they don’t find the called method. If the method
is not found whithin Page, super is called. For example, I can write:
p = Project.first
p.title #which calls page.title (it works)
Here is my code:
class Project < AR::Base
def method_missing(method_name, *args)
if page.respond_to?(method_name)
a = page.send(method_name, *args)
elsif respond_to?(method_name)
a = send(method_name, *args)
else
super
end
return a
end
end
It works fine with p.title. But if I do this:
p.respond_to :title_before_type_cast
=> true
p.title_before_type_cast
I get a SystemStackError…
I don’t understand why respond_to? returns true AND
p.send(:title_before_type_cast) calls method_missing at the same time?
Thanks!
Sorry, I made a mistake.
Actually, Project has the attribute ‘mission’.
p.title_before_type_cast
=> “Page title”
p.mission
=> “Project mission”
p.mission_before_type_cast
=> SystemStackError…
So, p.respond_to?(:mission_before_type_cast) returns true AND
p.send(:mission_before_type_cast) that calls method_missing at the same
time?
I hope it is not so confusing.
Thanks
On 17 Jul 2008, at 02:41, Wahid L. wrote:
Because some activerecord methods are generated on the fly by method
missing. respond_to? returns true because if you were to call the
method it wouldn’t raise NoMethodError or anything like that
Fred
Hi –
On Thu, 17 Jul 2008, Frederick C. wrote:
I don’t understand why respond_to? returns true AND
p.send(:title_before_type_cast) calls method_missing at the same time?
Because some activerecord methods are generated on the fly by method missing.
respond_to? returns true because if you were to call the method it wouldn’t
raise NoMethodError or anything like that
respond_to? actually also generates the methods on the fly.
t = Team.find(:first)
=> #<Team id: 277401923, name: “Persuaders”, mascot: “Cat”,
created_at: “2008-07-16 00:23:09”, updated_at: “2008-07-16 00:23:09”>
t.methods.grep(/mascot/)
=> []
t.respond_to?(:mascot)
=> true
t.methods.grep(/mascot/)
=> [“mascot?”, “mascot”, “mascot=”]
Like method_missing, it does this whether or not its argument is one
of the column attributes. Using a new session and a new t:
t.methods.grep(/mascot/)
=> []
t.respond_to?(:blah)
=> false
t.methods.grep(/mascot/)
=> [“mascot”, “mascot=”, “mascot?”]
In the default, out-of-the-box case, respond_to? doesn’t necessarily
predict whether NoMethodError will be raised:
class C
def method_missing(m)
if /exists/.match(m.to_s)
puts “That method will be treated as existent!”
end
end
end
c = C.new
c.this_sort_of_exists # “That method…”
print "Do I respond to :this_sort_of_exists?
puts c.respond_to?(:this_sort_of_exists) # false
David
–
Rails training from David A. Black and Ruby Power and Light:
Intro to Ruby on Rails July 21-24 Edison, NJ
Advancing With Rails August 18-21 Edison, NJ
See http://www.rubypal.com for details and updates!
On Thu, 17 Jul 2008, David A. Black wrote:
print "Do I respond to :this_sort_of_exists?
Whoops, add " at end of that line. (The code actually is
tested; I deleted the " in the email in the course of adding comments

David
–
Rails training from David A. Black and Ruby Power and Light:
Intro to Ruby on Rails July 21-24 Edison, NJ
Advancing With Rails August 18-21 Edison, NJ
See http://www.rubypal.com for details and updates!
Thanks guys for the replies. It helped me understand some behaviours I
found pretty strange.
I realized that my code had a contradiction that raised the
SystemStackError.
class Project < AR::Base
def method_missing(method_name, *args)
if page.respond_to?(method_name)
a = page.send(method_name, *args)
elsif respond_to?(method_name)
a = send(method_name, *args) #calls back method_missing
else
super
end
return a
end
end
You can’t call a missing method inside method_missing, and repond_to? on
that method doesn’t have sens since it is supposed to me missing in the
first place.
I also realized that some attributes were found due to some other code I
had in a module.
New simplified method_missing:
class Project < AR::Base
def method_missing(method_name, *args)
if page.respond_to?(method_name)
a = page.send(method_name, *args)
else
super #looks for the method in AR::Base or raises NoMethodError
end
return a
end
end
Wahid