使用MongoMapper时,在编辑资源时不会检查Formtastic复选框

oli*_*nes 1 ruby-on-rails formtastic mongomapper inherited-resources

使用以下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
Run Code Online (Sandbox Code Playgroud)

我有这个表格,用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 -%>
Run Code Online (Sandbox Code Playgroud)

控制器使用Inherited Resources,编辑操作是隐式的.

使用已与之关联的服务编辑@store时,后者的复选框不会显示为已选中.

Formtastic的README警告它不正式支持MongoMapper,但它也说人们已经成功地使用了两者,我在网上看到了一些这样的例子.

我怀疑Inherited Resources也不支持它,我从Devise + Simple Form看到的,都来自同一作者,不支持MM.他们正努力在他们的宝石中使用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  
Run Code Online (Sandbox Code Playgroud)

有没有人知道与MM的冲突在哪里,无论是在Formtastic还是IR,以及hack只是为了让这些复选框检查?

Bri*_*pel 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不同.

可能使其工作的hack是向ObjectId添加一个返回self的"id"方法(Formtastic在查找to_s之前查找id).更合适的补丁是覆盖此方法https://github.com/justinfrench/formtastic/blob/master/lib/formtastic/inputs/base.rb#L104以正确地内省MongoMapper关联,以便您可以编写表单.输入:服务,它会将其转换为名为"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完全按照你在内部编写的方式进行操作,但是如果你必须以这种方式编写它以使其工作,那么它就是...... )