嵌套资源的表单:NilClass:Class的未定义方法`model_name'

时间:2014-01-02 22:27:17

标签: ruby-on-rails forms partial null

我正在进行在线教程,其任务是实现嵌套在帖子资源下的评论资源,后者又在主题资源下。我已经找到了练习的所有步骤,只是将“评论创建”表单显示在帖子#show上。我已经尝试了几个小时来修复它,但一直收到以下错误:undefined method "model_name" for NilClass:Class。我不知道model_name是指什么,在我的绝望中,我甚至在GitHub上查看了教程的代码,但我仍然无法看到我犯错误的地方。

我的表单是部分的,错误指向第一行,所以我先将这段代码粘贴到此处:

<%= form_for [topic, post, comment] do |f| %> 
    <div class="controls">
      <%= f.text_area :body, rows: 8 %>
    </div>
  <div class="control-group">
    <div class="controls">
      <%= f.submit "Add Comment", class: 'btn' %>
    </div>
  </div>
<% end %>

我会发布我的路线,以便您可以看到嵌套:

X::Application.routes.draw do

  devise_for :users

  resources :topics do
    resources :posts, except: [:index] do
      resources :comments, only: [:create]
    end
  end

  match "about" => 'welcome#about', via: :get

  root to: 'welcome#index'

end

这是我的评论控制器:

class CommentsController < ApplicationController

  def new
  end

  def create
    @topic = Topic.find(params[:topic_id])
    @post = Post.find(params[:post_id])

    @comment = current_user.comments.build(params[:comment])
    @comment.post = @post


    if @comment.save
      flash[:notice] = "Comment was saved."
      redirect_to @post
    else
      flash[:error] = "Error! Try again."
      render :new
    end
  end
end

这是我的帖子#show view(表格应该在底部呈现):

<h1><%= markdown @post.title %></h1>

<div class="row">
  <div class="span8">
    <small>
      <%= image_tag(@post.user.avatar.tiny.url) if @post.user.avatar? %>
      submitted <%= time_ago_in_words(@post.created_at) %> ago by 
      <%= @post.user.name %>
    </small>
    <br><br>    
    <p><%= image_tag(@post.image.url) if @post.image? %></p>
    <p><%= markdown @post.body %></p>
  </div>
  <div class="span2">
    <% if can? :edit, @post %>
      <%= link_to "Edit Post", edit_topic_post_path(@topic,@post), class: 'btn btn-small' %>
    <% end %>
  </div>
</div>
<br><br>  
<h4>Comments</h4>
<%= render @comments %>
<br>
<%= render :template => "/comments/_form.html.erb", locals: { topic: @topic, post: @post, comment: @comment } %>

如果有人能帮我解决这个问题,我将非常感激。如果有任何我应该添加的信息,请告诉我。谢谢!

2 个答案:

答案 0 :(得分:0)

一般来说,我读过它不推荐使用3级嵌套资源。你能链接到你正在关注的教程吗?

无论如何我建议在你的路线上使用浅。

resources :topics, shallow: true do 
  resources :posts, except: [:index], shallow: true do
    resources :comments, only: [:create]
  end
end

将为您提供以下资源,这些资源可以让您更轻松地在视图中创建正确的表单。

 post_comments POST   /posts/:post_id/comments(.:format)    comments#create
   topic_posts POST   /topics/:topic_id/posts(.:format)     posts#create
new_topic_post GET    /topics/:topic_id/posts/new(.:format) posts#new
     edit_post GET    /posts/:id/edit(.:format)             posts#edit
          post GET    /posts/:id(.:format)                  posts#show
               PATCH  /posts/:id(.:format)                  posts#update
               PUT    /posts/:id(.:format)                  posts#update
               DELETE /posts/:id(.:format)                  posts#destroy
        topics GET    /topics(.:format)                     topics#index
               POST   /topics(.:format)                     topics#create
     new_topic GET    /topics/new(.:format)                 topics#new
    edit_topic GET    /topics/:id/edit(.:format)            topics#edit
         topic GET    /topics/:id(.:format)                 topics#show
               PATCH  /topics/:id(.:format)                 topics#update
               PUT    /topics/:id(.:format)                 topics#update
               DELETE /topics/:id(.:format)                 topics#destroy

现在您只需将post_id发送到您的评论表单即可。阅读更多here我在3级嵌套方面没有多少工作,但这可以让你了解如何让自己更容易。

修改 在create操作中,您应该使用@post构建注释,然后将用户设置为current_user。

  def create

    @post = Post.find(params[:post_id])

    @comment = @post.comments.build(params[:comment])
    @comment.user = current_user


    if @comment.save
      flash[:notice] = "Comment was saved."
      redirect_to @post
    else
      flash[:error] = "Error! Try again."
      render :new
    end
  end

现在不需要@topic

<%= render :template => "/comments/_form.html.erb", locals: { post: @post, comment: @comment } %>

答案 1 :(得分:0)

将'@comment = Comment.new'添加到PostController的“show”动作中。它只在CommentController“创建”操作中定义。