我在应用程序中有以下两个模型
class City
end
class Suburb
end
一个城市正好有5个郊区,北,东,南,西和中心。我想通过一种相应的方法来引用每个郊区,这样,
北通过city.north访问
南通过city.south进入
我可以在cities
表中为每个郊区添加外键,并使用belongs_to
和has_one
来定义每个关联。但我发现它并不像它应该的那样直观。这是因为一个郊区属于一个城市,而不是一个城市。所以下面的定义并不直观。
class City
belongs_to :north, class_name: 'Suburb'
belongs_to :east, class_name: 'Suburb'
belongs_to :south, class_name: 'Suburb'
belongs_to :west, class_name: 'Suburb'
belongs_to :center, class_name: 'Suburb'
end
class Suburb
has_one :city
end
这可以按预期工作。但是当你读它时,它是相反的。 a郊区属于城市和城市has_one:north,has_one:east,has_one:south,has_one:west和has_one:center。
我还尝试在has_many :suburbs
模型上定义city
,并为郊区模型添加枚举属性direction
,而不是为每个方向使用define_method'定义方法,但是我看到它过度设计了。
有没有办法对此进行正确建模。
答案 0 :(得分:1)
您的架构没有任何内在错误,但为了便于讨论,让我提出一个满足您的架构问题的替代方案:
正如您所建议的那样,让Suburb
属于City
。为了强制郊区对其城市的唯一性,我们在direction
表格中添加suburbs
列,以及结合city_id
和{{1}的唯一复合索引}。这样,direction
只属于一个城市,而某个城市在给定的Suburb
中不能有多个Suburb
。
<强>分贝/迁移/ ... create_suburbs.rb 强>
direction
应用/模型/ city.rb 强>
class CreateDeviseUsers < ActiveRecord::Migration
def self.change
create_table(:suburbs) do |t|
# no need for `index: true` here because of composite key below
t.references :city, null: false
t.text :direction, null: false
t.index [:city_id, :direction], unique: true
end
end
end
我们的class City < ActiveRecord::Base
has_many :suburbs
end
模型现在有点复杂了。我们需要Suburb
的验证,以及每个可能值的范围。我想添加一个确保direction
始终是符号的getter。
应用/模型/ suburb.rb 强>
direction
现在我们可以使用范围访问和深入了解郊区:
class Suburb < ActiveRecord::Base
DIRECTIONS = [:north, :east, :south, :west]
belongs_to :city
validates :city, presence: true
validates :direction, inclusion: { in: DIRECTIONS }
# define a scope for each direction
DIRECTIONS.each { |d| scope d, -> { where(direction: d) } }
# convenience getter so that we can reason about direction using symbols
def direction
self[:direction].try(:to_sym)
end
end
如果你真的不喜欢# all north suburbs
north_suburbs = Suburb.north
# northern suburbs of a city (there can only be one!)
north_suburbs = city.suburbs.north
# as a model
north_suburb = city.suburbs.north.first
位,你可以定义便利访问器:
应用/模型/ city.rb 强>
first
答案 1 :(得分:0)
我想说你需要一个额外的模型,CitySuburb,这样城市和郊区都有很多CitySuburbs,CitySuburb属于City和Suburb。
您可以在CitySuburb上为北部,南部等设置范围,从而将City与north_suburb,south_suburb等关联。