[英]Rails nested attributes form for polymorphic/single table inheritance associations
I am working on a form (using SimpleForm) that allows you to edit embedded associations. 我正在使用一个表单(使用SimpleForm),允许您编辑嵌入的关联。 The problem that I'm running into is that the nested models are subclasses so they are different types with potentially different fields.
我遇到的问题是嵌套模型是子类,因此它们是具有可能不同字段的不同类型。 I'm creating hidden forms for each type of model, and using JavaScript to display the form for the selected type.
我正在为每种类型的模型创建隐藏表单,并使用JavaScript显示所选类型的表单。
FYI, I'm using the following gems: 仅供参考,我使用以下宝石:
Here's a simplified example of what I have so far: 这是我到目前为止的简化示例:
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
In the console: 在控制台中:
> garage = Garage.new
> garage.vehicle = Car.new(car_field: 'something')
> garage.save!
In the form: 形式如下:
= 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()
The problem that will occur in this example is that it won't be able to render the truck_field
because Car
does not have a truck_field
method. 此示例中将出现的问题是它无法渲染
truck_field
因为Car
没有truck_field
方法。 I'm not sure how to solve this problem besides throwing out any form helpers and managing the html and field values manually. 除了抛弃任何表单助手并手动管理html和字段值之外,我不确定如何解决这个问题。 Even after much Googling, I haven't been able to find any examples of this type of form.
即使经过谷歌搜索,我也无法找到这种形式的任何例子。
How can this problem be solved in a standard, "Rails way" using existing form helpers? 如何使用现有的表单助手以标准的“Rails方式”解决这个问题?
I think I had a similar problem, however instead of a has_one
relationship, I have has_many
. 我认为我遇到了类似的问题,但是我有一个
has_many
而不是has_one
关系。
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
. 基本上我使用
cocoon
gem为每个装饰类(例如Car
或Truck
)动态添加字段,然后我使用accept_nested_attributes_for :vehicle
。 The form is built dynamically and on submit, the parameters go inside vehicle_attributes
. 表单是动态构建的,在提交时,参数在
vehicle_attributes
。
The code looks something like (updated for has_one
association): 代码看起来像(为
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'
Then inside _vehicle_fields
partial you check what object it is ( Car
or Truck
) and you render the correct fields. 然后在
_vehicle_fields
部分内部检查它是什么对象( Car
或Truck
)并渲染正确的字段。
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 我在以下网址写了一篇更长的解释: 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. 您可以尝试将Vehicle子类化为用于接受表单数据的类。 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. 这样,您可以保持
Vehicle
模型清洁。 You can also override methods in VehicleFormModel
to work like a factory, to build the correct instance when the object is being created. 您还可以覆盖
VehicleFormModel
方法以像工厂一样工作,以在创建对象时构建正确的实例。 In your controller, instantiate a VehicleFormModel instead of a Vehicle. 在您的控制器中,实例化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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.