Rails 4视图在视图中渲染额外的对象?

时间:2015-03-01 01:35:17

标签: ruby-on-rails

我有评论作为文章的子资源,如下所示:

resources :articles do
    resources :comments
end

我希望每篇文章的展示页面都能显示所有相应的评论,并且有一个表单,用户(如果已登录)可以创建与该文章相对应的新评论。

以下是ArticlesController的展示操作:

  def show
    @comment = @article.comments.build
    if user_signed_in?
      @comment.user_id = current_user.id
    end
    respond_with(@article)
  end

以下是CommentsController的相关代码:

 before_action :set_article

 ...

 def create
    @comment = @article.comments.create(comment_params)
    @comment.user_id = current_user.id
    if @comment.save
      flash[:notice] = "Comment successfully created!"
    end
    redirect_to @article
  end

  ...

 private

    def set_article
      @article = Article.find(params[:article_id])
    end

  end

以下是文章展示视图:

<b>Post comments:</b><br />

<table>
  <thead>
    <tr>
      <th>User email</th>
      <th>Comment</th>
    </tr>
  </thead>

  <tbody>
    <% @article.comments.each do |comment| %>
      <tr>
        <td><%= comment.user.email %></td>
        <td><%= comment.body %></td>
      </tr>
    <% end %>
  </tbody>
</table>
<br />

<%= form_for ([@article, @comment]) do |f| %>
  <div class="field">
    <%= f.text_area :body, placeholder: "Compose new comment..." %>
  </div>
  <%= f.submit "Post" %>
<% end %>

以下是我需要解决的两种情况:

  1. 当没有用户登录时,视图无法呈现,因为comment.user返回nil
  2. 当用户登录时,会显示每篇文章的幻像评论,因为ArticlesController中的show操作正在使用@comment = @ article.comments.build构建新的(空)评论
  3. 同时解决这两个问题的最佳方法是什么?

2 个答案:

答案 0 :(得分:1)

如果您不想在视图中执行此操作,则可以在控制器中执行此类操作。

def show
  @comment = Comment.new(:article => @article)
  respond_with(@article)
end

这不会将评论添加到article.comments数组中,也不会尝试呈现空白评论。

您是否需要在show动作的表单中设置注释的user_id?如果没有,您可以在创建

中执行此操作
def create
  @comment = Comment.new(comment_params)
  @comment.article = @article
  @comment.user = current_user
  if @comment.save
    flash[:notice] = "Comment successfully created!"
    redirect_to @article
  else
    render :show
  end

end

这样做的好处 - 您现在可以处理表单中的错误(例如,如果他们提交空白评论或最小字符)。即使您使用javascript / disabled按钮在视图中处理它,也很高兴服务器也支持验证和错误。

答案 1 :(得分:0)

开个玩笑,明白了。

build调用放入表单而不是ArticleController

<%= form_for ([@article, @article.comments.build]) do |f| %>
  <div class="field">
    <%= f.text_area :body, placeholder: "Compose new comment..." %>
  </div>
  <%= f.submit "Post" %>
<% end %>

并删除show动作中的所有内容:

  def show
    respond_with(@article)
  end