在Rails中使用相同的部分时显示不同数据的最佳实践

时间:2013-02-27 16:23:56

标签: ruby-on-rails scopes

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

假设我们有帖子和评论模型。相同的partial用于在索引视图和show视图上呈现帖子。在partial里面是对另一个呈现注释的部分的引用。

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方式。我猜测范围有一种方法,但我似乎无法弄明白。

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

我没有编译,所以你可能需要进一步处理你传递给渲染的参数:partial(可能你必须单独设置:partial和:object /:在这种情况下是集合,或者是smth else ,我不记得也没试过)。但我希望,这个想法很清楚 - 保持逻辑表示(所有注释或最后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