【问题标题】:Rails - Handling Deep Model HierarchiesRails - 处理深层模型层次结构
【发布时间】:2014-10-25 21:08:04
【问题描述】:

我有一个用户模型,其中包含三个与之关联的附加模型:CityStateCountry。它们的关联如下:

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 的选择框中选择 New York City,那么 State 选择框将返回 New York(父子配对)。有没有更好的方法将这些模型相互分配?

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

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

【问题讨论】:

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


    【解决方案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/

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

    【讨论】:

    • 使用 GeoNames,我是否仍会保留问题中的关联?另外,您是否知道我将如何配置我的视图/控制器来分配这些值?
    • 顺便说一句,我真的很喜欢预先填充数据库的想法,现在的问题是使用这些属性设置我的用户模型。
    • 我已经通过创建表和使用迁移导入数据的示例编辑了答案。
    • 从提供的示例中,我决定做更多的研究,并且能够找到并使用 Geocoder gem。感谢您为我指明正确的方向来完成我的目标。我将创建一个详细说明步骤的答案。
    • 伟大的卡尔。祝你的项目好运。
    【解决方案2】:

    对于任何想要完成创建具有地理属性的模型的人,我发现并决定使用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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-06-23
      • 1970-01-01
      • 1970-01-01
      • 2013-05-02
      • 2016-05-01
      • 2010-09-12
      • 2011-10-17
      相关资源
      最近更新 更多