如何在 Rails 视图中呈现所有评论?
Posted
技术标签:
【中文标题】如何在 Rails 视图中呈现所有评论?【英文标题】:How do I render all Comments in a Rails view? 【发布时间】:2010-12-19 08:59:10 【问题描述】:我是 Rails 新手,所以请轻松一点。我创建了一个博客。我已经成功实现了 cmets 并将它们附加到每个帖子中。现在...我想在侧边栏中显示所有帖子中最新的 cmets 列表。我认为这里涉及两件事,对 comment_controller.rb 的更新,然后是来自实际页面的调用。这是 cmets 控制器代码。
class CommentsController < ApplicationController
def create
@post = Post.find(params[:post_id])
@comment = @post.comments.create!(params[:comment])
respond_to do |format|
format.html redirect_to @post
format.js
end
end
end
【问题讨论】:
【参考方案1】:如果您想以最近的顺序显示任何帖子中的所有 cmets,您可以这样做:
@comments = Comment.find(:all, :order => 'created_at DESC', :limit => 10)
在视图中你可以这样做:
<% @comments.each do |comment| -%>
<p>
<%= comment.text %> on the post <%= comment.post.title %>
</p>
<% end -%>
【讨论】:
这看起来像我要找的。刚试了一下,还是不行。我怀疑这是因为我错误地引用了它。第二部分(视图)被放入帖子的布局文件夹中......这是否会将@cmets 更改为 cmets,反之亦然? 如果你把它放在布局中,那么你可能只想像这样将 find 语句内联到布局中: 'created_at DESC' , :limit => 10).each 做 |comment| -%> 我不确定这将如何在评论中格式化,但希望这是有道理的。一般来说,将逻辑放在视图中是不受欢迎的,但我认为您可以访问每个页面上的 @cmets 变量的唯一另一种方法是,如果您在 ApplicationController 中的每个方法之前放置一个运行挂钩。【参考方案2】:我发布了一个单独的答案,因为代码在 cmets 中的格式显然完全不正确。
我猜你在上一个答案中遇到的问题是你在放
@comments = Comment.find(:all, :order => 'created_at DESC', :limit => 10)
在您的控制器方法之一中。但是,您希望 @cmets 可用于布局文件,因此您必须将其放在每个控制器的每个控制器方法上才能使其工作。尽管不赞成将逻辑放入视图中,但我认为在布局文件中执行以下操作是可以接受的:
<% Comment.find(:all, :order => 'created_at DESC', :limit => 10).each do |comment| -%>
<p>
<%= comment.text %> on the post <%= comment.post.title %>
</p>
<% end -%>
虽然我们可以将其移到 Comment 模型中,但要从视图中获取一些逻辑
class Comment < ActiveRecord::Base
named_scope :recent, :order => ["created_at DESC"], :limit => 10
现在您可以在视图中执行此操作:
<% Comment.recent.each do |comment| -%>
<p>
<%= comment.text %> on the post <%= comment.post.title %>
</p>
<% end -%>
这是一个不错的fat model and skinny controller
【讨论】:
我喜欢命名范围,尽管视图代码非常干净,但它完全绕过了控制器。我想我的第一枪是在 App Controller 的 before_filter 中调用Comment.recent
,但我可能错了。
+1 表示命名范围,但安迪是对的。这属于应用程序控制器中的前置过滤器。它仍然有效,但视图不应直接处理模型。
我看到了关于 before 过滤器的观点,但我认为这次我实际上更喜欢视图中的逻辑。在我看来,它比 Application 控制器中的之前的过滤器更干净,更能揭示意图,在这种情况下,您可能会在阅读代码后想知道 @cmets 变量的来源而挠头。至少如果您要将过滤器放在应用程序控制器中,您应该选择一个非常独特的变量名称,以免污染命名空间。所以@recent_cmets_for_layout 而不是@cmets。
我不同意这种方法,将逻辑排除在视图之外。 ApplicationController 中应该有一个before_filter
,或者把一个方法做成一个helper,可以在所有视图中访问。
我不喜欢在 Application 控制器中将其用作前置过滤器的另一个原因是,即使您没有为此显示 cmets,您也会访问数据库以获取每个控制器方法的 cmets方法(例如更新,或者如果您获取的是 xml 而不是 html)。除非您要在多个地方使用它,否则辅助方法似乎是不必要的,而且在我看来,它实际上只会在一个布局视图中使用。【参考方案3】:
我倾向于为此使用助手:
# in app/helpers/application_helper.rb:
def sidebar_comments(force_refresh = false)
@sidebar_comments = nil if force_refresh
@sidebar_comments ||= Comment.find(:all, :order => 'created_at DESC', :limit => 10)
# or ||= Comment.recent.limited(10) if you are using nifty named scopes
end
# in app/views/layouts/application.html.erb:
<div id='sidebar'>
<ul id='recent_comments'>
<% sidebar_comments.each do |c| %>
<li class='comment'>
<blockquote cite="<%= comment_path(c) -%>"><%= c.text -%></blockquote>
</li>
<% end %>
</ul>
</div>
【讨论】:
以上是关于如何在 Rails 视图中呈现所有评论?的主要内容,如果未能解决你的问题,请参考以下文章