【问题标题】:Rails ActiveRecord includes with run-time parameterRails ActiveRecord 包含运行时参数
【发布时间】:2016-05-07 05:57:03
【问题描述】:

我有几个模型...

class Game < ActiveRecord::Base
  belongs_to :manager, class_name: 'User'
  has_many :votes
end

class Vote < ActiveRecord::Base
  belongs_to :game
  belongs_to :voter, class_name: 'User'
end

class User < ActiveRecord::Base
  has_many :games, dependent: :destroy
  has_many :votes, dependent: :destroy
end

在我的控制器中,我有以下代码...

user = User.find(params[:userId])
games = Game.includes(:manager, :votes)

我想在游戏中添加一个属性/方法voted_on_by_user,它采用 user_id 参数并返回 true/false。总的来说,我对 Rails 和 Ruby 还比较陌生,所以我还没有想出一个干净的方法来完成这个。理想情况下,我想避免 N+1 queries problem 在我的游戏模型上添加类似的东西......

def voted_on_by_user(user)
  votes.where(voter: user).exists?
end

但我对 Ruby/Rails 不够了解,无法找到一种仅通过一次数据库往返即可完成此任务的方法。有什么建议吗?

我尝试/研究过的一些事情

  • Specifying conditions on Eager Loaded Associations

    • 我不知道如何指定这个或给包含一个不同的名称,如voted_on_by_user。这并没有给我想要的东西......

    Game.includes(:manager, :votes).includes(:votes).where(votes: {voter: user})

  • Getting clever with joins。所以也许像......

    Game.includes(:manager, :votes).joins("as voted_on_by_user LEFT OUTER JOIN votes ON votes.voter_id = #{userId}")

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:

    由于您已经includeing votes,您可以只使用非数据库操作计算votes:如果预加载了votesgame.votes.select{|vote| vote.user_id == user_id}.present? 不会执行任何其他查询。

    如果您一定要将该字段放入查询中,您可以尝试以与您的第二个想法非常相似的方式执行LEFT JOINGROUP BY(尽管您从连接中省略了game_id):

    Game.includes(:manager, :votes).joins("LEFT OUTER JOIN votes ON votes.voter_id = #{userId} AND votes.game_id = games.id").group("games.id").select("games.*, count(votes.id) > 0 as voted_on_by_user")
    

    【讨论】:

    • 不错!第一个建议就像一个魅力。我刚刚在游戏中添加了一个循环,并在模型中添加了一个 attr_accessor。第二个建议是抛出一个错误。 Mysql2::Error: ...for the right syntax to use near '*)>0 另外,我尝试编辑您的答案以使代码多行但因此不允许我这样做,因为编辑必须至少为 6 个字符.如果你能做到这一点,它可能会让未来的访问者更清楚:)
    • 抱歉,刚刚编辑。应该需要计算一个实际的列,所以count(votes.*)应该是count(votes.id)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-05
    • 1970-01-01
    • 1970-01-01
    • 2015-06-21
    • 1970-01-01
    • 2012-06-30
    • 1970-01-01
    相关资源
    最近更新 更多