2009-12-04 5 views
11

RoR을 배우고 accepts_nested_attributes_for 및 has_and_belongs_to_many를 사용하여 전통적으로 두 가지 형식 인 정보를 제출하려고합니다. 호환되는 일부 사이트, 호환되지 않는 사이트 및 일부 사이트를 모르는 경우를 읽었습니다. 참고로 레일즈 2.3.4를 사용하고 있습니다. Ryan 's Scraps 튜토리얼에서 모델링 해 보았습니다 nested modelsaccepts_nested_attributes_for 및 has_and_belongs_to_many를 사용하려고 시도했지만 join 테이블이 채워지지 않습니다.

디버깅을 시도한 결과 두 가지 문제점이있는 것으로 보이지만 그 이유는 확실하지 않습니다.

  1. 중첩 모델이 포함 된 양식을 제출하면 중첩 모델 정보의 일부만 게시됩니다. 사용자가 선택할 수있는 "n"이 아닌 첫 번째 필드 만 가져옵니다.
  2. 게시되는 단일 필드 중에서 HABTM 관계에 대해 만든 조인 테이블에 삽입 된 행이 없습니다.

    변호사 모델 :

    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 ") ($ (이) .up ('협회.')를 제거합니다.", "제거" %> <퍼센트 = LINK_TO '새 연결', new_association_path %의> <% 끝 %>

변호사 헬

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"=>"[email protected]"}} 
    [4;35;1mAttorney Load (15.6ms)[0m [0mSELECT "attorneys".id FROM "attorneys" WHERE ("attorneys"."email" = '[email protected]') 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, '[email protected]')[0m 
Redirected to http://localhost:3000/attorneys/11 
Completed in 150ms (DB: 16) | 302 Found [http://localhost/attorneys] 

내가 볼 수있는 협회 "=> {"association_id "=>"3 "}이 그것을 특정 사용자에 대해 가지고있는 다중 연결의 마지막 만 가져오고 조인 테이블에 항목을 만들지 않습니다. 내 코드가 어디에서 잘못되었을 수 있습니까?

답변

27

두 가지 문제가 있습니다. 불행히도 그 중 하나는 다른쪽에 의해 가려집니다.

두 문제는 뷰의이 부분에서 줄기 :

<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이 무엇을 잘못 이해했습니다.

accepts_nested_fields_for는 양식의 관련 개체를 만들고 수정하는 데 사용됩니다. 그것은 당신이하려고하는 일종의 조인 테이블을 생성하는 데 사용될 수 있습니다. 그러나 accepts_nested_fields_for를 사용하여 조인 테이블을 채우는 것은 HABTM 관계로는 불가능합니다. accepts_nested_fields_for를 잘 사용하면 새로운 변호사와 연결될 새로운 연결을 만들고 싶을 것입니다. 또는 각 레코드에 대한 추가 정보가 필요한 풍부한 조인 모델이있는 경우

문제점 2 :이 양식의 입력란은 변호사 양식에 연결되어 있지 않습니다. accepts_nested_fields_for를 사용하는 데 필요한 것입니다.

accepts_nested_fields_for가이 작업을 수행하는 데 필요한 것이 아니지만 select association_id 필드를 양식과 연결하지 않았 음을 이미 입증했습니다. 그래서 params [associations] [association_id]가 설정되었고 params [attorney] [associations] [association_id]가 아닌 이유입니다.

문제 3 : 양식 구조가 당신이 성취하려는 것처럼 보이지 않습니다.

적절한 휴식 시간을주기 위해 너무 많은 수정이 필요합니다. complex-forms-example repository을 확인하는 것이 좋습니다. 그것은 accepts_nested_attributes_for의 작동 예제이며 HABTM 관계를 다루지는 않지만 필요한 모든 것을 가르쳐야합니다. 아래의 수정 된 코드는 필요한 것의 90 %입니다. 위에 링크 된 복잡한 양식 예제는 add_association_link 및 create_association_link 빈칸을 채우기 위해 알아야 할 것을 가르쳐줍니다.

보정에는 다음 단계가 포함

  1. 는이 모델을 결합 생성하고, 많은이에 조인 모델에 중첩 된 속성을 수용, 하나를 통해 관계를 변경합니다.
  2. 컨트롤러를 사물의 측면에서 약간 조정하십시오.
  3. 부분에 양식 빌더 오브젝트를 전달하십시오.
  4. 부분적으로 양식을 다시 작성하여 새로 작성한 조인 모델에 초점을 맞 춥니 다.

다음과 같이 변경하면됩니다.

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 

새로운 변호사보기 : 그 add_association_link 있으리라 믿고있어

<% 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 %> 

빈을 복제 할 수있는 링크를 생성하는 자바 스크립트 도우미 멤버쉽 부분의 인스턴스입니다. create_association_link는 새 도우미에 부분을 추가하는 유사한 도우미의 자리 표시 자입니다.부분

변호사 협회 : 부분

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

협회 : 양식 'F'에 전달하는 뷰를 변경하여

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

, 지금 오류를 얻고있다 : 정의되지 않은 <% = assoc_form.collection_select (: association_id, Association.find (: all), : id)이 줄의 # 에 대한 'association_id' , : 이름, : include_blank => true) %>. 어떤 아이디어? – davidstites

+0

다른 여러 문제를 간과 한 것처럼 보입니다. 나는 그 문제를 해결하기 위해 해결책을 업데이트했다. – EmFi

+0

나는 몇 주 동안이 일을하고 아직도 문제가 있습니다. attorney_association 부분을 렌더링하려 할 때 'f'가 무엇인지 모르는 것에 대한 불평이 ... 나는 형식 객체가 : locals hash와 함께 전달되었다고 생각했습니다. – davidstites

관련 문제