接受_nested_attributes_for with has_many => :through Options

Posted

技术标签:

【中文标题】接受_nested_attributes_for with has_many => :through Options【英文标题】:accepts_nested_attributes_for with has_many => :through Options 【发布时间】:2011-01-13 19:59:40 【问题描述】:

我有两个模型,链接和标签,通过第三个链接标签关联。以下代码在我的 Link 模型中。

协会:

class Link < ActiveRecord::Base
  has_many :tags, :through => :link_tags
  has_many :link_tags

  accepts_nested_attributes_for :tags, :allow_destroy => :false, 
  :reject_if => proc  |attrs| attrs.all?  |k, v| v.blank?  
end

class Tag < ActiveRecord::Base
  has_many :links, :through => :link_tags
  has_many :link_tags
end

class LinkTag < ActiveRecord::Base
  belongs_to :link
  belongs_to :tag
end

links_controller 操作:

  def new
    @link = @current_user.links.build
    respond_to do |format|
      format.html # new.html.erb
      format.xml   render :xml => @link 
    end
  end

  def create
    @link = @current_user.links.build(params[:link])

    respond_to do |format|
      if @link.save
        flash[:notice] = 'Link was successfully created.'
        format.html  redirect_to links_path 
        format.xml   render :xml => @link, :status => :created, :location => @link 
      else
        format.html  render :action => "new" 
        format.xml   render :xml => @link.errors, :status => :unprocessable_entity 
      end
    end
  end

从 new.html.erb 查看代码:

<% form_for [current_user, @link], :url => account_links_path do |f| %>
<%= render :partial => "form", :locals =>  :f => f  %>
<% end %>

以及对应的部分:

  <%= f.error_messages %>

  <p>
    <%= f.label :uri %><br />
    <%= f.text_field :uri %>
  </p>
  <p>
    <%= f.label :title %><br />
    <%= f.text_field :title %>
  </p>

  <h2>Tags</h2>
  <% f.fields_for :tags_attributes do |tag_form| %>
  <p>
    <%= tag_form.label :name, 'Tag:' %>
    <%= tag_form.text_field :name %>
  </p>
  <% unless tag_form.object.nil? || tag_form.object.new_record? %>
  <p>
    <%= tag_form.label :_delete, 'Remove:' %>
    <%= tag_form.check_box :_delete %>
  </p>
  <% end %>
  <% end %>

  <p>
    <%= f.submit 'Update' %>
  </p>

下面这行代码,在Link控制器的create动作中抛出错误:

@link = @current_user.links.build(params[:link])

错误:Tag(#-621698598) expected, got Array(#-609734898)

在 has_many => :through 案例中是否需要额外的步骤?这些似乎是基本 has_many 案例的唯一指示更改。

【问题讨论】:

我无法根据您发布的代码重现您的问题。您能否发布您的三个模型的关联部分(has_many/belongs_to/etc 行),包括相关的控制器操作(links#new、links#create)和与链接表单有关的任何视图代码。 我已经为关联、控制器动作和视图添加了代码。感谢您的帮助。 【参考方案1】:

看看你的代码行

<% f.fields_for :tags_attributes do |tag_form| %>

您只需使用:tags 而不是:tags_attributes。 这将解决您的问题

确保您的控制器中有构建链接和标签,例如

def new
  @link = @current_user.links.build
  @link.tags.build
end

【讨论】:

【参考方案2】:

您需要在控制器或视图中构建标签

def new
  @link = @current_user.links.build
  @link.tags.build
end

#in your view you can just use the association name
<% f.fields_for :tags do |tag_form| %>

【讨论】:

【参考方案3】:

我在***上找到了这个:

Rails nested form with has_many :through, how to edit attributes of join model?

请告诉我它是否有效。

【讨论】:

这是我的问题(也是我的答案),我可以肯定地告诉你它有效 :)【参考方案4】:

试试

<% f.fields_for :tags do |tag_form| %> 

(即丢失 :tag_attributes 中的 _attributes)这就是我通常做嵌套表单的方式

【讨论】:

【参考方案5】:

为了让它工作,你需要传入正确的参数哈希:

params = 
  :link => 
    :tags_attributes => [
      :tag_one_attr => ..., :tag_two_attr => ...
    ],
    :link_attr => ...
  

您的控制器将如下所示:

def create
  @link = Link.create(params[:link]) # this will automatically build the rest for your
end

【讨论】:

【参考方案6】:

在新操作(加载表单部分)的控制器中,您是否通过链接构建@tag?

所以你应该看到以下内容:

@link = Link.new
@tag = @link.tags.build

最好发布你的 links_controller 的 new 和 create action 的内容。

【讨论】:

控制器动作现在在原始帖子中。我没有在新操作中创建标签。我在这里关注多模型部分:guides.rubyonrails.org/getting_started.html,这并不表示需要更改控制器。也就是说,尽管没有任何标签,但新表单确实会自动生成一个标签框。【参考方案7】:

试试这个:

<% f.fields_for :tags_attributes do |tag_form| %>

【讨论】:

现在出现不同的错误:“编码”的“未定义方法 `with_indifferent_access”:字符串' 参数:“commit”=>“Update”、“authenticity_token”=>“fwCGGgcTKOSfxpFJMXmq7IUfRtfOvdOKl31Xys4TKC8=",“link” =>"tags_attributes"=>"name"=>"Coding", "uri"=>"***.com", "title"=>"Stack Overflow" 感谢您的建议。这个问题有方法解决吗?它是否试图将其中一个属性的值视为哈希? 你能粘贴你的整个表格吗 我已将表单添加到原始帖子中。感谢您的帮助。 我有完全相同的问题,has_many with through 和关于“with_indifferent_access”的错误。你找到解决办法了吗? 解决办法是不使用 Rails 嵌套的表单助手,你需要传入一个自定义的 params 哈希,这意味着你自己构建你的表单。

以上是关于接受_nested_attributes_for with has_many => :through Options的主要内容,如果未能解决你的问题,请参考以下文章

TypeError: __init__() 接受 1 个位置参数,但给出了 2 个

简单的留言簿 django:__init__() 接受 1 个位置参数,但给出了 2 个

Java JPA。 SQL 接受 '_' LIKE 错误

TypeError: __init__() 接受 2 个位置参数,但给出了 4 个

TypeError: __init__() 接受 1 个位置参数,但给出了 3 个

图表类:TypeError:__init__() 接受 1 个位置参数,但给出了 3 个