Topic: saving, polymorphism, and repetition

I've been experimenting with polymorphic relations a little, and so far have got a working voting system for multiple models. The thing that gets me itchy, and that I dont seem to find examples about, is what the best practice would be for storing results into the table.

so, as I have votes from multiple models, that all contain the same reocurring values, the save action looks pretty much the same for each controller. So far I've been driven to write a vote action in each controller I wanted the function in, because it needs to know the model associated before saving, but this is terribly repetitive, and I'd really like to end up with a votes controller with only one save action, maybe by submitting the model name from the vote form to the action along the vote itself? Is this even in good practice or is there a better way that I'm not aware of?

Re: saving, polymorphism, and repetition

sgr wrote:

I'd really like to end up with a votes controller with only one save action, maybe by submitting the model name from the vote form to the action along the vote itself? Is this even in good practice or is there a better way that I'm not aware of?

I have done this in the past and didn't have any problems with it. The primary thing you need to be concerned with is security, as this allows someone to input any class name they want.

Railscasts - Free Ruby on Rails Screencasts

Re: saving, polymorphism, and repetition

so there shouldnt be any problem submitting the classname as a part of the form, as if I understand it correctly, the find method will just fail before the save with a non-existant classname, and in the worst case they'll just end up voting for a different model's child than was intended.
I could limit this in the vote model with a validation on voteable_type tho, right? to restrict votes being cast on models that are not intended to be voted on, thus not leaving any stray orphans in the db.

Re: saving, polymorphism, and repetition

sgr wrote:

I could limit this in the vote model with a validation on voteable_type tho, right? to restrict votes being cast on models that are not intended to be voted on, thus not leaving any stray orphans in the db.

Yep, that's probably how I would do it if you are concerned about it. Seeing if the model responds to "votes" is probably good enough. Or if you are doing custom_model.votes.build(params[:vote]) this should automatically result in an error if the given class doesn't support votes.

Last edited by ryanb (2006-11-27 14:33:57)

Railscasts - Free Ruby on Rails Screencasts

Re: saving, polymorphism, and repetition

I just stumbled upon a problem with submitting the model name as a part of the form, for some reason I cant do the following
(results in a LocalJumpError - no block given)

blinkyeyes = params[:theonemodel]
mydad = blinkyeyes.find(params[:id])

am I missing something here, or cant I use the params directly like this?
Will I have to loop thru all the appliable modelnames like
(this one does work)
if params[:theonemodel]=="SomeModelName"
mydad = SomeModelName.find(params[:id])
end

in order to be able to do
vote = mydad.votes.build(params[:vote])
vote.save

also, is there an easy way to get the classname in view code, for example if I'm listing a profile_comment , or will I just be writing these by hand in a hidden_field_tag ?

Re: saving, polymorphism, and repetition

You can do this to fetch the class:

model_class = params[:theonemodel].constantize
some_model = model_class.find(params[:id])

sgr wrote:

is there an easy way to get the classname in view code

It depends on how the class/model is referenced. If you have a given model you can fetch the class like this.

@foo.class.to_s

Railscasts - Free Ruby on Rails Screencasts

Re: saving, polymorphism, and repetition

perfect, everything seems to be working now thanks to the great help wink