这与another question I asked recently有关。但在我实现该问题的答案之前,我想尝试以更简单的方式执行此操作。
我在rails应用程序上构建了一个ruby,允许用户跟踪他们的锻炼。锻炼也有能力被评论。在我current_user
的信息中心视图中,我试图删除current_user评论过的所有评论。这是一个例子:
用户A在其上创建锻炼和用户B评论。用户C评论用户A的锻炼。我希望用户B在其仪表板视图中查看用户C的评论。
循环评论并从用户评论过的训练中提取所有评论的最有效方法是什么?这就像我想说的那样,但显然这不起作用:
<% current_user.comments.workouts.comments.each do |comment| %>
我一直在尝试使用named_scopes,但似乎无法弄明白。协会正如您所期望的那样。
User has_many :workouts
User has_many :comments
Workout belongs_to :user
Workout has_many :comments
Comment belongs_to :user
Comment belongs_to :workout
答案 0 :(得分:1)
由于您可能希望根据用户评论的训练来组织评论(而不是没有任何上下文的一个长的无差别的评论字符串),首先我建议使用:has_many =&gt;通过聚合用户评论过的锻炼,大致类似于(未经测试,显然):
has_many :commented_workouts, :through => :comments, :class_name => 'Workout', :source => :workout, :uniq => true, :order => "created_at desc"
然后你可以在你的erb中显示评论:
<% current_user.commented_workouts.each do |workout| %>
<%= workout.name %>:
<% workout.comments.each do |comment| %>
<%= comment.text %>
<% end %>
<% end %>
编辑:你也可以这样做:
<% current_user.commented_workouts.each do |workout| %>
<% workout.comments.sort{|x,y| x.created_at <=> y.created_at }.each do |comment| %>
<%= comment.user.name %> just commented on <%= workout.title %>:
<div><%= comment.text %></div>
<% end %>
<% end %>
编辑:或者像这样(注意添加到数组的限制):
class User
def watched_comments
commented_workouts.map(&:comments).flatten.sort{|x,y| x.created_at <=> y.created_at }
end
end
# and in the erb:
<% current_user.watched_comments[0,10].each do |comment| %>
<%= comment.user.name %> just commented on <%= comment.workout.title %>:
<div><%= comment.text %></div>
<% end %>
这里有一些讨厌的n + 1查询,这可能不是真正的性能。或者,您可以尝试在直接的SQL中完成所有操作,这样做会更好。像(sql ninjas无疑可以做得更好):
编辑:您还可以直接在SQL
中添加“限制”选项has_many :watched_comments, :class_name => 'Comment', :finder_sql => 'select * from comments, workouts where comments.workout_id = workout.id and workouts.id in (select workouts.id from workouts, comments where workouts.id = comments.id and comments.user_id = #{id}) order by comments.created_at desc limit 10'
答案 1 :(得分:0)
像
这样的东西<% workouts = []
current_user.comments.each do |comment|
unless workouts.include? comment.workout.id # prevents duplicates
workouts << comment.workout.id
comment.workout.comments.each do |comment|
# now comment refers to all comments for that workout
puts "#{comment.user.name} says #{comment.text}"
end
end
end %>
基本上,您可以获取与其每条评论相关联的锻炼并显示所有评论。
额外的家庭作业;)
答案 2 :(得分:0)
class User < ActiveRecord::Base
has_many :workouts
has_many :comments
def workouts_on_which_i_commented
comments.map{|x|x.workout}.uniq
end
def comment_stream
workouts_on_which_i_commented.map do |w|
w.comments
end.flatten.sort{|x,y| y.created_at <=> x.created_at}
end
end