Флажки Formtastic не проверяются при редактировании ресурса при использовании MongoMapper - PullRequest
1 голос
/ 01 апреля 2011

Со следующими моделями 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 со службами, уже связанными с ним, флажки для последних не отображаются как отмеченные.

README от Formtastic предупреждает, что официально он не поддерживает 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  

Кто-нибудь знает, где конфликт с MM, в Formtastic или IR, и взлом, чтобы проверить эти флажки?

1 Ответ

6 голосов
/ 03 апреля 2011

Скорее всего, проблема 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). К сожалению, to_s ObjectId не совпадает с идентификатором ваших объектов Store.

Хак, который может заставить его работать, состоит в добавлении метода «id» в ObjectId, который возвращает self (Formtastic ищет id, прежде чем ищет to_s). Более подходящим патчем было бы переопределить этот метод 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 гем, теперь они находятся в отдельных классах BelongsToAssociation, OneAssociation и ManyAssociation, каждый из которых наследуется от Associations :: Base.

Так что не похоже, что есть простое исправление. Другой вариант - создать свои флажки вручную.

(Кроме того: меня немного смущает ваш метод обновления, потому что я ожидаю, что IR будет делать именно то, что вы написали внутри, но если бы вам пришлось писать это таким образом, чтобы заставить его работать, так ...)

...