0

:city:stateと:countryに属するユーザーモデルがあります。

CityモデルはStateに属しています。

そして、州のモデルは国に属しています。

ユーザーがサインアップするときに、場所(都市の州と国)を選択するか、データベースにない場合は場所を追加できる必要があります。問題は、都市と州を追加するときに、それぞれの州または国に関連付けることができるようにすることです。私が今まで持っているのはこれです

私のユーザーモデルでは

belongs_to  :state 
belongs_to  :city
belongs_to  :country     

def city_name
  city.try(:name)
end

def city_name=(name)
  self.city = City.find_or_create_by_name(name.titleize) if name.present?
end

def country_name
  country.try(:name)
end

def country_name=(name)
  self.country = Country.find_or_create_by_name(name.titleize) if name.present?
end

def state_name
  state.try(:name)
end

def state_name=(name)
  self.state = State.find_or_create_by_name(name.titleize) if name.present?
end

私のユーザー/新しいフォーム

<div class="field">
  <%= f.label :your_city %><br />
  <%= f.text_field :city_name, data: {autocomplete_source: cities_path} %>
  <br /> or <%= link_to "add New Location" ,"javascript:toggleDiv('hideme');"%>
</div>
<div id="log"></div>

<div id="hideme">
  <div class="field">
    <%= f.label :country_name %><br />
    <%= f.text_field :country_name %>
  </div>

  <div class="field">
    <%= f.label :state_name %><br />
    <%= f.text_field :state_name %>
  </div>
</div>

このようにして、ユーザーを作成して都市国家と国に関連付けますが、都市国家と国はそれぞれの州と国の親に関連付けられていない状態で変動しています。ユーザーの作成時にこれらのモデルを関連付ける方法はありますか?このアプローチを放棄する必要がありますか?

4

1 に答える 1

0

これを行う場所はbefore_saveフックにあると思います(またはbefore_create、市、州、国が変更されない場合)。

多分このようなもの:

class User < ActiverRecord::Base
  before_save :city_state_country_setup

  ...

  private

  def city_state_country_setup
    self.state.update_attributes(country_id: self.country.id)
    self.city.update_attributes(state_id: self.state.id)
  end
end

ただし、データの構造を再検討することをお勧めします。モデル間の競合につながる可能性のある冗長リンクがあります。たとえば、ユーザーの状態を変更しても、その都市の状態を変更しない場合、ユーザーの状態とユーザーの都市の状態の間に競合が発生します。

これを回避する1つの方法は、ユーザーの州または国をより緊密な関連付けを通じて定義することです。

class User
  belongs_to  :city

  #New accessor methods for state and country
  def state
    @state ||= self.city.state
  end

  def state=(s)
     self.city.state = s
  end

  def country
    @country ||= self.state.country
  end

  def country=(c)
     self.state.country = c
  end

  ...

end

このように、ユーザー、都市、州、国の間の関係は、それぞれ1つの場所でのみ定義されるため、競合が発生しにくくなります。このアプローチの唯一の注意点は、ユーザーが作成されたときに、州を追加する前に都市が作成され、国の前に州が作成されていることを確認する必要があることです。これは、コントローラーで実行することも、before_saveフックで実行することもできます。

于 2013-02-06T19:56:00.740 に答える