我正在开发一个允许您编辑嵌入关联的表单(使用SimpleForm)。我遇到的问题是,嵌套模型是子类,所以它们是不同的类型,具有潜在的不同字段。我为每种类型的模型创建隐藏表单,并使用JavaScript显示所选类型的表单。
仅供参考,我正在使用以下宝石:
- 轨道3.2
- Mongoid
- SimpleForm
以下是我迄今为止所拥有的一个简化示例:
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!
形式:
= 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()
本例中出现的问题是,由于Car
没有truck_field
方法,因此无法呈现truck_field
。除了抛出任何表单助手和手动管理html和字段值之外,我不知道如何解决这个问题。即使在谷歌上搜索了很多,我也找不到任何这种形式的例子
如何使用现有的表单助手在标准的"Rails方式"中解决这个问题?
我想我也遇到过类似的问题,但我有has_many
,而不是has_one
关系。
基本上,我使用cocoon
-gem为每个装饰类(如Car
或Truck
)动态添加字段,然后使用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
部分中,检查它是什么对象(Car
或Truck
),并渲染正确的字段。
我认为这很有效,正是我所需要的。希望能有所帮助。
我写了一个更长的解释: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