在我的应用程序中,一个城市可以有很多链接。链接将两个城市连接在一起并且是双向的,因此链接没有“从”和“到”。这会产生以下数据库架构
:
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
关系?或者我应该放弃这种方法并以某种方式更改我的数据库架构
?
最佳答案
我认为这与类似 facebook 的应用程序中的“友谊”是同样的问题,其中一个用户关注另一个用户,并且他们都互相关注,他们是 friend 。我以前也遇到过这个问题,我通过加入友谊表来解决它,这将带来所有相互的友谊。这里的区别在于,无论方向如何,连接始终存在,但总的来说,我看到了之前遇到的相同问题。 我的建议是:
创建链接时,始终双向创建, Link.new(端点1_id: city_1_id, 端点2_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
此解决方案可能不是解决此问题的最佳解决方案,但它绝对更灵活,因为它还允许您以相同的方式处理单向连接。
关于ruby-on-rails - 与两个外键的 has_many 关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27481056/