"comments"没有方法错误,找不到并更正nil值以发表评论



我对rails比较陌生,并且正在尝试实现我与评论的第一个多态关联。

我正在运行轨道 3.2.3

编辑 - 当我尝试发表评论时,我的日志返回此错误:

Started POST "/comments" for 127.0.0.1 at 2012-05-20 13:17:38 -0700
Processing by CommentsController#create as HTML
Parameters: {"utf8"=>"✓",     "authenticity_token"=>"SOLcF71+WpfNLtpBFpz2qOZVaqcVCHL2AVZWwM2w0C4=", "comment"=>{"text"=>"Test this comment"}, "commit"=>"Create Comment"}
User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 101 LIMIT 1
Completed 500 Internal Server Error in 126ms
NoMethodError (undefined method `Comment' for nil:NilClass):
app/controllers/comments_controller.rb:13:in `create'

我已经尝试了SO和其他地方提供的许多不同的解决方案,包括下面Jordan的答案,我敢肯定,由于我自己的经验不足,但无法解决错误。

跟踪在注释控制器中调用第 13 行,我在下面的该行之后进行了注释以标记错误:

class CommentsController < ApplicationController
  def index
    @commentable = find_commentable
    @comments = @commentable.comments
  end
  def new
    @post = Post.find(params[:post_id])
  end
  def create
    @commentable = find_commentable
    @comment = @commentable.comments.build(params[:comment]) #<<<<LINE 13
    if @comment.save
      flash[:notice] = "Successfully created comment."
      redirect_to :id => nil
    else
      render :action => 'new'
    end
  end
  private
  def find_commentable
    params.each do |name, value|
      if name =~ /(.+)_id$/
        return $1.classify.constantize.find(value)
      end
    end
    nil
  end
end

帖子控制器:

def show
@post = Post.find(params[:id])
respond_to do |format|
  format.html  # show.html.erb
  format.json  { render :json => @post }
end
end

评论模板(在后期展示中(

<ul id="comments">
  <% if @comments %>
     <h2>Comments</h2>
         <% @comments.each do |comment| %>
        <li><%= comment.text %></li>
      <% end %>
  <% else %>
       <h2>Comment:</h2>
  <% end %>
</ul>
<%= simple_form_for [@commentable,Comment.new], :html => { :class => 'form-horizontal', :multipart => true } do |f| %>
   <fieldset>
       <%= f.input :text %>
       Upload Photo <%= f.file_field :photo %>
  </fieldset>
  <div class="form-actions">
    <%= f.submit nil, :class => 'btn btn-primary' %>
  </div>
<% end %>

展后:

<p id="notice"><%= notice %></p>
<div class="row">
<div class="span2 offset1">
   <%= image_tag @post.photo.url(:show) %>
</div>
    <div class="span5">
            <h1><%= @post.title %></h1>
            <p><%= @post.index_text.html_safe %></p>
           <p><%= @post.show_text.html_safe %></p>
            <%= render "comments/comment" %>
            <%= render "comments/form" %>
            <% if can? :update, @course %>
                <%= link_to 'Edit Post', edit_post_path(@post), :class => 'btn btn-mini' %>
                <%= link_to 'Delete Post', @post, 
                                    confirm: 'Are you sure?', 
                                    method: :delete, 
                                    :class => 'btn btn-mini' %>
                 <%= link_to 'New Post', new_post_path, :class => 'btn btn-mini' %>
            <% end %>
     </div>
<nav class="span2 offset1">
    <ul class="well">
        <li>Category 1</li>
        <li>Category 2</li>
    </ul>
</nav>
</div>
<div class="row offset2">
    <%= link_to 'Back to Posts', posts_path, :class => 'btn btn-mini' %>
</div>

路线:

  resources :posts, :has_many => :comments
  resources :comments

这可能是显而易见的事情,有更多经验的人可以解决。如果有什么想法,请告诉我。布莱恩

问题是@commentablenil,这意味着CommentsController#find_commentable正在返回nil。我认为您的正则表达式是合理的,因此这意味着find_commentable中发生了以下两件事之一:

  1. params中没有任何与您的正则表达式匹配的键。
  2. 您的正则表达式匹配,但结果表中没有任何 id 在 value 中的记录。

像往常一样通过检查数据库中的params和记录来调试它,以确保它们看起来像您期望的外观。

问题是你的find_commentable方法。

以下是传递给您的 CommentsController#create 的参数:

Started POST "/comments" for 127.0.0.1 at 2012-05-20 13:17:38 -0700
Processing by CommentsController#create as HTML
Parameters: {"utf8"=>"✓",     "authenticity_token"=>"SOLcF71+WpfNLtpBFpz2qOZVaqcVCHL2AVZWwM2w0C4=", "comment"=>{"text"=>"Test this comment"}, "commit"=>"Create Comment"}

这是您的评论控制器#创建:

def create
  @commentable = find_commentable
  @comment = @commentable.comments.build(params[:comment]) #<<<<LINE 13

def find_commentable
  params.each do |name, value|
    if name =~ /(.+)_id$/
      return $1.classify.constantize.find(value)
    end
  end
  nil
end

如您所见,find_commentable需要一个像 xx_id 这样的参数(例如,comments_id(,它使用它来搜索适当的类(在 comments_id 的情况下,它将是 Comment(,否则它将返回 nil。请参阅此处的分类和常量化。

您的参数不包含任何此类参数。所以,你总是得到一个 nil 对象。

您的find_commentable需要一些返工。我认为在nested_fields的情况下,它应该是一个表达式,例如

/(.+)_attributes$/ 

而不是

/(.+)_id$/. 

你需要有

:accepts_nested_attributes_for :commentable 

在注释模型类中。

我尝试了上述两个答案,但问题仍然存在。

最终咨询了一位朋友,他提出了以下解决方案,我喜欢它,因为它比我最初的尝试更优雅,更容易阅读(稍后,当我或其他人需要返回代码时(:

def find_commentable
  if params[:post_id]
    Post.find(params[:post_id])
  #elsif params[:other_id]
  #  Other.find(params[:other_id])
  else
    # error out?
  end
end

注释掉的部分将在我启动并运行其他关联后引用它们。

最新更新