Reputation: 83680
I've got something like this
class Reply < AR::Base
end
class VideoReply < Reply
def hello
p 'not ok'
end
end
class PostReply < Reply
def hello
p 'ok'
end
end
...
So when I am creating object:
# params[:reply][:type] = "VideoReply"
@reply = Reply.new(params[:reply])
How can I invoke child method (in this case VideoReply::hello
)?
UPD: I can imagine only very stupid solution:
@reply = Reply.new(params[:reply])
eval(@reply.type).find(@reply.id).hello
But it is not cool, I think :)
Upvotes: 1
Views: 822
Reputation: 211580
When you're dealing with STI-based models, you'll have problems creating them if you're not careful. Retrieving them should be done automatically so long as you use the base class to find.
What you need is to create the proper kind of model in the first place and the rest will be fine. In your model or controller define a list of valid classes:
REPLY_CLASSES = %w[ Reply VideoReply PostReply ]
Then you can use this to verify the type before creating an object:
# Find the type in the list of valid classes, or default to the first
# entry if not found.
reply_class = REPLY_CLASSES[REPLY_CLASSES.index(params[:reply][:type]).to_i]
# Convert this string into a class and build a new record
@reply = reply_class.constantize.new(params[:reply])
This should create a reply with the proper class. Methods should work as desired at this point.
Upvotes: 2