Rails 4 个回形针:"NoMethodError in Posts#create"

Rails 4 x Paperclip: "NoMethodError in Posts#create"

我有一个 Rails 应用程序具有以下型号:

class User < ActiveRecord::Base
  has_many :administrations
  has_many :calendars, through: :administrations
end

class Calendar < ActiveRecord::Base
  has_many :administrations
  has_many :users, through: :administrations
  has_many: :posts
end

class Administration < ActiveRecord::Base
  belongs_to :user
  belongs_to :calendar
end

class Post < ActiveRecord::Base
  belongs_to :calendar
end

在我尝试使用 Paperclip 向 post 模型添加 :image 属性之前,一切都曾完美运行。

现在,当我尝试创建新的 post 时,出现以下错误:

NoMethodError in Posts#create
undefined method `posts_path' for #<#<Class:0x007faa87d6a748>:0x007faa87d69c08>
<%= form_for(@post) do |f| %>
  <% if @post.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:</h2>

      <ul>

所以,这是我的文件:

routes.rb:

Rails.application.routes.draw do

  devise_for :users, :path => 'account', controllers: { registrations: "registrations", confirmations: "confirmations" }

  unauthenticated :user do
    root to: 'pages#home'
  end

  authenticated :user do
    root 'calendars#index', as: :authenticated_root
  end

  resources :calendars do
    resources :posts, shallow: true do
      resources :comments, shallow: true
    end
  end

  resources :invites

  resources :administrations, only: [:destroy]

end

_form.html.erb新建post:

<%= form_for(@post) do |f| %>
  <% if @post.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:</h2>

      <ul>
      <% @post.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <p>
      <%= f.label :date %><br>
      <%= f.date_select :date %>
    </p>
    <p>
      <%= f.label :time %><br>
      <%= f.time_select :time %>
    </p>
    <p>
      <%= f.label :subject %><br>
      <%= f.text_field :subject %>
    </p>
    <p>
      <%= f.label :format %><br>
      <%= f.text_field :format %>
    </p>
    <p>
      <%= f.label :copy %><br>
      <%= f.text_area :copy %>
    </p>
    <p>
      <%= f.label :image %><br>
      <%= f.file_field :image %>
    </p>
  </div>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

来自 PostsControllerPosts#Create 操作:

def create
    @calendar = Calendar.find(params[:calendar_id])
    @post = @calendar.posts.create(post_params)

    respond_to do |format|
      if @post.save
        format.html { redirect_to calendar_path(@calendar), notice: 'Post was successfully created.' }
        format.json { render :show, status: :created, location: @post }
      else
        format.html { render :new }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

–––––

UPDATE:正如@Pavan 在评论中所问,这里是 Posts#New 方法:

def new
  @post = Post.new
end

–––––

此外,因为我们从 Calendar#Show 视图创建了新的 posts,所以这里是日历 show.html.erb:

<h2><%= @calendar.name %> Calendar</h2>

<h3>Posts</h3>
<% if @calendar.posts.any? %>
    <table>
        <tr>
            <th><span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span></th>
      <th><span class="glyphicon glyphicon-wrench" aria-hidden="true"></span></th>
      <th><span class="glyphicon glyphicon-trash" aria-hidden="true"></span></th>
      <th>Date</th>
            <th>Time</th>
          <th>Subject</th>
          <th>Format</th>
          <th>Copy</th>
          <th>Image</th>
      <th>Comments</th>
        </tr>
  <% @calendar.posts.each do |post| %>
        <tr>
        <td><%= link_to post do %><span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span><% end %></td>
        <td><%= link_to edit_post_path(post) do %><span class="glyphicon glyphicon-wrench" aria-hidden="true"></span><% end %></td>
        <td><%= link_to post, method: :delete, data: { confirm: 'Are you sure?' } do %><span class="glyphicon glyphicon-trash" aria-hidden="true"></span><% end %></td>
        <td><%= post.date.strftime("%A, %d") %></td>
            <td><%= post.time.strftime("%I:%M %p")%></td>
            <td><%= post.subject %></td>
            <td><%= post.format %></td>
            <td><%= post.copy %></td>
            <td><%= post.image.url(:med) %></td>
        <td>
          <% post.comments.each do |comment| %>
            <table>
              <tr><td><strong><%= comment.user_first_name %>: </strong><%= comment.body %> <%= link_to 'x', comment, method: :delete, data: { confirm: 'Are you sure?' } %></td></tr>
            </table>
          <% end %>
          <table>
            <%= form_for([post, post.comments.build]) do |f| %>
              <p>
                <%= f.text_area :body, :placeholder => "New comment" %><%= f.submit %>
              </p>
            <% end %>
          </table>
        </td>
        </tr>
    </table>
  <% end %>
<% else %>
<p>This calendar does not contain any post yet: just create one with the form below.</p>
<% end %>

<h3>Add a post to <%= @calendar.name %> Calendar:</h3>
<%= form_for([@calendar, @calendar.posts.build]), html: { multipart: true }  do |f| %>
  <p>
    <%= f.label :date %><br>
    <%= f.date_select :date %>
  </p>
  <p>
    <%= f.label :time %><br>
    <%= f.time_select :time %>
  </p>
  <p>
    <%= f.label :subject %><br>
    <%= f.text_field :subject %>
  </p>
  <p>
    <%= f.label :format %><br>
    <%= f.text_field :format %>
  </p>
  <p>
    <%= f.label :copy %><br>
    <%= f.text_area :copy %>
  </p>
  <p>
    <%= f.label :image %><br>
    <%= f.file_field :image %>
  </p>
  <p>
    <%= f.submit %>
  </p>
<% end %>


<%= link_to 'Edit', edit_calendar_path %> |
<%= link_to 'Back', calendars_path %>

这是我用来将附件添加到 Post 模型的迁移:

class AddPaperclipToPost < ActiveRecord::Migration
  def change
    remove_column :posts, :media
    add_attachment :posts, :image
  end
end

我这样做是因为我的 Post 模型曾经有一个 :media 属性,但我想用 :image 属性替换它并使用这个 :image允许用户将文件上传到 posts.

的属性

这里是 Post 型号:

class Post < ActiveRecord::Base

  belongs_to :calendar

  has_attached_file :image, styles: { small: "64x64", med: "100x100", large: "200x200" }
  validates_attachment :image, :content_type => { :content_type => "image/jpg" },
                                :size => { :in => 0..2000.kilobytes }
end

最后但同样重要的是,这是我的 server logs:

Started POST "/calendars/3/posts" for ::1 at 2015-09-21 16:46:29 -0700
Processing by PostsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"8TUY8AhkQmnDbYo6dmIEdEWpo7bXl0gBEzlxKIyuxivxAofK/cWcxzMN2E646q/SpkLkQFdq1pcaXebw3VvrWQ==", "post"=>{"date(1i)"=>"2015", "date(2i)"=>"9", "date(3i)"=>"21", "time(1i)"=>"2015", "time(2i)"=>"9", "time(3i)"=>"21", "time(4i)"=>"23", "time(5i)"=>"32", "subject"=>"Another image test", "format"=>"Image", "copy"=>"This is a second image test to see if Paperclip works.", "image"=>#<ActionDispatch::Http::UploadedFile:0x007faa893ac240 @tempfile=#<Tempfile:/var/folders/8x/t_8ws7y91k34_qzf2ttl0hnw0000gq/T/RackMultipart20150921-24195-g4tdab.png>, @original_filename="Capture d’écran 2015-09-21 à 08.55.58.png", @content_type="image/png", @headers="Content-Disposition: form-data; name=\"post[image]\"; filename=\"Capture d\xE2\x80\x99\xC3\xA9cran 2015-09-21 \xC3\xA0 08.55.58.png\"\r\nContent-Type: image/png\r\n">}, "commit"=>"Create Post", "calendar_id"=>"3"}
  Calendar Load (0.1ms)  SELECT  "calendars".* FROM "calendars" WHERE "calendars"."id" = ? LIMIT 1  [["id", 3]]
   (0.1ms)  begin transaction
Command :: file -b --mime '/var/folders/8x/t_8ws7y91k34_qzf2ttl0hnw0000gq/T/b27b4279f10a51498de05fe8699e95ec20150921-24195-16bb55q.png'
Command :: file -b --mime '/var/folders/8x/t_8ws7y91k34_qzf2ttl0hnw0000gq/T/b27b4279f10a51498de05fe8699e95ec20150921-24195-brivpw.png'
   (0.1ms)  commit transaction
   (0.0ms)  begin transaction
Command :: file -b --mime '/var/folders/8x/t_8ws7y91k34_qzf2ttl0hnw0000gq/T/b27b4279f10a51498de05fe8699e95ec20150921-24195-8rl6x7.png'
   (0.1ms)  rollback transaction
  Rendered posts/_form.html.erb (16.9ms)
  Rendered posts/new.html.erb within layouts/application (17.9ms)
Completed 500 Internal Server Error in 74ms (ActiveRecord: 1.2ms)

ActionView::Template::Error (undefined method `posts_path' for #<#<Class:0x007faa87d6a748>:0x007faa87d69c08>):
    1: <%= form_for(@post) do |f| %>
    2:   <% if @post.errors.any? %>
    3:     <div id="error_explanation">
    4:       <h2><%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:</h2>
  app/views/posts/_form.html.erb:1:in `_app_views_posts__form_html_erb___617022956579766846_70185160605820'
  app/views/posts/new.html.erb:3:in `_app_views_posts_new_html_erb__3720911906763373835_70185160686220'
  app/controllers/posts_controller.rb:35:in `block (2 levels) in create'
  app/controllers/posts_controller.rb:30:in `create'


  Rendered /Users/TXC/.rvm/gems/ruby-2.2.1@global/gems/actionpack-4.2.2/lib/action_dispatch/middleware/templates/rescues/_source.erb (10.7ms)
  Rendered /Users/TXC/.rvm/gems/ruby-2.2.1@global/gems/actionpack-4.2.2/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (4.6ms)
  Rendered /Users/TXC/.rvm/gems/ruby-2.2.1@global/gems/actionpack-4.2.2/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.5ms)
  Rendered /Users/TXC/.rvm/gems/ruby-2.2.1@global/gems/actionpack-4.2.2/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb within rescues/layout (72.9ms)
Cannot render console with content type multipart/form-dataAllowed content types: [#<Mime::Type:0x007faa82c583a0 @synonyms=["application/xhtml+xml"], @symbol=:html, @string="text/html">, #<Mime::Type:0x007faa82c58008 @synonyms=[], @symbol=:text, @string="text/plain">, #<Mime::Type:0x007faa847b0dc8 @synonyms=[], @symbol=:url_encoded_form, @string="application/x-www-form-urlencoded">]

——————

更新 2:我按照@Pavan 的建议更新了 Posts#Create 操作:

def new
  @calendar = Calendar.find(params[:calendar_id])
  @post = @calendar.posts.build
end

现在,当我尝试访问任何日历显示视图时,出现以下错误:

SyntaxError in CalendarsController#show
/Users/TXC/code/rails/calendy/app/views/calendars/show.html.erb:51: syntax error, unexpected tLABEL ... @calendar.posts.build]), html: { multipart: true } do |f| ... ... ^ /Users/TXC/code/rails/calendy/app/views/calendars/show.html.erb:51: syntax error, unexpected keyword_do_block, expecting keyword_end ..., html: { multipart: true } do |f| @output_buffer.safe_appe... ... ^ /Users/TXC/code/rails/calendy/app/views/calendars/show.html.erb:85: syntax error, unexpected keyword_ensure, expecting end-of-input
<h3>Add a post to <%= @calendar.name %> Calendar:</h3>
<%= form_for([@calendar, @calendar.posts.build]), html: { multipart: true }  do |f| %>
  <p>
    <%= f.label :date %><br>
    <%= f.date_select :date %>

——————

更新 3:为了解决上述问题(来自 更新 2),我将 <%= form_for([@calendar, @calendar.posts.build]), html: { multipart: true } do |f| %> 替换为 <%= form_for[@calendar, @calendar.posts.build], html: { multipart: true } do |f| %>.

这使日历显示视图再次起作用。

但是,当我尝试从日历索引视图添加新的 post 时,我仍然遇到与最初在这个问题中提到的相同的错误:

NoMethodError in Posts#create
undefined method `posts_path' for #<#<Class:0x007f86f5a96b58>:0x007f86f752ebf0>
<%= form_for(@post) do |f| %>
  <% if @post.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:</h2>

      <ul>

我很乐意分享任何必要的额外代码来提供帮助。

——————

同样,在我尝试实施 Paperclip.

之前一切正常

知道哪里出了问题吗?

尝试改变您的 new 方法,如下所示

def new
  @calendar = Calendar.find(params[:calendar_id])
  @post = @calendar.posts.build
end