Obtendo fields_for e accepts_nested_attributes_for ao trabalho com um relacionamento belongs_to
-
19-09-2019 - |
Pergunta
Eu não consigo obter uma forma aninhada para gerar em um trilhos vista para um relacionamento belongs_to
usando a nova instalação accepts_nested_attributes_for
do Rails 2.3. I fez check-out muitos dos recursos disponíveis e parece que meu código deve estar trabalhando, mas explode fields_for
em mim, e eu suspeito que ele tem algo a ver com a forma como eu tenho os modelos aninhados configurados.
O hit de erro I é comum que pode ter muitas causas:
'@account[owner]' is not allowed as an instance variable name
Aqui estão os dois modelos envolvidos:
class Account < ActiveRecord::Base
# Relationships
belongs_to :owner, :class_name => 'User', :foreign_key => 'owner_id'
accepts_nested_attributes_for :owner
has_many :users
end
class User < ActiveRecord::Base
belongs_to :account
end
Talvez este é o lugar onde eu estou fazendo isso 'rong', como uma conta pode ter um 'proprietário', e pode 'utilizadores', mas um usuário só tem uma 'conta', com base na chave account_id modelo de usuário.
Este é o código vista em new.html.haml que explode em mim:
- form_for :account, :url => account_path do |account|
= account.text_field :name
- account.fields_for :owner do |owner|
= owner.text_field :name
E este é o código do controlador para a nova ação:
class AccountsController < ApplicationController
# GET /account/new
def new
@account = Account.new
end
end
Quando tento carga / conta / nova recebo a seguinte exceção:
NameError in Accounts#new
Showing app/views/accounts/new.html.haml where line #63 raised:
@account[owner] is not allowed as an instance variable name
Se eu tentar usar o método misterioso 'construir', ele apenas bombas no controlador, talvez por causa de construção é apenas para relações multi-gravação:
class AccountsController < ApplicationController
# GET /account/new
def new
@account = Account.new
@account.owner.build
end
end
You have a nil object when you didn't expect it!
The error occurred while evaluating nil.build
Se eu tentar definir isso usando @ account.owner_attributes = {} no controlador, ou @ account.owner = User.new, estou de volta ao erro original, "@account [proprietário] não é permitido como um nome de variável de instância".
Alguém mais tem o novo método accepts_nested_attributes_for trabalhar com um relacionamento belongs_to? Existe algo especial ou diferente, você tem que fazer? Todos os exemplos oficiais e código de exemplo (como o grandes coisas sobre a Ryans Recortes ) está preocupado com associações multi-recordes.
Solução
Eu acho que sua accepts_nested_attributes
está no lado errado do relacionamento. Talvez algo como isso iria funcionar?
class Account < ActiveRecord::Base
belongs_to :owner, :class_name => 'User', :foreign_key => 'owner_id'
has_many :users
end
class User < ActiveRecord::Base
belongs_to :account
has_one :account, :foreign_key => :owner_id
accepts_nested_attributes_for :account
end
Para a construção da conta que você deseja usar build_account.
Você pode ver mais exemplos na os docs .
Outras dicas
Eu sou alguns meses de atraso, mas eu estava olhando para resolver este erro e minha situação era que eu não poderia mudar a relação com a 'cara para o outro lado'.
A resposta é realmente muito simples, você tem que fazer isso em sua nova ação:
@account.build_owner
A razão pela qual a forma não exibir usando fields_for era porque não tinha um objeto válido. Você teve a idéia lá em cima com:
@account.owner.build
No entanto, este não é o trabalho de maneira belongs_to
. Este método é gerado apenas com has_many
e has_and_belongs_to_many
.
Referência: http://guides.rubyonrails.org/association_basics.html#belongs-to -Associação referência
Eu estou usando Rails 2.3.5 e notei a mesma coisa. Verificando a fonte para nested_attributes.rb de active_record, parece que belongs_to deve funcionar bem. Assim, parece que poderia ser um "formas aninhadas" bug.
Eu tenho um formulário aninhado exatamente como o seu, com User belongs_to :address
e Address
é independente do usuário.
Em seguida, na forma, eu só faço <% f.fields_for :address_attributes do |address_form| %>
vez de <% f.fields_for :address do |address_form| %>
. corte temporário até que há uma maneira melhor, mas isso funciona. O método accepts_nested_attributes_for
está esperando os parâmetros para incluir algo como:
{user=>{address_attributes=>{attr1=>'one',attr2=>'two'}, name=>'myname'}
... mas fields_for
está produzindo:
{user=>{address=>{attr1=>'one',attr2=>'two'}, name=>'myname'}
Desta forma, você não tem que acrescentar que has_one :account
ao seu código, o que não funciona no meu caso.
Update: Encontrado uma resposta melhor:
Aqui está a essência do código que estou usando para fazer este trabalho certo:
Rails formulários aninhados com belongs_to Gist
Espero que ajude.
class Account < ActiveRecord::Base
belongs_to :owner :class_name => 'User', :foreign_key => 'owner_id'
end
Ele funciona para mim. : Foreign_key => 'owner_id' era o problema chave no meu caso.