Reputation: 6907
I have a Rails app with the following models:
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
Everything used to work perfectly, until I tried to add an :image
attribute to the post
model with Paperclip.
Now, when I try to create a new post, I get the following error:
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>
So, here are my files:
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
The _form.html.erb
to create a new 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 %>
The Posts#Create
action from the PostsController
:
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: as asked by @Pavan in the comments, here is the Posts#New method:
def new
@post = Post.new
end
–––––
Also, because we create new posts
from the Calendar#Show
view, here is the Calendar 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 %>
Here is the migration I used to add the attachment to the Post
model:
class AddPaperclipToPost < ActiveRecord::Migration
def change
remove_column :posts, :media
add_attachment :posts, :image
end
end
I did that because I used to have a :media
attribute on my Post
model, but wanted to replace it with an :image
attribute and use this :image
attribute to allow users to upload files to posts.
Here is the Post model:
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
And, last but not least, here are my 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">]
—————
UPDATE 2: I updated the Posts#Create action as recommended by @Pavan:
def new
@calendar = Calendar.find(params[:calendar_id])
@post = @calendar.posts.build
end
Now, when I try to visit any calendar show view, I get the following error:
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 %>
—————
UPDATE 3: to fix the above problem (from UPDATE 2), I replaced <%= form_for([@calendar, @calendar.posts.build]), html: { multipart: true } do |f| %>
with <%= form_for[@calendar, @calendar.posts.build], html: { multipart: true } do |f| %>
.
This made the calendar show views to work again.
However, when I try to add a new post from the calendar index view, I still get the same error as mentioned originally in this question:
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>
I am happy to share any necessary additional code to help.
—————
Again, everything was working before I tried to implement Paperclip
.
Any idea of what is going wrong?
Upvotes: 2
Views: 195
Reputation: 33552
Try changing your new
method like below
def new
@calendar = Calendar.find(params[:calendar_id])
@post = @calendar.posts.build
end
Upvotes: 1