0

使用从 API 导出的数据

我正在构建一个排行榜,显示每个团队的 Team.name 以及选择该特定团队作为他们最爱的用户。我还填充了另一个属性 Favorite.points; 显示为相应团队积累的最多积分的用户。

以下是我正在使用的模型:

收藏夹.rb

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

团队.rb

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

用户.rb

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

为了开始这个过程,我试图匹配 Team.external_id 和 Favorite.team_id 之间共有的 id(User.external_id => Favorites.user_id 也是如此)。我可以使用 Team.find_all_by_external_id(3333) 来获取所有具有 external_id 为“3333”的 Team 对象的 ID,Favorite.find_all_by_team_id 也是如此。

获取/显示我正在寻找的数据的下一个最佳步骤是什么?SQL 连接子句是最好的吗?还是编写 if 语句匹配值并遍历 JSON 数组更好?

任何帮助表示赞赏,谢谢!

4

1 回答 1

2

这将为您提供与表中行的属性team_id匹配的所有收藏夹,用于特定团队(此处为具有 id 的团队):external_idteams3333

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

正如我在评论中提到的那样,这里的棘手之处在于,当您将模型上的外部id Team(您创建的属性)与模型team_id上的Favorite(使用整个rails获取和分配关联)。

一旦您尝试真正获得您在上述加入中找到的最爱的团队,您就会看到问题:

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。请注意,它不是在寻找外部id 为 3333 的团队,这正是您想要的。

根本问题是您试图使用外部 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 进行过滤。

希望有帮助!

更新

从评论看来,team_id您的Favorite模型上的 似乎是从 API 数据定义的,这意味着 id 对应于external_id您的Team模型。这是一个坏主意:在 rails 中,外键<model name>_idteam_id,user_id等)具有特定含义:id 被理解为映射到id相应关联模型的字段(Team)。

为了让您的关联起作用,您需要使用 ids(而不是外部 ids)用于任何地方的关联(也与您的User模型一起使用)。为此,您需要将 API 中定义的关联转换为 rails 应用程序中的 id。当您从 API 添加收藏夹时,找到与idAPI 团队 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 加载的每个收藏夹查询数据库,这在性能方面可能会付出高昂的代价,但因为您只在没什么大不了的时候才这样做。

于 2013-01-20T01:42:10.647 回答