【问题标题】:Getting fields_for and accepts_nested_attributes_for to work with a belongs_to relationship让fields_for和accepts_nested_attributes_for与belongs_to关系一起工作
【发布时间】:2009-08-21 17:08:41
【问题描述】:

我似乎无法使用 Rails 2.3 的新 accepts_nested_attributes_for 工具在 Rails 视图中为 belongs_to 关系生成嵌套表单。我确实检查了许多可用资源,看起来我的代码应该可以工作,但是fields_for 对我来说是爆炸性的,我怀疑它与我如何拥有嵌套模型有关配置好了。

我遇到的错误很常见,可能有很多原因:

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

以下是涉及的两个模型:

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 键。

这是我在 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] is not allowed作为实例变量名”。

还有其他人使用新的accepts_nested_attributes_for 方法来处理belongs_to 关系吗?你有什么特别或不同的事情要做吗?所有官方示例和示例代码(如great stuff over at Ryans Scraps)都与多记录关联有关。

【问题讨论】:

    标签: ruby-on-rails ruby associations nested-attributes


    【解决方案1】:

    我已经晚了几个月,但我正在寻求解决这个错误,而我的情况是我无法将关系更改为“面向另一个方向”。

    答案真的很简单,你必须在你的新动作中这样做:

    @account.build_owner
    

    使用 fields_for 不显示表单的原因是它没有有效的对象。你有正确的想法:

    @account.owner.build
    

    但是,这不是belongs_to 的工作方式。此方法仅使用has_manyhas_and_belongs_to_many 生成。

    参考: http://guides.rubyonrails.org/association_basics.html#belongs-to-association-reference

    【讨论】:

    • 但是多态关系中不存在build_方法。
    • @Jaryl,像魅力一样工作...... :) 请评论“当编辑时呈现相同的表单并且具有属于 belongs_to 关联的嵌套属性时应该做什么。”。
    • @zeal 又晚了一个月,但理想情况下不需要做任何进一步的事情来处理创建和编辑。 form_for 和accepts_nested_attributes_for 协同工作以生成表单元素,使得现有记录的id 存在,如果不存在,它将只生成[]。它事件以相同的方式适用于 has_many 关联,但带有一个额外的 [] 来维护一些索引。需要注意的一些注意事项是,对于强参数,您需要允许 owner_attributes: [:account_id, :your_data],其中外键允许维护关联。
    • 显然这种非常不直观的行为是这样设计的github.com/rails/rails/issues/2709#issuecomment-4859798
    【解决方案2】:

    我认为您的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 中查看更多示例。

    【讨论】:

    • 天啊!这样就可以了。我实际上可能会更改此设置,以便 Account has_one :owner 和 User belongs_to :owned_account 或 :team 或其他内容,并设置外键。
    • accepts_nested_attributes_for 可以在关系的任何一方(至少我已经确认 has_one,belongs_to)。我假设 has_many 的功能相同。
    【解决方案3】:

    我使用的是 Rails 2.3.5,我注意到了同样的事情。查看 active_record 的 nested_attributes.rb 的源代码,belongs_to 看起来应该可以正常工作。所以看起来它可能是一个“嵌套表单”错误。

    我有一个和你一模一样的嵌套表单,User belongs_to :addressAddress 独立于用户。

    然后在表单中,我只使用&lt;% f.fields_for :address_attributes do |address_form| %&gt; 而不是&lt;% f.fields_for :address do |address_form| %&gt;。临时破解,直到有更好的方法,但这有效。方法accepts_nested_attributes_for 期望参数包含以下内容:

    {user=&gt;{address_attributes=&gt;{attr1=&gt;'one',attr2=&gt;'two'}, name=&gt;'myname'}

    ...但是fields_for 正在生产:

    {user=&gt;{address=&gt;{attr1=&gt;'one',attr2=&gt;'two'}, name=&gt;'myname'}

    这样您就不必将 has_one :account 添加到您的代码中,这在我的情况下不起作用。

    更新:找到更好的答案:

    这是我用来使这项工作正常进行的代码的要点:

    Rails Nested Forms with belongs_to Gist

    希望对您有所帮助。

    【讨论】:

      【解决方案4】:
      class Account < ActiveRecord::Base
      
          belongs_to :owner  :class_name => 'User', :foreign_key => 'owner_id'
      end
      

      它对我有用。 :foreign_key => 'owner_id' 是我的关键问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多