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?
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
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.
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