0

APIからエクスポートされたデータの操作

各チームのTeam.nameと、その特定のチームをお気に入りとして選択したユーザーを表示するリーダーボードを作成しています。また、別の属性Favorite.pointsを設定しています。それぞれのチームで最も多くのポイントを獲得したユーザーを表示します。

使用しているモデルは次のとおりです。

Favorite.rb

class Favorite < ActiveRecord::Base
  belongs_to :users
  belongs_to :teams
end

Team.rb

class Team < ActiveRecord::Base
  has_many :favorites
  has_many :users, :through => :favorites 
end

User.rb

class User < ActiveRecord::Base
  has_many :favorites
  has_many :teams, :through => :favorites 
end

このプロセスを開始するために、Team.external_idとFavorite.team_idの間で共通のIDを一致させようとしています(User.external_id => Favorite.user_idの場合も同じです)。Team.find_all_by_external_id(3333)を使用して、external_idが「3333」であるすべてのTeamオブジェクトのIDを取得できます。これは、Favorite.find_all_by_team_idにも当てはまります。

探しているデータを取得/表示するための次の最善のステップは何ですか?SQL結合句は最適ですか?または、ステートメントが値と一致し、JSON配列を反復処理する場合に記述したほうがよいでしょうか。

どんな助けでもありがたいです、ありがとう!

4

1 に答える 1

2

これにより、特定のチーム(ここではidを持つチーム)について、テーブル内の行の属性にteam_id一致するすべてのお気に入りが取得されます。external_idteams3333

Favorite.joins("left outer join teams on teams.external_id = favorites.team_id")\
  .where('team_id' => 3333)

ここで注意が必要なのは、コメントで述べたように、モデルの外部ID (作成した属性)をモデルの外部ID (使用される属性)と一致させると、Railsの関連付けに完全に反することです。アソシエーションを取得して割り当てるためのレール全体)。Teamteam_idFavorite

上記の参加で見つけたお気に入りのチームを実際に取得しようとするとすぐに、問題が発生します。

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_idFavoriteつまり、IDはモデルのに対応していexternal_idますTeam。これは悪い考えです。レールでは、外部キー<model name>_idteam_id、、など)には特定の意味があります。IDは、対応する関連モデル( )user_idのフィールドにマップされると理解されます。idTeam

アソシエーションを機能させるには、あらゆる場所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にクエリを実行する必要があります。これは、パフォーマンスの面でコストがかかる可能性がありますが、一度だけ実行するため、大したことではありません。

于 2013-01-20T01:42:10.647 に答える