【问题标题】:Simplify multiple calls to ActiveRecord #find down to single line/SQL statement简化对 ActiveRecord #find 的多次调用到单行/SQL 语句
【发布时间】:2013-05-29 23:55:42
【问题描述】:

在将 ActiveRecord 中的两个 #find 方法的使用浓缩为单个语句和 SQL 查询时,我有点脑残。

我有一条 Sinatra 路由,其中​​提供了父记录和子记录的 slug(父记录有很多子记录)。 Atm 我首先通过#find_by_slug 调用找到父级,然后在匹配的父级关联中再次通过#find_by_slug 找到子级。

这导致了两个 SQL 查询,在我看来应该可以很容易地压缩成一个......只是我无法弄清楚 ActiveRecord 是如何实现的。

模型、路线和 AR 日志如下。使用 ActiveRecord 3.2

编辑

我意识到我需要澄清所要求的确切结果(我在当天很晚才写这篇文章)。我只需要Episode,但在atm 我首先要获得Show,才能到达Episode。我只需要 Episode 并认为它们必须是一种无需添加额外行并首先获取 Show 即可获取该对象的方法。

型号

class Show < ActiveRecord::Base
  has_many :episodes
end

class Episode < ActiveRecord::Base
  belongs_to :show
end

西纳特拉路线

get "/:show_slug/:episode_slug" do
  @show = Show.find_by_slug show_slug
  @episode = @show.episodes.find_by_slug episode_slug

  render_template :"show/show"
end

ActiveRecord 日志

Show Load (1.0ms)  SELECT `shows`.* FROM `shows` WHERE `shows`.`slug` = 'the-show-slug' LIMIT 1
Episode Load (1.0ms)  SELECT `show_episodes`.* FROM `show_episodes` WHERE `show_episodes`.`show_id` = 1 AND `show_episodes`.`slug` = 'episode-21' LIMIT 1

【问题讨论】:

  • 问题是什么?
  • 我在编辑中澄清了。我只需要 Episode 对象,并且认为必须有一种比进行两个 SQL 查询更有效的方法来获取该对象

标签: ruby activerecord sinatra arel


【解决方案1】:

如果你只需要@episode,你也许可以这样做

@episode = Episode.joins(:shows).where('shows.slug = ?', show_slug).where('episodes.slug = ?', episode_slug).first

如果您还需要@show,则必须有两个查询。

【讨论】:

  • 如果我错了,请纠正我,但这并没有考虑到episode_slug,所以我只会从所有节目中获得第一集来对抗一个节目?
  • 你完全正确,对不起。需要添加另一个.where。我已经改变了答案。
  • 谢谢!我稍后再试一下
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-01
  • 2011-07-22
  • 1970-01-01
  • 2023-03-07
相关资源
最近更新 更多