5

これは本当に私を失望させています!:(

ユーザー モデルのネストされたモデル フォームを作成しようとしています。その中にチェックボックス リストがあり、複数のストアをチェックまたはチェック解除して、モデル スタッフィングを通じてストアを管理できます。

class Staffing < ActiveRecord::Base
  # Associations
  belongs_to :user
  belongs_to :staffable, :polymorphic => true
  belongs_to :store,     :class_name => "Store",
                         :foreign_key => "staffable_id"
end

class User < ActiveRecord::Base
  # Includes
  acts_as_authentic

  # Associations
  has_many :staffings, :dependent => :destroy
  has_many :stores, :through => :staffings

  # Nested Attributes
  accepts_nested_attributes_for :staffings, :allow_destroy => true
end

class Store < ActiveRecord::Base
  # Associations
  has_many :staffings, :as => :staffable, :dependent => :destroy
  has_many :users, :through => :staffings
end


# Users Controller
def create
  @user = User.new(params[:user])
  flash.now[:notice] = "#{@user.name} was successfully created." if @user.save
  respond_with @user
end


def update
  @user = User.find(params[:id])
  params[:user][:store_ids] ||= []
  @user.update_attributes(params[:user])
  flash.now[:notice] = "#{@user.name} was successfully updated."
  respond_with @user
end

当面の目的では、他のスタッフ可能な関連付けは無視できます。これは、最終的に Store と一緒に管理したいと考えている同様のモデルですが、このままでは困惑するので、まず第一に考えることです。

# User Form
- for store in Store.all
  %p
    = check_box_tag "user[store_ids][]", store.id, @user.stores.include?(store)
    = store.nickname

私のパラメータを次のように送信します。

{"utf8"=>"✓",
 "authenticity_token"=>"blub-blub-blub=",
 "user"=>{"login"=>"hey.buddy",
 "email"=>"test@hey.net",
 "role"=>"admin",
 "hq"=>"1",
 "password"=>"[FILTERED]",
 "password_confirmation"=>"[FILTERED]",
 "store_ids"=>["3",
 "4"]}}

そしてエラー!

Mysql2::Error: Column 'staffable_type' cannot be null: INSERT INTO `staffings` (`created_at`, `staffable_id`, `staffable_type`, `updated_at`, `user_id`) VALUES ('2010-11-17 00:30:24', 3, NULL, '2010-11-17 00:30:24', 102)

staffable_type を 'Store' として作成する必要があることはわかっていますが、一日中試してみました。

staffable_type (および id) 列を :null => false に設定していますが、DB にアクセスする前にコントローラーでこれを調整する必要があるため、これが原因ではありません。

私の作成アクションで以下が機能しないのはなぜですか:

@user.staffings.each do |s|
  s.staffable_type = 'Store'
end

また:

@user.store_ids.each do |i|
  s = @user.staffings.build
  s.staffable_type = 'Store'
  s.staffable_id = i
end

上記に似た多くのことを試しても無駄です。どんな助けでも大歓迎です。

御時間ありがとうございます!

4

1 に答える 1

4

さて、私はこれを理解しました。私はここで答えているので、いつか誰かを助けることができれば幸いですが、問題は Has Many Through と Has And Belongs To Many Associations の違いに関する基本的な見落としでした。

Has Many Through でチェックボックスまたは複数選択リストを処理する場合、関連付けによって生成される '_ids' メソッドはなく、自分で作成する必要があります。

ここで Paul Barry の記事を参照してください: http://paulbarry.com/articles/2007/10/24/has_many-through-checkboxes

ポリモーフィックなものは複雑になる可能性がありますが、本当にうまく行き詰まっている場合は、一歩下がって、それがあなたを台無しにするさらに基本的なものではないことを確認してください-私にとってはうまくいきました!

以下は、ポールのブログから変更されたコードで、ポリモーフィックに多くのスルーがある場合にこれを処理する方法について説明しています (基本的には、属性ハッシュを使用して polymorphic_type 属性を記述するだけで済みます)。

attr_accessor :store_ids
after_save :update_stores

#after_save callback to handle group_ids
def update_stores
  unless store_ids.nil?
    self.staffings.each do |staffing|
      staffing.destroy unless store_ids.include?(staffing.staffable_id.to_s)
      store_ids.delete(staffing.staffable_id.to_s)
    end 
    store_ids.each do |s|
      self.staffings.create(attributes = {:staffable_id => s, :staffable_type => 'Store'}) unless s.blank?
    end
    reload
    self.store_ids = nil
  end
end 
于 2010-11-17T15:57:52.417 に答える