1

使用以下 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 的 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 中,以及为了检查这些复选框而进行的黑客攻击?

4

1 回答 1

6

很可能是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 不同。

一个可能使它起作用的技巧是向返回 self 的 ObjectId 添加一个“id”方法(Formtastic 在查找 to_s 之前查找 id)。更合适的补丁是覆盖此方法https://github.com/justinfrench/formtastic/blob/master/lib/formtastic/inputs/base.rb#L104以正确内省 MongoMapper 关联,以便您可以编写表单。 input :services ,它会将其转换为名称为“service_ids”的输入,同时仍使用对象的 services 方法。通过该更改,它仍然可以正确调用 @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 以来,关联已经被重构了一点,它们现在位于单独的类 BelongsToAssociation、OneAssociation 和 ManyAssociation 中,每个类都继承自 Associations::Base。

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

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

于 2011-04-03T02:21:23.473 回答