web-dev-qa-db-ja.com

belongs_to関係を操作するためのfields_forとaccepts_nested_attributes_forの取得

Rails 2.3の新しいbelongs_to機能を使用してaccepts_nested_attributes_for関係のRailsビューで生成するネストされたフォームを取得できないようです。利用可能な多くのリソースを確認しましたが、コードは機能しているはずですのようですが、fields_forが爆発し、疑わしいと思いますネストされたモデルをどのように構成するかと関係があります。

私がヒットしたエラーは、多くの原因が考えられる一般的なエラーです。

'@account[owner]' is not allowed as an instance variable name

関連する2つのモデルを次に示します。

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

アカウントが「所有者」を持つことができ、「ユーザー」が存在する可能性があるため、おそらくこれが「間違った」ことを実行している場所ですが、ユーザーはユーザーモデルaccount_idキーに基づいて1つの「アカウント」しか持っていません。

これは、私に吹き飛ばされるnew.html.hamlのビューコードです:

- form_for :account, :url => account_path do |account|
  = account.text_field :name
  - account.fields_for :owner do |owner|
    = owner.text_field :name

そして、これは新しいアクションのコントローラーコードです:

class AccountsController < ApplicationController
  # GET /account/new
  def new
    @account  = Account.new
  end
end

/ account/newを読み込もうとすると、次の例外が発生します。

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

神秘的な「ビルド」メソッドを使用しようとすると、おそらくビルドがマルチレコード関係のためだけなので、コントローラーで爆破するだけです。

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

コントローラで@ account.owner_attributes = {}または@ account.owner = User.newを使用してこれを設定しようとすると、「@ account [owner]はインスタンスとして許可されていません。変数名」。

他に誰かが属しているto_関係で動作する新しいaccepts_nested_attributes_forメソッドがありますか?何か特別なことや違うことはありますか?すべての公式の例とサンプルコード(Ryans Scrapsの 素晴らしいもの など)は、複数レコードの関連付けに関係しています。

28
Billy Gray

accepts_nested_attributesは関係の反対側にあります。たぶんこのようなものがうまくいくでしょうか?

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

アカウントを作成するには、build_accountを使用します。

the docs でより多くの例を見ることができます。

8
Andy Gaskell

私は数ヶ月遅すぎますが、このエラーを解決しようとしていましたが、私の関係では、関係を「反対向き」に変更することができませんでした。

答えは非常に簡単です。新しいアクションでこれを行う必要があります。

@account.build_owner

Fields_forを使用してフォームが表示されなかった理由は、フォームに有効なオブジェクトがなかったためです。あなたはそこに正しい考えを持っていました:

@account.owner.build

ただし、これはbelongs_toの動作とは異なります。このメソッドは、has_manyおよびhas_and_belongs_to_manyでのみ生成されます。

リファレンス: http://guides.rubyonrails.org/association_basics.html#belongs-to-association-reference

44
Jaryl

私はRails 2.3.5を使用していますが、同じことに気づきました。active_recordのnested_attributes.rbのソースを確認すると、belongs_toは正常に動作するはずです。したがって、「ネストされたフォーム」のバグ。

私はあなたとまったく同じようにネストされたフォームを持っています、User belongs_to :address、およびAddressはユーザーから独立しています。

次に、フォームでは<% f.fields_for :address_attributes do |address_form| %> の代わりに <% f.fields_for :address do |address_form| %>。より良い方法が見つかるまで一時的にハッキングしますが、これはうまくいきます。メソッドaccepts_nested_attributes_forは、paramsに次のようなものが含まれることを期待しています:

{user=>{address_attributes=>{attr1=>'one',attr2=>'two'}, name=>'myname'}

...だが fields_forが生成しています:

{user=>{address=>{attr1=>'one',attr2=>'two'}, name=>'myname'}

このように、それを追加する必要はありませんhas_one :accountをコードに追加すると、私の場合は機能しません。

更新:より良い答えが見つかりました:

これを正しく動作させるために私が使用しているコードの要点は次のとおりです。

Railsネストフォーム、belongs_to Gistを使用

お役に立てば幸いです。

8
Lance Pollard