0

我有一个属于 :city :state 和 :country 的用户模型。

城市模型属于一个州。

一个国家模型属于一个国家。

当用户注册时,他们应该能够选择一个位置(城市州和国家/地区),或者如果它不在数据库中,则添加一个。问题是,在添加城市和州时,我希望能够将它们分别与他们的州或国家相关联。到目前为止我所拥有的是这个

在我的用户模型中

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

但我建议您重新考虑数据的结构。您有可能导致模型之间发生冲突的冗余链接。例如,如果您更改了用户的状态,但不更改他或她所在城市的状态,那么用户的状态和用户所在城市的状态之间就会发生冲突。

解决此问题的一种方法是通过更紧密的关联来定义用户的州或国家:

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

这样,用户、城市、州和国家之间的关系都只在一个地方定义,这使得它们不太容易发生冲突。这种方法唯一需要注意的是,您必须确保在创建用户时,在尝试添加州之前创建城市,并且在国家之前创建州。您可以在控制器中执行此操作,也可以在before_save挂钩中再次执行此操作。

于 2013-02-06T19:56:00.740 回答