Pergunta

Este está realmente me derrubando! :(

Estou tentando criar um formulário de modelo aninhado para o meu modelo de usuário com uma lista de seleção, onde várias lojas podem ser verificadas ou desmarcadas para administrar as lojas por meio do pessoal do modelo.

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

Para os propósitos em questão, a outra associação de equipe pode ser ignorada. É um modelo semelhante que eu gostaria de administrar ao lado da loja, mas a primeira coisa é a primeira, já que estou tão perplexo como é.

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

Envia meus parâmetros como tal:

{"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"]}}

E então erro!

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)

Eu sei que tenho que criar Staffable_type como 'loja', mas tenho tentado o dia todo-o que é o truque?

Eu tenho as colunas Staffable_type (e ID) definidas como: null => false, mas essa não pode ser a causa disso, pois isso precisa ser endireitado no controlador antes de atingir o banco de dados de qualquer maneira.

Por que o abaixo não funciona na minha ação de criação:

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

ou:

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

Se estiver tentando muitas coisas semelhantes às acima sem sucesso. Qualquer ajuda será extremamente apreciada.

Obrigado pelo seu tempo!

Foi útil?

Solução

Ok, eu descobri isso. Estou respondendo aqui para que eu possa ajudar alguém algum dia, mas o problema foi uma supervisão básica sobre a diferença entre muitas e pertencem a muitas associações.

Você deseja lidar com caixas de seleção ou listas de múltiplas selecionas em A muitas, não existe um método '_ids' gerado para você pela associação e precisa escrever uma por si mesmo.

Veja o artigo de Paul Barry aqui:http://paulbarry.com/articles/2007/10/24/has_many-through-checkboxes

As coisas polimórficas podem ser complicadas, mas se você estiver preso, talvez dê um passo atrás e certifique-se de que não seja algo ainda mais básico que está bagunçando você- funcionou para mim!

Abaixo está o código modificado no blog de Paul sobre como lidar com isso se você estiver lidando com um polimórfico tem muitos (basicamente você só precisa usar o hash dos atributos e escrever seu atributo 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 
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top