Rails - 处理深层模型层次结构

时间:2014-10-25 21:08:04

标签: ruby-on-rails ruby activerecord model associations

我有一个用户模型,其中包含三个与之关联的模型:城市国家/地区。他们的协会如下:

class User < ActiveRecord::Base
  has_one :city
  has_one :state
  has_one :country
end

class City < ActiveRecord::Base
  belongs_to :state
  belongs_to :user
end

class State < ActiveRecord::Base
  has_many :cities
  belongs_to :country
  belongs_to :user
end

class Country < ActiveRecord::Base
  has_many :states
  belongs_to :user
end

我想要做的是创建一个表单,允许新用户/现有用户将这些信息添加到他们的个人资料中。但是在rails控制台中尝试这个之后,我发现要完成这个事情会变得严重束缚。

city       = City.create(name: "New York City")
city.state = state 

state         = State.create(name: "New York")
state.country = country

country = Country.create(name: "United States")

user         = User.create(name: "John Doe")
user.city    = City.first
user.state   = user.city.state
user.country = user.state.country

我的最终目标是能够创建具有自动完成功能的选择框或输入,以便能够检索并返回所选内容的数据。因此,如果我在City的选择框中选择纽约市,那么州选择框将返回纽约(父子配对)。有没有更好的方法将这些模型分配给彼此?

奖励点:用于显示控制器逻辑。当我继续认为那里的事情很可能会出现在用户进入网站上没有的新州,城市或国家的时候。我假设我的用户控制器的创建/更新看起来像这样,但就其他剩余的动作而言,我似乎无法想到解决方案?

# users_controller.rb
def create
  @user.build_city
  @user.build_state
  @user.build_country
end

2 个答案:

答案 0 :(得分:1)

Carl,我建议您完全加载您的位置表一次。这样,几乎不会发生城市,州或国家的创造。

如果我没有弄错的话,这个网站提供API,或者你可以下载完整的数据库加载到你的网站。看看:http://www.geonames.org

查看示例: http://blog.inspired.no/populate-your-database-with-free-world-cities-countries-regions-in-2-minutes-using-a-rails-migration-273/

还有一个人创造了一个宝石来初始化城市,州和国家。但我没有测试过:https://github.com/mettadore/geoinfo

答案 1 :(得分:0)

对于任何想要完成创建具有地理属性的模型的人,我发现并决定使用Geocoder gem。一旦安装,这就是我的用户模型最终看起来像。请注意,属性应该显然需要将三个属性添加到模型中才能实现:

class User < ActiveRecord::Base

  after_validation :geocode

  geocoded_by :address do |obj,results|
    if geo = results.first
      obj.state = geo.state
      obj.country = geo.country
      obj.city = geo.city
      obj.province = geo.province
    end
  end
end