【问题标题】:Formtastic checkboxes not getting checked when editing resource, when using MongoMapper使用 MongoMapper 编辑资源时未检查 Formtastic 复选框
【发布时间】:2011-04-01 14:07:08
【问题描述】:

使用以下 Store 和 Service 模型,由 MongoMapper 管理:

class Store
  include MongoMapper::Document         
  key :service_ids, Array, :typecast => 'ObjectId'
  many :services, :in => :service_ids
end

class Service
  include MongoMapper::Document         
  key :name, String  
  many :stores, :foreign_key => :service_ids  
end

我有这个表格,用 Formtastic 完成的:

<%= semantic_form_for @store, :url => admin_store_path(@store), :method => :put do |form| %>
  <%= form.input :service_ids, :label => "Select Store Services", 
                               :as => :check_boxes, 
                               :collection => Service.all %>
<% end -%>

控制器使用继承资源,编辑动作是隐式的。

在编辑已关联服务的@store 时,后者的复选框不会显示为选中状态。

Formtastic's README 官方警告它不支持 MongoMapper,但它也说人们已经成功地同时使用了这两种方法,我在网上看到了一些这样的例子。

我怀疑Inherited Resources 也不支持它,从我从 Devise + Simple Form 中看到的,都来自同一作者并且不支持 MM。他们正在努力在他们的 gems 中使用 ORM 适配器,但它还没有准备好 AFAIK。

而且我已经遇到了问题,我正在覆盖更新操作以使其工作:

  def update
    store = Store.find(params[:id])    
    if store.update_attributes!(params[:store])

      flash[:notice] = 'Store was successfully updated.'
      redirect_to admin_store_path(store)
    else
      redirect_to new_store_path
    end
  end  

有谁知道与 MM 的冲突在哪里,在 Formtastic 或 IR 中,以及为了检查这些复选框而进行的黑客攻击?

【问题讨论】:

    标签: ruby-on-rails mongomapper formtastic inherited-resources


    【解决方案1】:

    很可能是 Formtastic 问题。看来问题出在这里:https://github.com/justinfrench/formtastic/blob/master/lib/formtastic/inputs/check_boxes_input.rb#L122

    Formtastic 调用@store.service_ids 来查找选定的框。 Service_ids 返回一个 ObjectId 的数组,但 Formtastic 需要一个 Store 对象的数组。如果我们遵循 Formtastic 的代码,我们会看到它尝试了几种方法来找出如何从这些 ObjectId 中获取“值”,并最终选择“to_s”(参见https://github.com/justinfrench/formtastic/blob/master/lib/formtastic/form_builder.rb#L20)。不幸的是,ObjectId 的 to_s 与您的 Store 对象的 id 不同。

    一个可能使它起作用的技巧是向 ObjectId 添加一个“id”方法,该方法返回 self(Formtastic 在查找 to_s 之前查找 id)。更合适的补丁是覆盖此方法 https://github.com/justinfrench/formtastic/blob/master/lib/formtastic/inputs/base.rb#L104 以正确内省 MongoMapper 关联,以便您可以编写 form.input :services 并将其转换为名称为“service_ids”的输入,同时仍使用服务方法你的对象。通过该更改,它仍然可以正确调用 @store.services 并找到与 Store.all 相同类型的对象并且可以正常工作。

    如果你想走这条路,Store.associations[:services] 应该让你得到 MongoMapper 的关联定义,你可以自省(参见https://github.com/jnunemaker/mongomapper/blob/master/lib/mongo_mapper/plugins/associations/base.rb)但请注意,自 0.8.6 以来,关联已经被重构了一点gem,它们现在位于分别从 Associations::Base 继承的 BelongsToAssociation、OneAssociation 和 ManyAssociation 类中。

    因此,似乎没有简单的解决方法。另一种选择是手动生成复选框。

    (旁白:我对您的更新方法有点困惑,因为我希望 IR 完全按照您在内部编写的内容进行操作,但是如果您必须以这种方式编写它才能使其正常工作,那么它就是...)

    【讨论】:

    • 很好的答案!澄清了很多我刚开始看到的东西。我想我现在可以根据您提供的路线图实施适当的补丁。非常感谢
    • re IR,我也是,但由于某种原因,#create 和 #update 都不起作用,响应将返回 200,但不会创建/更新对象。当然,当我以相反的方式设置关联(服务上的 store_ids 外键)时,就会发生这种情况。现在可能会尝试删除这些操作,以查看 IR 是否按预期工作
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-25
    • 1970-01-01
    • 2017-02-19
    • 1970-01-01
    • 1970-01-01
    • 2021-09-25
    • 1970-01-01
    相关资源
    最近更新 更多