これにより、特定のチーム(ここではidを持つチーム)について、テーブル内の行の属性にteam_id
一致するすべてのお気に入りが取得されます。external_id
teams
3333
Favorite.joins("left outer join teams on teams.external_id = favorites.team_id")\
.where('team_id' => 3333)
ここで注意が必要なのは、コメントで述べたように、モデルの外部ID (作成した属性)をモデルの外部ID (使用される属性)と一致させると、Railsの関連付けに完全に反することです。アソシエーションを取得して割り当てるためのレール全体)。Team
team_id
Favorite
上記の参加で見つけたお気に入りのチームを実際に取得しようとするとすぐに、問題が発生します。
f = Favorite.joins("left outer join teams on teams.external_id = favorites.team_id")\
.where('team_id' => 3333).first
=> #<Favorite id: 1, user_id: nil, team_id: 3333, points: nil, created_at: ... >
f.team
Team Load (0.3ms) SELECT "teams".* FROM "teams" WHERE "teams"."id" = 3333 LIMIT 1
=> nil
何が起きてる?クエリをよく見ると、railsが3333のチームを選択していることがわかります。外部IDが3333のチームを検索していないid
ことに注意してください。これは、必要なものです。
基本的な問題は、関連付けに外部ID(APIに固有のID)を使用しようとしていることですが、これは機能しません。そして確かに、このようにする理由はありません。
代わりに、これを試してください:
Favorite.joins(:team).where('teams.external_id = 3333')
これにより、チームの外部IDが3333であるすべてのお気に入りが取得されます。Railsは、に参加しteams.id = favorites.team_id
、次の方法でフィルタリングすることでこれを行うことに注意してteams.external_id
ください。
SELECT "favorites".* FROM "favorites" INNER JOIN "teams"
ON "teams"."id" = "favorites"."team_id" WHERE (teams.external_id = 3333)
あなたは逆に同じことをすることができます:
Team.joins(:favorites).where('teams.external_id = 3333')
これはSQLを生成します:
SELECT "teams".* FROM "teams" INNER JOIN "favorites"
ON "favorites"."team_id" = "teams"."id" WHERE (teams.external_id = 3333)
id
外部IDではなく、結合で使用されているのはであることに再度注意してください。これはこれを行う正しい方法id
です。関連付けに従来型を使用し、必要に応じて(カスタム定義、API固有の)外部IDでフィルタリングします。
お役に立てば幸いです。
更新:
コメントから、モデルのはAPIデータから定義されているようですteam_id
。Favorite
つまり、IDはモデルのに対応していexternal_id
ますTeam
。これは悪い考えです。レールでは、外部キー<model name>_id
(team_id
、、など)には特定の意味があります。IDは、対応する関連モデル( )user_id
のフィールドにマップされると理解されます。id
Team
アソシエーションを機能させるには、あらゆる場所(User
モデルでも)のアソシエーションにID(外部IDではなく)を使用する必要があります。これを行うには、APIで定義された関連付けをrailsアプリのIDに変換する必要があります。APIからお気に入りを追加するときはid
、APIチームIDに対応するチームを見つけます。
external_team_id = ... # get external team id from API JSON data
favorite.team_id = Team.find_by_external_id(external_team_id).id
したがってid
、指定された外部IDを使用してチームのを割り当てています。APIからロードするお気に入りごとにDBにクエリを実行する必要があります。これは、パフォーマンスの面でコストがかかる可能性がありますが、一度だけ実行するため、大したことではありません。