Rails嵌套属性表单用于多态/单表inheritance关联

我正在使用一个表单(使用SimpleForm),允许您编辑嵌入的关联。 我遇到的问题是嵌套模型是子类,因此它们是具有可能不同字段的不同类型。 我正在为每种类型的模型创建隐藏表单,并使用JavaScript显示所选类型的表单。

仅供参考,我使用以下gem:

  • Rails 3.2
  • Mongoid
  • 简单的forms

这是我到目前为止的简化示例:

class Garage include Mongoid::Document embeds_one :vehicle accepts_nested_attributes_for :vehicle end class Vehicle include Mongoid::Document embedded_in :garage attr_accessible :_type end class Car < Vehicle field :car_field attr_accessible :car_field end class Truck < Vehicle field :truck_field attr_accessible :truck_field end 

在控制台中:

 > garage = Garage.new > garage.vehicle = Car.new(car_field: 'something') > garage.save! 

forms如下:

 = simple_form_for @garage do |f| = f.input :vehicle do |vehicle_form| = vehicle_form.input :_type, collection: ['Car', 'Truck'] %span.hide{data:{fields-for:'Car'}} = vehicle_form.input :car_field %span.hide{data:{fields-for:'Truck'}} = vehicle_form.input :truck_field :coffeescript $('#garage_vehicle_attributes__type').change -> type = $(@).find('option:selected').val() $('[data-fields-for="' + type + '"]').show() 

此示例中将出现的问题是它无法渲染truck_field因为Car没有truck_field方法。 除了丢弃任何表单助手并手动管理html和字段值之外,我不确定如何解决这个问题。 即使经过谷歌搜索,我也无法找到任何这种forms的例子。

如何使用现有的表单助手以标准的“Rails方式”解决这个问题?

我认为我遇到了类似的问题,但是我有一个has_many而不是has_one关系。

基本上我使用cocoon gem为每个装饰类(例如CarTruck )动态添加字段,然后我使用accept_nested_attributes_for :vehicle 。 表单是动态构建的,在提交时,参数在vehicle_attributes

代码看起来像(为has_one关联更新):

 # _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' 

然后在_vehicle_fields部分内部检查它是什么对象( CarTruck )并渲染正确的字段。

我认为这很有效,而且正是我所需要的。 希望能帮助到你。

我在以下url写了一篇更长的解释: http : //www.powpark.com/blog/programming/2014/05/07/rails_nested_forms_for_single_table_inheritance_associations

这是直接将表单映射到模型的情况之一并不理想。 我认为用户填写的表单映射和持久性模型实例是两个截然不同的概念。

您可以尝试将Vehicle子类化为用于接受表单数据的类。 然后混合使用所需的所有额外代码来处理表单特有的内容。 这样,您可以保持Vehicle模型清洁。 您还可以覆盖VehicleFormModel方法以像工厂一样工作,以在创建对象时构建正确的实例。 在您的控制器中,实例化VehicleFormModel而不是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