我有一个应用程序,其中数据库表things
包含locatable
个对象 - 如城市,地址,聚会场所,公交车站等。
一个可定位的对象可以例如成为一个城市和国家。这些对象通过多态has_one关联连接到Thing,因为每个City代表一个可定位的Thing。但是国家也has_many :cities
,因为所有国家都位于特定国家。我正在使用这种结构做各种奇怪的关联请求,到目前为止(使用Rails 3.0)它运行良好。但是使用Rails 4.2,它失败了,见下文。
这是数据库结构:
Thing: id, locateable_id, locateable_type, lat, lng, name, country_id, city_id, ...
City: id, name, country_id
Country: id, name
代码:
class Thing < AR::Base
belongs_to :locateable, :polymorphic => true
belongs_to :country
belongs_to :city
...
end
class Country < AR::Base
has_one :thing, as: :locatable
has_many :cities
...
end
class City < AR::Base
has_one :thing, as: :locatable
...
end
在Rails 3.0.20,Ruby 1.9.3中,调用此代码
1.9.3-p551 :005 > Thing.find_by_name("Aachen").country.thing
# Thing Load (0.5ms) SELECT "things".* FROM "things" WHERE "things"."name" = 'Aachen' LIMIT 1
# Country Load (0.3ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = 276 ORDER BY name LIMIT 1
# Thing Load (0.3ms) SELECT "things".* FROM "things" WHERE ("things".locateable_id = 276 AND "things".locateable_type = 'Country') LIMIT 1
=> <Thing id: 355371, locateable_id: 276, locateable_type: "Country", name: "Deutschland", country_id: 276, ...>
将返回这个城市的国家。在Rails 4.2.5,Ruby 2.2.1中,完全相同的代码再次返回城市的事物:
2.2.1 :008 > Thing.find_by_name("Aachen").country.thing
# Thing Load (0.4ms) SELECT "things".* FROM "things" WHERE "things"."name" = $1 LIMIT 1 [["name", "Aachen"]]
# Country Load (0.3ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 ORDER BY name LIMIT 1 [["id", 276]]
=> <Thing id: 105548, locateable_id: 3, locateable_type: "City", name: "Aachen", country_id: 276, city_id: 3, ...>
为什么呢?这似乎不正确。特别是因为它不一致:
> Country.find(276).thing
=> #<Thing id: 355371, locateable_id: 276, locateable_type: "Country", coordinate_id: nil, name: "Deutschland", ...>
# but
> c = Thing.find_by_name("Aachen").country
=> <Country id: 276, name: "Deutschland">
> c.thing
=> #<Thing id: 105548, locateable_id: 3, locateable_type: "City", coordinate_id: nil, name: "Aachen", ...>
这可能是Rails中的一个错误吗?或者我是否滥用多态关联系统?