Ruby on rails 多态/单表继承关联的Rails嵌套属性表单
我正在开发一个表单(使用SimpleForm),它允许您编辑嵌入的关联。我遇到的问题是,嵌套模型是子类,因此它们是不同的类型,具有潜在的不同字段。我正在为每种类型的模型创建隐藏表单,并使用JavaScript显示所选类型的表单 仅供参考,我正在使用以下宝石:Ruby on rails 多态/单表继承关联的Rails嵌套属性表单,ruby-on-rails,ruby-on-rails-3,mongoid,nested-attributes,Ruby On Rails,Ruby On Rails 3,Mongoid,Nested Attributes,我正在开发一个表单(使用SimpleForm),它允许您编辑嵌入的关联。我遇到的问题是,嵌套模型是子类,因此它们是不同的类型,具有潜在的不同字段。我正在为每种类型的模型创建隐藏表单,并使用JavaScript显示所选类型的表单 仅供参考,我正在使用以下宝石: 轨道3.2 蒙哥德 单纯形 以下是我迄今为止所拥有的一个简化示例: class Garage include Mongoid::Document embeds_one :vehicle accepts_nested_attr
- 轨道3.2
- 蒙哥德
- 单纯形
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
形式如下:
= 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\u字段
方法,因此无法渲染truck\u字段。除了扔掉任何表单助手和手动管理html和字段值之外,我不知道如何解决这个问题。即使在谷歌搜索了很多次之后,我仍然找不到这种形式的任何例子
如何使用现有的表单帮助程序以标准的“Rails方式”解决此问题?这是直接将表单映射到模型并不理想的情况之一。我认为用户填充表单映射和持久性模型实例是两个非常不同的概念
您可以尝试将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
车辆等级FORMMODEL
我想我也有类似的问题,但是我没有一个有一个
关系,而是有很多
基本上,我使用cocoon
gem为每个装饰类(例如Car
或Truck
)动态添加字段,然后我接受:vehicle的嵌套属性。表单是动态生成的,在提交时,参数进入车辆属性
代码看起来类似(更新为有一个关联):
然后在\u vehicle\u字段
partial中检查它是什么对象(Car
或Truck
),并渲染正确的字段
我认为这很有效,这正是我所需要的。希望能有帮助
我在:上写了一个较长的解释:也许这会有帮助:(但不确定)@jethroo谢谢,但不幸的是,答案涵盖了我的代码示例中已有的所有内容。他们省略了为不同型号使用不同字段的最后一步。如果基础文档没有任何公共字段,我会考虑创建两组字段,一组用于卡车(带有新的空白实例),另一组用于汽车,在车辆类型开关上设置\u destroy
,然后创建一个新的卡车文档。如果这对您不起作用或者看起来太不雅观,另一种选择是将所有字段移动到基本文档,因为如果您将汽车转换为卡车,我相信mongoid不会取消设置汽车字段,并且您在db中的文档将有比它需要的更多的字段。切换文档类型的正确方法是分配新文档,而不是编辑现有的IMHO。@rubish很好的提示,我也发现了这一点。我也有一个embedded\u many
关联,因此解决方案有点不同。我认为embed\u many比embed one相对容易处理,因为您可以使用嵌套属性的现有机制在一次调用中销毁旧文档并创建新文档。但是,使用Embeddes_one,您需要创建新文档并覆盖现有文档,还需要确保在销毁文档(如删除s3文件)时进行任何清理,并妥善处理。我看到一个Railscast可能会介绍这一点:有趣的想法。不过我想看到更多的HTML/JavaScript实现。我又看了一遍RailsCast,它非常全面。我已经看过了屏幕。我指的是这种表单的细节,它根据您之前选择的字段创建不同的字段。
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
# _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'