2

只是一个与 Rails 最佳实践相关的问题:

假设我们有一个 Post 和一个 Comment 模型。相同的部分用于在索引视图和显示视图上呈现帖子。在该部分内部是对呈现评论的另一个部分的引用。

post_controller.rb

def index
  @posts = Post.all
end

def show
  @post = Post.find(params[:id])
end

_post.html.haml

.post
  = post.content 
  = render 'comments/list', :comments => post.comments

评论/_list.html.haml

- comments.each do |c|
    c.comment

现在假设对于帖子索引视图,我们只想显示每个帖子的最后 3 条评论,但在显示视图中我们希望显示帖子的所有评论。因为使用了相同的部分,我们不能编辑调用来限制评论。实现这一目标的最佳方法是什么?目前我已经将它抽象为一个助手,但是感觉有点狡猾:

def limited_comments(comments)
  if params[:controller] == 'posts' and params[:action] == 'show'
    comments
  else
    comments.limit(3)
  end
end

这意味着_post.html.haml更改为读取

= render 'comments/list', :comments => limited_comments(post.comments)

它有效,但感觉不像 Rails 方式。我猜有一种使用范围的方法,但我似乎无法弄清楚。

4

2 回答 2

1

您可以对索引操作持续 3 条评论并分配给@comments变量,对于显示操作,您可以加载该帖子的所有评论。所以它变成

def index
  @posts = Post.all
  @comments = Comment.order("created_at desc").limit(3)
end

def show
  @posts = Post.all
  @comments = @post.comments.order("created_at desc").limit(3)
end

在视图中它只是

= render 'comments/list', :comments => @comments
于 2013-02-27T17:29:47.280 回答
1

我相信@benchwarmer 想说的是最好将参数传递给_post partial。直截了当的@comments 不起作用,但类似下面的代码可能:

def index
  @posts = Post.all
  render :partial => @posts, :locals => { :max_comments => 3 }
end

def show
  @post = Post.find(params[:id])
  render :partial => @post, :locals => { :max_comments => false }
end

在 post.html.haml 中:

= render 'comments/list', :comments => limited_comments(post.comments,max_comments)

你的助手:

def limited_comments(comments,max_comments)
  max_comments ? comments.limit(max_comments) : comments
end

我没有编译,因此您可能需要进一步处理传递给 render :partial 的参数(在这种情况下,您可能必须单独设置 :partial 和 :object/:collection ,否则,我不'不记得也没有尝试)。但我希望这个想法很明确——将逻辑表示(所有评论或最后 3 条)与处理路径(哪个控制器/动作)分开。可能您稍后会想要显示带有嵌入另一个列表中的评论的帖子(用户列表的最后 3 个帖子),那么这种分离将派上用场。

如果您不想在控制器级别公开所有内部逻辑细节,您也可以这样做:

def index
  @posts = Post.all
  render :partial => @posts, :locals => { :comments_list_type => :short }
end

def show
  @post = Post.find(params[:id])
  render :partial => @post, :locals => { :comments_list_type => :full }
end

然后,在 post.html.haml 中:

= render 'comments/list', :comments => build_comments_list(post.comments,comments_list_type)

你的助手:

def limited_comments(comments,comments_list_type)
  case comments_list_type
    when :short
      comments.limit(3) 
    when :long
      comments.limit(10) 
    when :full
      comments
  end
end
于 2013-02-27T22:24:49.120 回答