Ruby on rails 带有祖先数据模型的rails半复杂STI规划路线和控制器

Ruby on rails 带有祖先数据模型的rails半复杂STI规划路线和控制器,ruby-on-rails,ruby-on-rails-3,routes,mongoid,sti,Ruby On Rails,Ruby On Rails 3,Routes,Mongoid,Sti,我正试图找出为特定用例管理控制器和模型的最佳方法 我正在构建一个审查系统,在这个系统中,用户可以使用多态性审查表对几种不同的类型进行审查 Country (has_many reviews & cities) Subdivision/State (optional, sometimes it doesnt exist, also reviewable, has_many cities) City (has places & review) Burrow (optional,

我正试图找出为特定用例管理控制器和模型的最佳方法

我正在构建一个审查系统,在这个系统中,用户可以使用多态性审查表对几种不同的类型进行审查

Country (has_many reviews & cities)
Subdivision/State (optional, sometimes it doesnt exist,  also reviewable, has_many cities) 
City (has places & review)
Burrow (optional, also reviewable ex: Brooklyn)
Neighborhood (optional & reviewable, ex: williamsburg)
Place (belongs to city)
我还想知道如何增加更多的复杂性。我还想偶尔包括细分。。。也就是说,对于美国,我可能会加上德克萨斯州或德国的巴威里亚州,让它也可以被审查,但并不是每个国家都有地区,甚至那些有地区的国家也可能永远不会被审查。所以它一点也不严格。我希望它尽可能简单和灵活

如果用户只需登陆一个表单,选择一个城市或一个国家,然后使用Foursquare中的数据向下搜索,找到城市中的某个特定位置并进行审查,那就太好了

我真的不知道该走哪条路?例如,如果我有一个国家和一个城市。。。然后我决定加一个洞穴

我能给纽约市的地方标签(如威廉斯堡、布鲁克林)和纽约市的标签吗

标签更灵活,可以选择性地解释他们可能在哪些地区,标签属于一个城市,但也有位置,可以查看

因此,我正在为任何做过相关工作的人寻求建议


使用Rails 3.2和mongoid。

听起来是嵌套路由/资源的好选择。在
routes.rb
中,执行以下操作:

resources :cities do
  resources :reviews
end

resources :countries do
  resources :reviews
end

resources :places do
  resources :reviews
end
它应该沿着
耙路线产生一些东西

   reviews_cities GET /cities/:id/reviews     {:controller=>"reviews", :action=>"index"}
reviews_countries GET /countries/:id/reviews  {:controller=>"reviews", :action=>"index"}
   reviews_places GET /countries/:id/reviews  {:controller=>"reviews", :action=>"index"}

...etc., etc.
在控制器操作中,查找匹配
可查看
记录的
:id
,并仅发回附加到该
可查看
对象的查看


另外,请参阅和的
嵌套资源
部分,其中有一个关于路由和使所有内容正确排列的快速部分。

我可能会保持我的数据模型非常不受限制,并处理与控制器/视图中显示的过滤器相关的任何细节。制作一个映射表,您可以在其中以多态方式映射属性(即城市、自治区、州、国家),也可以以多态方式映射到可查看的

通过假设多对多,您的模式尽可能灵活,并且您可以使用模型中的验证或过滤器限制要创建的映射

它基本上是使用标签,就像你逃避的那样,但实际上并不是使用标签模型本身,而是与不同模型的多态关联,所有这些模型都像标签一样


保持数据库模式干净,并保持ruby中的业务逻辑。

我构建了一些非常相似的东西,发现了两种完全不同的方式,它们都工作得很好

方式1:国家»次国家»城市»社区 对我来说,第一个有效的方法是与国家、次国家、城市、社区合作。这很好地映射到主要的地理编码服务,并且对于大多数简单的使用来说已经足够了。这可以是STI(如您的示例中所示),也可以是多个表(我是如何做到的)

在您的示例中,您编写了“细分/状态”。我的两分钱是为了避免使用这些术语,而是使用“Subcountry”,因为这是ISO标准,当其他开发商认为某个细分市场是一个很小的住宅小区时,或者当您所在的非美国国家不使用州,而是使用省时,您可以避免一些混淆

这就是我在尝试了很多模型名称(如地区、地区、区域、地带等)后所决定的,并放弃了这些太模糊或太具体的名称。在你的STI案例中,使用更多的名字可能是好的

令人惊讶的是,编写多层次的协会是一个很大的帮助,例如说country.cities(跳过subcountry)。这是因为有时中介模型不存在(即没有子国家)。在你的性病中,这可能更棘手

另外,如果您对表进行非规范化,您将获得很大的加速,例如,我的城市表有一个国家字段。这使得更新信息变得有点棘手,但这是值得的。你的STI可以通过使用标签来实现类似的功能

方式2:带边框的lat/lng形状列表区域 第二种方法是使用任意分区模型并存储经纬度形状。这为您提供了极大的灵活性,并且您可以预先计算形状何时包含其他形状,或与其他形状相交。所以你的“向下钻取”变成了“立即向我展示这一个里面的形状”

Postgres为此提供了一些很好的地理编码帮助,您可以通过使用最小/最大lat/lng边界框来加快查找速度。我们还存储了一些数据,如分区的预期中心点(我们将在地图上放置一个大头针的位置)和半径(用于计算查询,如“显示y距离内的所有x项”)


通过这种方法,我们可以制作有趣的区域,如“纽约百老汇”,它实际上不是一个街区,而不是一条长街,以及“亚马逊盆地”,它是由河流而不是一个国家定义的。

STI模型具有祖先和多形性关系。

我为以前的项目构建了类似的东西,并选择了带有祖先的STI,因为它非常灵活,允许对节点树进行建模。并非所有的中间节点都必须存在(如您的State/subsection/Subcountry示例)

对于Mongoid,至少有两个祖先宝石:Mongoid祖先和mongestry(以下链接)

将STI与祖先一起使用的另一个好处是,您还可以对其他位置相关的节点进行建模,比如餐馆或其他地方

您还可以将地理位置信息lat/lon添加到所有节点,以便对它们进行地理标记。 在下面的示例中,我只使用了一组地理位置坐标(中心点),但您当然也可以添加几个地理位置来建模边界框

您可以按自己喜欢的任何顺序排列节点,例如通过
此_
# app/models/geo_node.rb

class GeoNode  # this is the parent class; geo_nodes is the table name / collection name.
  include Mongoid::Document
  has_ancestry   # either this
  has_mongestry  # or this
  has_many :reviews, :as => :reviewable

  field :lat, type: Float
  field :lon, type: Float

  field :name, type: String
  field :desc, type: String
  # ...
end

# app/models/geo_node/country.rb
class Country < GeoNode
end

# app/models/geo_node/subcountry.rb
Class Subcountry < GeoNode
end

# app/models/geo_node/city.rb
class City < GeoNode
end


# app/models/review.rb
class Review
  include Mongoid::Document
  belongs_to :reviewable, :polymorphic => true
  field :title
  field :details
end