San Diago
San Diago

Reputation: 1050

How to access and submit related polymorphic models in the same form, in Rails?

Suppose I have 3 models, Car, Motorcycle and Truck, and for each I have to enter a bunch of stuff, such as a list of known previous owners, traffic tickets, license plates, etc. So I created a model for each (PreviousOwners, PreviousPlates, etc) and set up polymorphic associations for the related models.

The problem is, how can I enter all of that using just one form, kind of like this:

Car #123

Known previous owners:
Jason Jazz
Brian Bass [add another]

Known previous license plates:
12345
67890 [add another]

Current status:
Cleared 
(this is a dropdown select menu, CurrentStatus is also a polymorphic association, but with predefined values.)

etc

This is proving to be a bitch, way beyond my level of expertise (newbie here). The resources are not nested and almost everything I find on multiple models is for nested resources, and nothing seems to apply to polymorphic associations.

(This is just an example, I know ideally I should have a Vehicle model with 'Car', etc, as categories, but it's just to illustrate the real need for polymorphic models in my case.)

Thanks.

Upvotes: 3

Views: 3210

Answers (6)

Stewart Johnson
Stewart Johnson

Reputation: 14449

You can avoid this and make things a bit simpler by introducing a Vehicle model. The Vehicle model can have all your PreviousOwners, PreviousPlates, etc collections, and then your Truck, Car and Motorcycle models can has_one Vehicle.

Upvotes: 1

Preston Marshall
Preston Marshall

Reputation: 1195

You can use the new nested attributes in Rails 2.3, but there is a certain way you have to write it to make it work. The trick is that you need to create the actual polymorphic object, then build the class that has the belongs to polymorphic clause in it. This is an example I found at Ryans Scraps, posted by a user named: Superslau (I've cleaned it up a good bit for here):

This feature is really awesome. I have implemented this with polymorphic associations, and it works!

 class Task < ActiveRecord::Base
   has_many :assets, :dependent=>:destroy
   accepts_nested_attributes_for :assets, :allow_destroy => true
   belongs_to :workable, :polymorphic => true
 end



 class Upload < ActiveRecord::Base
   has_one :task, :as => :workable, :dependent=>:destroy
   accepts_nested_attributes_for :task, :allow_destroy => true 
 end

Upload is a kind of task. All tasks can have one or more assets uploaded.

I took me a while to figure out that I should use the Upload model as the parent. So in one form, I can create an upload, and it’s corresponding task entry, along with a file upload.

in my controller:

 def new   
  @upload = Upload.new  
  @upload.task = Task.new  
  @upload.task.assets.build 
 end 

Don’t worry if that doesn’t make any sense, I just wanted to let people know that accepts_nested_attributes_for works just fine with polymorphic associations. Thanks Eloy!

Upvotes: 2

Ole Spaarmann
Ole Spaarmann

Reputation: 16749

Maybe the PresenterPattern is helpfull too:

http://blog.jayfields.com/2007/03/rails-presenter-pattern.html

The basic idea is to create a presenter which acts like a model and processes all the incoming data from your form and distributes it to the models. This way it's also easy to create multiple instances of lets say PreviousOwner and attach it to Car.

Check the link out!

Upvotes: 2

zaius
zaius

Reputation: 6409

If the car/motorcycle/truck models are identical, you should add a type column to your vehicle model. If they're not, you should use STI (single table inheritance).

But yeah, need to see your models first before I can give you code.

Upvotes: 1

btw
btw

Reputation: 7164

There is a RailsCast on Complex Forms that might help you with building a single form from multiple models.

Upvotes: 1

Hemant Kumar
Hemant Kumar

Reputation: 2018

Very well, nested form builders doesn't have to be associated with nested resources AFAIK.Can you post your models code as well?

Upvotes: 1

Related Questions