2

Placeという親クラスがあります。

# Parent class for Country, City and District
class Place < ActiveRecord::Base
end

class Country < Place
  has_many :cities, foreign_key: "parent_id"
  has_many :districts, through: :cities
end

class City < Place
  belongs_to :country, foreign_key: "parent_id"
  has_many :districts, foreign_key: "parent_id"
end

class District < Place
  belongs_to :city, foreign_key: 'parent_id'
  has_one :country, through: :city
end

スキーマ:

create_table "places", force: true do |t|
  t.string   "name"
  t.string   "type"
  t.integer  "parent_id"
  t.datetime "created_at"
  t.datetime "updated_at"
end

add_index "places", ["parent_id"], name: "index_places_on_parent_id"
add_index "places", ["type"], name: "index_places_on_type"

以下は期待どおりに機能します。

@country.cities # => Returns all of the cities that belong to this country
@city.districts # => Returns all of the districts that belong to this city

しかし、これは私が思ったようには機能しません:

@country.districts # => Does not return all of the districts belonging to cities in this country

性感染症にどのように対処すればよいか、誰か説明できますか?

アップデート

からの出力SQLクエリは次のとおりです@country.districts

SELECT "places".* FROM "places" INNER JOIN "places" "cities_districts_join" ON "places"."parent_id" = "cities_districts_join"."id" WHERE "places"."type" IN ('City') AND "places"."type" IN ('District') AND "cities_districts_join"."parent_id" = ?  [["parent_id", 1]]

問題は、両方のリレーションに同じ結合テーブルを使用していることだと思いますが、結合テーブルの名前を変更する「Rails の方法」があるかどうかはわかりません (エレガントに)

4

2 に答える 2

2

これは ActiveRecord にとって難しいケースです。検索する必要がある自己結合の列districtsが STI インスタンスであることを推測する必要があります。どうやら、これを正しく行うほど賢くないようです。唯一のテーブルはplacesであるため、このクエリが生成されることはそれほど驚くことではありません。

SELECT "places".* FROM "places" 
INNER JOIN "places" "cities_districts_join" 
ON "places"."parent_id" = "cities_districts_join"."id" 
WHERE "places"."type" IN ('City')   <<<<< ERROR HERE
AND "places"."type" IN ('District') 
AND "cities_districts_join"."parent_id" = ?  

ご覧のとおり、1 つの文字列が と の両方Cityになることはできないため、型チェックは失敗するはずDistrictです。の最初の節WHEREが代わりにある場合、すべてが機能します

WHERE "cities_districts_join"."type" IN ('City')  

私は関係についていくつかのオプションを試しましたが (考えられる:class_nameかもしれません)、喜びはありませんでした。

この制限は SQL で回避できます。has_many ... throughクラス内のを削除し、にCountry置き換えます

def districts
  District.find_by_sql(['SELECT * from places AS city 
                           INNER JOIN places AS district 
                         ON district.parent_id = city.id 
                         WHERE city.parent_id = ?', id])
end

または、他の誰かがよりエレガントな方法を見るかもしれません。そうでない場合は、これを Rails 開発の問題として投稿することを検討してください。興味深い事例です。

于 2013-10-07T02:28:26.093 に答える
-1

モデルの継承を変更する必要があると思います。

class Country < Place

class City < Country

class District < City

そして、

has_one :country through: :city 

ライン。

下にスクロールして、STI に関する情報を見つけます http://api.rubyonrails.org/classes/ActiveRecord/Base.html

于 2013-10-03T03:40:07.577 に答える