Rails nested attributes form for polymorphic/single table inheritance associations

我怕爱的太早我们不能终老 提交于 2019-11-30 22:24:10

I think I had a similar problem, however instead of a has_one relationship, I have has_many.

Basically I used cocoon gem to dynamically add fields for each decorated class (such as Car or Truck) and then I accept_nested_attributes_for :vehicle. The form is built dynamically and on submit, the parameters go inside vehicle_attributes.

The code looks something like (updated for has_one association):

# _form.html.haml

= simple_form_for @garage, :html => { :multipart => true } do |f|

  = f.simple_fields_for :vehicles do |vehicle|
    = render 'vehicle_fields', :f => item
    = link_to_add_association 'Add a Car', f, :vehicles, :wrap_object => Proc.new { |vehicle| vehicle = Car.new }
    = link_to_add_association 'Add a Truck', f, :vehicles, :wrap_object => Proc.new { |vehicle| vehicle = Truck.new }

= f.button :submit, :disable_with => 'Please wait ...', :class => "btn btn-primary", :value => 'Save' 

Then inside _vehicle_fields partial you check what object it is (Car or Truck) and you render the correct fields.

I think this works quite good, and was exactly what I needed. Hope it helps.

I wrote a longer explanation at: http://www.powpark.com/blog/programming/2014/05/07/rails_nested_forms_for_single_table_inheritance_associations

This is one of those situations where directly mapping a form to a model is not ideal. I think a user-filled form map and a persistence model instance are two very distinct concepts.

You might try subclassing Vehicle into a class that is used to accept form data. Then mix in all the extra code you need to handle what is specific to the form. This way, you keep your Vehicle model clean. You can also override methods in VehicleFormModel to work like a factory, to build the correct instance when the object is being created. In your controller, instantiate a VehicleFormModel instead of a Vehicle.

class VehicleFormModel < Vehicle
  include Car::FormModel
  include Truck::FormModel

  def self.build
    # Use a form field to handle specifics for each type,
    # delegating to the mixed in FormModel as needed
  end

end

class Car < Vehicle
  module FormModel
    def self.included(base)
      base.class_eval do
        field :car_field
        attr_accessible :car_field
      end
    end
  end
end
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!