在我的应用中,一个城市可以有很多链接。链接将两个城市连接在一起并且是双向的,因此链接没有“从”和“到”。这导致以下db schema
:
create_table "links", force: true do |t|
t.integer "endpoint1_id"
t.integer "endpoint2_id"
t.integer "capacity"
end
create_table "cities", force: true do |t|
t.string "name"
t.string "lat"
t.string "long"
end
在我的ActiveRecord模型中,我想声明两个表之间的关系。因为我在设置has_many
关系时似乎无法声明两个外键,所以我就这样解决了这个问题:
class City < ActiveRecord::Base
# has_many with two foreign keys?
# has_many :links
def links
Link.where("endpoint1_id=? OR links.endpoint2_id=?", id, id)
end
end
class Link < ActiveRecord::Base
belongs_to :endpoint1, :class_name => 'City'
belongs_to :endpoint2, :class_name => 'City'
end
这允许我执行:City.find(1).links
但似乎不是一个正确的解决方案,并且不强制执行任何继承。此外,从link
我无法找到关系城市,除非我同时通过city.endpoint1
和city.endpoint2
。
是否有更优雅的解决方案来定义与两个外键的has_many
关系?或者我是否可以放弃这种方法并以某种方式改变我的db schema
?
答案 0 :(得分:-1)
我认为这与在类似Facebook的应用程序中的“友谊”是一样的问题,其中一个用户跟随另一个用户,并且他们都互相关注,他们是朋友。我之前有过这个,我通过加入友谊表来解决它,这将给予所有相互的友谊。这里的不同之处在于,无论方向如何,连接始终存在,但总的来说,我看到了之前遇到的同样问题。 我的建议是:
创建链接时,始终要创建它们, Link.new(endpoint1_id:city_1_id,endpoint2_id:city_2_id) Link.new(endpoint2_id:city_1_id,endpoint1_id:city_2_id)
然后从一个城市的连接中搜索时,从城市和链接中选择一个sql语句,如下所示:
def connections # find your cities, where connections run both ways
City.find_by_sql "
select * from cities
where id in
(select f2.endpoint1_id from links as f1 inner join links as f2 on (f1.endpoint1_id = f2.endpoint2_id) and (f1.endpoint2_id = f2.endpoint1_id) and (f1.endpoint1_id = #{id.to_i}))" # normally this can cause an sql injection, but here it is handled by to_i
end
此解决方案可能不是此问题的最佳解决方案,但它肯定更灵活,因为它还允许您以相同的方式处理单向连接。