Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 多态/单表继承关联的Rails嵌套属性表单_Ruby On Rails_Ruby On Rails 3_Mongoid_Nested Attributes - Fatal编程技术网

Ruby on rails 多态/单表继承关联的Rails嵌套属性表单

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

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

仅供参考,我正在使用以下宝石:

  • 轨道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'