【问题标题】:Include associated model for all objects (in index action)包括所有对象的关联模型(在索引操作中)
【发布时间】:2014-05-29 21:54:14
【问题描述】:

我正在尝试为我的应用程序开发评级,用户可以在其中为评论设置特定评级。为了做到这一点,我遵循了以下tutorial

这是我的联想:

class Rating < ActiveRecord::Base
  belongs_to :comment
  belongs_to :user
end

class Comment < ActiveRecord::Base
  has_many :ratings
  belongs_to :user
end

class User < ActiveRecord::Base
  has_many :ratings
  has_many :comments
end

我的问题是,在我的 cmets 控制器的索引操作中,我需要包含用户对该评论所做的评分。在教程中只展示了如何通过这样做来选择特定的评级:

@rating = Rating.where(comment_id: @comment.id, user_id: @current_user.id).first 

unless @rating 
  @rating = Rating.create(comment_id: @comment.id, user_id: @current_user.id, score: 0) 
end

但是,我会有几个评分,因为在我的控制器中我有:

def index
  @comments = @page.comments #Here each comment should have the associated rating for the current_user, or a newly created rating if it does not exist.
end

【问题讨论】:

    标签: ruby-on-rails associations rating


    【解决方案1】:

    您想在评级的 user_id 与当前用户匹配的地方找到评论的评级。

    <%= comment.ratings.where(user_id: current_user.id).first %>
    

    但是这种逻辑在视图中相当麻烦,更好的策略是在Rating 中定义一个范围,返回特定用户的所有评分。

    class Rating
      scope :by_user, lambda { |user| where(user_id: user.id) }
    end
    
    class Comment
      # this will return either the rating created by the given user, or nil
      def rating_by_user(user)
        ratings.by_user(user).first 
      end
    end
    

    现在在您看来,您可以访问当前用户创建的评论的评分:

    <% @comments.each do |comment| %>
      <%= comment.rating_by_user(current_user) %>
    <% end %>
    

    如果您想在索引页面中快速加载所有评分,您可以执行以下操作:

    def index
      @comments = page.comments.includes(:ratings)
    end
    

    然后您可以通过以下方式找到正确的评分:

    <% @comments.each do |comment| %>
      <%= comment.ratings.find { |r| r.user_id == current_user.id } %>
    <% end %>
    

    这将返回正确的评分而不生成任何额外的 SQL 查询,但代价是为每个评论加载每个相关的评分。


    我不知道 ActiveRecord 中有一种方法可以急切加载 has_many 关系的子集。请参阅 this 相关的 StackOverflow 问题,以及包含有关预加载的更多信息的 this 博客文章。

    【讨论】:

    • 所以,我不能在执行时使用包含:@page.cmets ?
    • 什么意思?您是否尝试同时加载评级和 cmets?
    • hjing,理想情况下,page.cmets 每个评论都有当前用户的评分。是的。
    • 你的意思是你想急切地加载每条评论的每一个评分吗? guides.rubyonrails.org/…,或者您是否想要一个名为 @ratings 的单独实例变量,它只包含当前用户对 @comments 实例变量中加载的 cmets 的评分?
    • 我想为每条评论加载每个评级(由当前用户完成)。每个用户的评论只能有一个评分。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-05
    • 1970-01-01
    • 1970-01-01
    • 2017-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多