尝试使用accepts_nested_attributes_for和has_and_belongs_to_many,但是未填充联接表 [英] Trying to use accepts_nested_attributes_for and has_and_belongs_to_many but the join table is not being populated

查看:50
本文介绍了尝试使用accepts_nested_attributes_for和has_and_belongs_to_many,但是未填充联接表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习RoR,并尝试使用accepts_nested_attributes_for和has_and_belongs_to_many提交传统上是两种形式的信息.我读过一些兼容的站点,某些不兼容的站点,以及某些不知道的站点.作为参考,我正在使用Rails 2.3.4.我尝试在嵌套模型

I am learning RoR and trying to use accepts_nested_attributes_for and has_and_belongs_to_many to submit information that would traditionally be two forms. I have read on some sites they are compatible, some sites they aren't compatible, and some sites don't know. As reference, I am using Rails 2.3.4. I tried modeling my solution from the Ryan's Scraps tutorial on nested models

从我尝试调试的内容来看,似乎有两个问题,但是我不确定为什么.

From what I have tried to debug, it seems that I have two problems but I am not sure why.

  1. 当我提交带有嵌套模型的表单时,只会发布部分嵌套模型信息.我只得到第一个字段,而不是用户可能选择的其他"n"个
  2. 在发布的单个字段中,我为HABTM关系创建的联接表中没有插入任何行.

这是一段代码和我尝试插入的相应日志:

Here is a piece of code and the corresponding logs for my insertion attempt:

律师模式:

class Attorney < ActiveRecord::Base 
  has_and_belongs_to_many :associations
  accepts_nested_attributes_for :associations, :reject_if => proc { |a| a['name'].blank? }
end

关联模型:

class Association < ActiveRecord::Base
  has_and_belongs_to_many :attorneys
  accepts_nested_attributes_for :attorneys
  validates_presence_of :name, :message => "Please enter an association name."
end

律师代理人:

def new
  @attorney = Attorney.new
  @attorney.associations.build

  respond_to do |format|
    format.html # new.html.erb
    format.xml  { render :xml => @attorney }
  end
end

def create
  @attorney = Attorney.new(params[:attorney])

  respond_to do |format|
    if @attorney.save
      flash[:notice] = 'Attorney was successfully created.'
      format.html { redirect_to(@attorney) }
      format.xml  { render :xml => @attorney, :status => :created, :location => @attorney }
    else
      format.html { render :action => "new" }
      format.xml  { render :xml => @attorney.errors, :status => :unprocessable_entity }
    end
  end
end

律师的新观点:

<% form_for(@attorney, :html => {:multipart => true}) do |f| %>
  <%= f.error_messages %>
 <%= f.label :"First name" %> 
 <%= f.text_field :firstname %><br>

 <%= f.label :"Last Name" %> 
 <%= f.text_field :lastname %><br>

 <%= f.label :"Attorney Type" %> 
 <%= f.collection_select :member_type_id, MemberType.all, :id, :name %><br>

 <%= f.text_area :bio, :cols => 70, :rows => 20 %><br><br>

 <%= f.label :"Attorney Location" %> 
 <%= f.collection_select :office_location_id, OfficeLocation.all, :id, :location %><br>

 <div id="associations">
      <%= render :partial => 'shared/membership' %>
 </div>
 <%= add_association_link "Add Association" %>
    <%= f.submit 'Create' %>
<% end %>

部分会员资格

<div class="association">
  <% fields_for :associations do |assoc_form| %>
    <%= assoc_form.collection_select(:association_id, Association.find(:all), :id, :name, :include_blank => true) %>

<%= link_to_function删除","$(this).up('.association').remove()"%> <%=链接到新关联",new_association_path%> <%结束%>

<%= link_to_function "remove", "$(this).up('.association').remove()" %> <%= link_to 'New Association', new_association_path %> <% end %>

律师帮助链接:

def add_association_link(name)
  link_to_function name do |page|
    page.insert_html :bottom, :associations, :partial => 'shared/membership', :object => AssociationsAttorneys.new
  end
end

加入表迁移:

class CreateAssociationsAttorneys < ActiveRecord::Migration
  def self.up
    create_table :associations_attorneys do |t|
      t.references :attorney, :null => false
      t.references :association, :null => false
      t.timestamps
    end
  end

  def self.down
    drop_table :associations_attorneys
  end
end

日志捕获:

    Processing AttorneysController#new (for 127.0.0.1 at 2009-12-04 08:16:19) [GET]
Rendering template within layouts/default
Rendering attorneys/new
  [4;35;1mMemberType Load (0.4ms)[0m   [0mSELECT * FROM "member_types" [0m
  [4;36;1mOfficeLocation Load (18.6ms)[0m   [0;1mSELECT * FROM "office_locations" [0m
  [4;35;1mAssociation Load (0.6ms)[0m   [0mSELECT * FROM "associations" [0m
Rendered shared/_membership (3.5ms)
  [4;36;1mCACHE (0.0ms)[0m   [0;1mSELECT * FROM "associations" [0m
Rendered shared/_membership (1.5ms)
Rendered shared/_nav (0.6ms)
Rendered shared/_footer (0.1ms)
Completed in 149ms (View: 114, DB: 20) | 200 OK [http://localhost/attorneys/new]

Processing ApplicationController#index (for 127.0.0.1 at 2009-12-04 08:16:19) [GET]

Processing AttorneysController#create (for 127.0.0.1 at 2009-12-04 08:16:57) [POST]
  Parameters: {"commit"=>"Create", "authenticity_token"=>"Jh7aMCcOY7jUu/D1YtiCswg2n6iwqnS98VnVn46psp0=", "associations"=>{"association_id"=>"3"}, "attorney"=>{"birthstate"=>"Alabama", "office_location_id"=>"1", "birthdate"=>"December 3, 2009", "birthcity"=>"Test", "middlename"=>"Test", "lastname"=>"Testing", "image_temp"=>"", "member_type_id"=>"2", "firstname"=>"Test", "bio"=>"testing testing testing", "suffix"=>"", "email"=>"testing@test.com"}}
  [4;35;1mAttorney Load (15.6ms)[0m   [0mSELECT "attorneys".id FROM "attorneys" WHERE ("attorneys"."email" = 'testing@test.com') LIMIT 1[0m
  [4;36;1mAttorney Create (0.8ms)[0m   [0;1mINSERT INTO "attorneys" ("birthstate", "created_at", "birthdate", "office_location_id", "birthcity", "updated_at", "middlename", "lastname", "firstname", "member_type_id", "suffix", "bio", "image", "email") VALUES('Alabama', '2009-12-04 15:16:57', 'December 3, 2009', 1, 'Test', '2009-12-04 15:16:57', 'Test', 'Testing', 'Test', 2, '', 'testing testing testing', NULL, 'testing@test.com')[0m
Redirected to http://localhost:3000/attorneys/11
Completed in 150ms (DB: 16) | 302 Found [http://localhost/attorneys]

我看到关联"=> {" association_id"=>" 3}只是获得了我与特定人的多个关联中的最后一个,并且没有在联接表中创建任何条目.我的代码可能在哪里出错了?

I can see that associations"=>{"association_id"=>"3"} it is only getting the last of the multiple associations that I had for the particular person and it isn't creating any entries into the join table. Where might my code have gone wrong?

推荐答案

你们两个在这里有问题,不幸的是其中一个被另一个掩盖了.

You two have problems here, unfortunately one of them is masked by the other.

这两个问题均源于此部分视图:

Both problems stem from this part of the view:

<div class="association">
  <% fields_for :associations do |assoc_form| %>
    <%= assoc_form.collection_select(:association_id, Association.find(:all),
      :id, :name, :include_blank => true) %>

问题1:您误解了accept_nested_fields_for的功能.

Problem 1: You've misunderstood what accept_nested_fields_for does.

accepts_nested_fields_for用于创建和修改表单中的相关对象.它可用于填充联接表,这是您要尝试执行的操作.但是,对于HABTM关系,不可能使用accepts_nested_fields_for填充联接表.如果您想创建一个将与新律师联系起来的新协会,则可以很好地使用accepts_nested_fields_for.或者,如果您有一个丰富的联接模型,该模型需要每个记录的附加信息.

accepts_nested_fields_for is used to create and modify related objects in a form. It can be used to populate join table, which is kind of what you're trying to do. However, using accepts_nested_fields_for to populate the join table is impossible with a HABTM relationship. A good use of accepts_nested_fields_for would be if you wanted to create a new Association that will be linked with the new Attorney. Or if you had a rich join model that required additional information for each record.

问题2:您没有将此表单中的字段链接到律师表单.使用accepts_nested_fields_for是必需的.

Problem 2: You're not linking the fields in this form to the attorney form. Which is necessary to use accepts_nested_fields_for.

我们已经确定accepts_nested_fields_for不是完成此操作所需要的,但是,您仍然没有将select association_id字段与表单相关联.这就是为什么设置了params [associations] [association_id]而不是params [attorney] [associations] [association_id].

We've already established that accepts_nested_fields_for is not what you need to accomplish this, but, you're still not associating the select association_id field with the form. Which is why params[associations][association_id] was set and not params[attorney][associations][association_id].

问题3:表单结构对于您要完成的工作完全不正确.

Problem 3: The form structure is all wrong for what it looks like you're trying to accomplish.

有太多需要纠正的内容,以进行适当的分类.您最好检查一下 complex-forms-example存储库.这是一个accepts_nested_attributes_for的工作示例,它不处理任何HABTM关系,但是它应该教会您所有您需要知道的事情.下面更正的代码是您需要的90%.上面链接的complex-forms-examples将教您需要了解的知识,以填补add_association_link和create_association_link的空白.

There's a too much that needs correcting for me to give a proper break down. You're better off checking out the complex-forms-example repository. It's a working example of accepts_nested_attributes_for, it doesn't deal with any HABTM relationships, but it should teach you every thing you need to know. The corrected code below is 90 % of what you need. The complex-forms-examples linked above will teach you what you need to know to fill in the blanks that are add_association_link and create_association_link.

更正涉及以下步骤:

  1. 创建一个联接模型,并通过在联接模型上接受嵌套的属性,通过一个将多个关系更改为一个.
  2. 就建筑方面而言,对控制器进行了微小的调整.
  3. 将表单生成器对象传递给局部对象.
  4. 重写部分表单,以便将其重点放在新创建的联接模型上.

您可以通过以下更改来完成此操作.

You can accomplish this with the following changes.

class Attorney < ActiveRecord::Base
  has_many :attorney_associations
  has_many :associations, :through => :attorney_associations

  accepts_nested_attributes_for :attorney_associations, :reject_if => proc { |a| 
     a['association_id'].blank? }
  accepts_nested_attributes_for :associations, :reject_if => proc {|a|
     a['name'].blank?}
end

class AttorneyAssociations < ActiveRecord::Base
  belongs_to :attorney
  belongs_to :association
end

检察官:

def new
  @attorney = Attorney.new
  @attorney.associations.build
  @attorney.attorney_associations.build


  respond_to do |format|
    format.html # new.html.erb
    format.xml  { render :xml => @attorney }
  end
end

新律师视图:

<% form_for(@attorney, :html => {:multipart => true}) do |f| %>
  <%= f.error_messages %>
 <%= f.label :"First name" %> 
 <%= f.text_field :firstname %><br>

 <%= f.label :"Last Name" %> 
 <%= f.text_field :lastname %><br>

 <%= f.label :"Attorney Type" %> 
 <%= f.collection_select :member_type_id, MemberType.all, :id, :name %><br>

 <%= f.text_area :bio, :cols => 70, :rows => 20 %><br><br>

 <%= f.label :"Attorney Location" %> 
 <%= f.collection_select :office_location_id, OfficeLocation.all, :id, :location %><br>

 <div id="associations">
   <% f.fields_for :attorney_association do |aa_form| %>
     <%= render :partial => 'attorney_association', :locals => {:f => aa_form} %>
   <% end %>
   <%= add_association_link "Add Another Existing Association" %>
   <% f.fields_for :associations do |assoc_form| %>
     <%= render :partial => 'attorney', :locals => {:f => assoc_form} %>       
   <%= create_association_link, "Create a New Association for this Attorney" %>
 </div>



 <%= f.submit 'Create' %>
<% end %>

我假设add_association_link是一个JavaScript帮助器,它创建一个链接来克隆一个隶属关系部分的空实例. create_association_link是类似帮助器的占位符,它将为新的关联添加部分内容.

I'm assuming that add_association_link is a javascript helper that creates a link to clone an empty instance of what was the Membership partial. create_association_link is a place holder for a similar helper that will add a partial for a new association.

律师协会部分:

  <div class="attorney_association">
    <%= f.collection_select(:association_id, Association.find(:all),
      :id, :name, :include_blank => true) %>
    <%= link_to_function "remove", "$(this).up('.attorney_association').remove()" %>
  </div>

部分关联:

  <div class="association">
    <%= f.label_for :name %>
    <%= f.text_field :name %>
    <%= link_to_function "remove", "$(this).up('.attorney_association').remove()" %>
  </div>

这篇关于尝试使用accepts_nested_attributes_for和has_and_belongs_to_many,但是未填充联接表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆