7

簡潔にするために質問を編集し、行ったことを更新します。

会社の複数の住所を持つモデルを作成し、単一の住所を連絡先に割り当て、連絡先の作成または編集時にそれらを割り当てるにはどうすればよいですか?

新しい連絡先の作成時にアドレスを追加できるように、ネストされた属性を使用したいと考えています。最初から入力するのではなく、既存のアドレスからドロップダウンするオプションが必要な場合があるため、そのアドレスは独自のモデルとして存在します。

私はそれを機能させることができないようです。nil:NilClass エラーに対して未定義のメソッド「build」が表示されます

連絡先の私のモデルは次のとおりです。

class Contact < ActiveRecord::Base
  attr_accessible :first_name, :last_name, :title, :phone, :fax, :email, :company, 
                  :date_entered, :campaign_id, :company_name, :address_id, :address_attributes

  belongs_to :company
  belongs_to :address
  accepts_nested_attributes_for :address
end

これが住所の私のモデルです:

class Address < ActiveRecord::Base
  attr_accessible :street1, :street2, :city, :state, :zip

  has_many :contacts
end

新しい連絡先を作成するときに、会社に属する他の連絡先に属するすべてのアドレスにアクセスしたいと思います。だからここに私が会社を表す方法があります:

class Company < ActiveRecord::Base
  attr_accessible :name, :phone, :addresses

  has_many :contacts

  has_many :addresses, :through => :contacts

end

これは、View for _form for Contact にフィールドを作成して、誰かが新しい Contact を作成するときに、住所を Address モデルに渡し、その住所を Contact に関連付ける方法です。

  <% f.fields_for :address, @contact.address do |builder| %>
  <p>
    <%= builder.label :street1, "Street 1" %> </br> 
    <%= builder.text_field :street1 %>
  <p>
  <% end %>

編集しようとすると、Street 1 のフィールドが空白になります。また、show.html.erb の値を表示する方法がわかりません。

下部にあるのは私のエラー コンソールです。アドレス テーブルに値を作成できないようです。

私の連絡先コントローラーは次のとおりです。

  def new
    @contact = Contact.new
    @contact.address.build # Iundefined method `build' for nil:NilClass

    @contact.date_entered = Date.today
    @campaigns = Campaign.find(:all, :order => "name")
    if params[:campaign_id].blank? 

    else
      @campaign = Campaign.find(params[:campaign_id])
      @contact.campaign_id = @campaign.id
    end

    if params[:company_id].blank?

    else
      @company = Company.find(params[:company_id])
      @contact.company_name = @company.name
    end

  end

  def create
    @contact = Contact.new(params[:contact])
    if @contact.save
      flash[:notice] = "Successfully created contact."
      redirect_to @contact
    else
      render :action => 'new'
    end
  end

  def edit
    @contact = Contact.find(params[:id])
    @campaigns = Campaign.find(:all, :order => "name")
  end

エラー コンソールのスニペットを 次に示します。属性を投稿していますが、アドレス テーブルで作成していません。

ContactsController#create の処理 (2010-05-12 21:16:17 の 127.0.0.1 の場合)

[POST] パラメータ: {"commit"=>"Submit", "authenticity_token"=>"d8/gx0zy0Vgg6ghfcbAYL0YtGjYIUC2b1aG+dDKjuSs=", "contact"=>{"company_name"=>"Allyforce", "title"=>" "、"campaign_id"=>"2"、"address_attributes"=>{"street1"=>"abc"}、"fax"=>""、"phone"=>""、"last_name"=>""" , "date_entered"=>"2010-05-12", "email"=>"", "first_name"=>"abc"}}

Company Load (0.0ms)[0m [0mSELECT * FROM "companys" WHERE ("companys"."name" = 'Allyforce') LIMIT 1[0m

Address Create (16.0ms)[0m
[0;1mINSERT INTO "addresses" ("city", "zip", "created_at", "street1", "updated_at", "street2", "state") VALUES(NULL, NULL , '2010-05-13 04:16:18', NULL, '2010-05-13 04:16:18', NULL, NULL)[0m

連絡先の作成 (0.0ms)[0m
[0mINSERT INTO "contacts" ("company", "created_at", "title", "updated_at", "campaign_id", "address_id", "last_name", "phone", "fax" , "company_id", "date_entered", "first_name", "email") VALUES(NULL, '2010-05-13 04:16:18', '', '2010-05-13 04:16:18', 2, 2, '', '', '', 5, '2010-05-12', 'abc', '')[0m

4

4 に答える 4

3

平凡な質問ですが、連絡先フォームでこれを使用する場合、アドレスを単数形にするべきではありませんか?

 <% f.fields_for :address, @contact.address do |builder| %>
   <p>
     <%= builder.label :street1, "Street 1" %> </br> 
     <%= builder.text_field :street1 %>
   <p>
 <% end %>

あなたの行動の中で、あなたもしなければならない

@ycontact.build_address

ソースコードを見ると、入力フィールドは次のようになっているはずです。

< input type="text" size="30" name="contact[address_attributes][street1]" id="contact_address_attributes_street1">

address_id を連絡先に保存すると、関連付けにも問題があると思います

class Contact < ActiveRecord::Base
  belongs_to :address
  accepts_nested_attributes_for :address
end

class Address < ActiveRecord::Base
  attr_accessible :street1
  has_many :contacts
end

複数の連絡先にアドレスを割り当てたいので、これがあなたのケースだと思います。

アドレス モデルに contact_id を保存する場合は、逆にすることもできます。

class Contact < ActiveRecord::Base
  has_one :address
  accepts_nested_attributes_for :address
end

class Address < ActiveRecord::Base
  attr_accessible :street1
  belongs_to :contact
end

この場合、同じアドレスを持つユーザーを持つことはできません。

アップデート

ユーザー show.html.eb で使用できます

<%= @contact.address.street1 %>

あなたの会社の show.html.erb では、次のようなアドレスを表示できます。

<% @company.addresses.each do |address| %>
  <%= address.street1 %>
  ...
<% end %>

ユーザー編集ページでは、フォーム フィールドは new.html.erb と同じである必要があります。フォーム タグは次のようになります。

<% form_for @contact do |form| %>
  <%=render :partial=>'fields' %>
<% end %>

フィールドのパーシャルには、すべてのフィールドと次のものが含まれます。

 <% f.fields_for :address, @contact.address do |builder| %>
   <p>
     <%= builder.label :street1, "Street 1" %> </br> 
     <%= builder.text_field :street1 %>
   <p>
 <% end %>

これはうまくいくはずです。

更新 2

次の方法で、会社に属するすべてのアドレスにアクセスできます。

@company.addresses

あなたが持っている場合

class Company<Activerecord::Base
    has_many :contacts
    has_many :addresses, :through=>:contacts
end

下書き、またはデフォルトのアドレスについて。必要に応じて、さまざまなオプションを使用できます。連絡先がデータベースから既存のアドレスの 1 つを選択できるオプションが必要です。次のように、連絡先フォームで選択ボックスを実行できます。

 <%= form.select :address_id, options_from_collection_for_select(@company.addresses, 'id', 'street1')%>

また、ユーザーが既存のアドレスの 1 つを選択した場合は、派手な JavaScript を使用してアドレス フォームを追加または削除することもできます。この場合、フォームから address_attributes を削除する必要があります。address_attributes を追加して削除する (トグル スタイル) JavaScript コードを使用してリンクを作成することをお勧めします。

于 2010-05-12T07:02:49.100 に答える
1

会社と連絡先の両方に属するアドレスが必要なため、2 つの選択肢があります。複数のアドレスを必要としない場合 (想定しないことをお勧めします)、Company と Contact の両方に「belongs_to :address」を入れることができます。アドレスには、「has_many :companys」と「has_many :contacts」の両方が含まれます。

より理にかなったより良いオプションは、ポリモーフィックな関連付けを使用することです。この場合、アドレス テーブルには :addressable_type 列と :addressable_id 列があり、いずれかのモデルにリンクされます。

class Company < ActiveRecord::Base
  attr_accessible :name, :phone, :addresses

  has_many :contacts  
  accepts_nested_attributes_for :contacts

  has_many :addresses, :as => :addressable
  accepts_nested_attributes_for :addresses

end

class Contact < ActiveRecord::Base
  attr_accessible :first_name, :last_name, :title, :phone, :fax, :email, :company, 
                  :date_entered, :campaign_id, :company_name

  belongs_to :company
  has_many :addresses, :as => :addressable
  accepts_nested_attributes_for :addresses
end

class Address < ActiveRecord::Base
  attr_accessible :street1

  belongs_to :addressable, :polymorphic => true
end

問題は、単一の関連付け "company.addresses" を使用して、そのアドレスとその連絡先のアドレスの両方を取得することです。これを避けて、別のアプローチを使用することをお勧めします。

ビュー内のこれらのアドレスを正しいレコードにマップする必要があるため、それらを分離するのが最善の方法です。

<% form_for @company do |company_form| %>
  <% company_form.fields_for :addresses do |address_form| %>
    <%= address_form.text_field :street1 %>
  <% end %>
  <% company_form.fields_for :contacts do |contact_form| %>
    <% contact_form.fields_for :addresses do |contact_address_form| %>
      <%= contact_address_form.text_field :street1 %>
    <% end %>
  <% end %>
<% end %>

アドレス テーブルには、次のような多態的な列があります。

class CreateAddresses < ActiveRecord::Migration
  def self.up
    create_table :addresses do |t|
      t.string :street1
      t.string :addressable_type
      t.integer :addressable_id
      t.timestamps
    end
  end

  def self.down
    drop_table :addresses
  end
end

このようにレコードを個別にネストしないと、すべてのリンクをまっすぐに保つ方法がわかりません。

表示目的で会社のすべての住所を取得する必要がある場合は、collect などの標準的な ruby​​ の列挙可能な操作を使用してそれらを集めることができます。

幸運を!

于 2010-05-12T16:36:21.830 に答える
1

各アドレスが 1 つの連絡先のみに属している場合 (自宅の住所など)、次のようにできます。

class Company < ActiveRecord::Base
  has_many :contacts
end

class Contact < ActiveRecord::Base
  belongs_to :company
  has_one :address
end

class Address < ActiveRecord::Base
  belongs_to :contact
end

もちろん、住所列を Contact テーブルに移動して、Address モデルを完全に削除することもできます。

各住所に複数の連絡先がある場合 (つまり、住所が連絡先が勤務する会社の施設である場合):

class Company < ActiveRecord::Base
  has_many :contacts
end

class Contact < ActiveRecord::Base
  belongs_to :company
  belongs_to :address
end

class Address < ActiveRecord::Base
  has_many :contacts
end

has_many :through取得する関連付けを追加できますcompany.addresses:

class Company < ActiveRecord::Base
  has_many :contacts
  has_many :addresses, :through => :contacts
end

どちらの場合も、住所コンポーネント (番地、都市、州など) は住所テーブルの列です。

質問の最後の部分は、実際にはデータの分布に依存します。住所が少数しかない場合は、メインの住所をデフォルトとして選択要素に貼り付けるだけです。住所が増えると、住所テーブルを検索するオートコンプリートを備えた AJAX 化されたフォームが必要になる場合があります。

新しい連絡先/住所をテーブルに取得するには、ネストされたフォームを確認することをお勧めします。Railscast 196は良い入門書です。

編集 -- ネストされた属性の詳細

accepts_nested_attributes_forhas_manyまたは関連付けのいずれかでhas_one動作し、複数レベルのネストで動作する必要があります。Contact を Company に所属させ、Address を Contact に所属させたいと考えているようですが、その場合は次のようになります。

class Company < ActiveRecord::Base
  has_many :contacts
  accepts_nested_attributes_for :contact
end

class Contact < ActiveRecord::Base
  belongs_to :company
  has_one :address # or has_many, if you prefer
end

class Address < ActiveRecord::Base
  belongs_to :contact
end

次に、Railscast で説明されているようにビューでform_forandを使用して、ネストされたフォーム要素を取得します。fields_forフォームが特殊な場合、これを正しく行うのは少し難しい場合があります。ここには、いくつかの典型的な状況をカバーする ryanb の優れた例があります。

于 2010-05-09T06:50:59.597 に答える
0

連絡先に多くのアドレスを持たせることをお勧めします。とにかく、それは野生で起こります。1つだけ決めるとすれば、has_one :address

ああ、あなたはそれらを小文字にする必要があります:するhas_many :Contacts必要がありますhas_many :contacts

参照する Address モデルで (データベースにはaddressable_idandaddressable_typeフィールドが必要です)

belongs_to :addressable, :polymorphic => true
于 2010-05-09T07:05:37.040 に答える