I’m a newbie trying to create a simple Rails (4.2.1) app that allows a user (when logged in >> ‘devise’ gem) to add a post with an image (‘paperclip’ gem).
The form data is not being saved in the DB. I suspect this might have to do with the way the parameters are passed but since I’m new to this, I’m not sure.
It was working — posts were being saved in DB and then displayed on site — until I refactored the form to use @post instead of Post.new (so my view isn’t speaking directly to the model), and then added the 'new' method to the controller, but now the form data is not being saved.
I tried both using and omitting passing in the ‘post_params’ for the 'new' method. When I pass in the params to 'new' method, I get this error:
ActionController::ParameterMissing (param is missing or the value is empty: post):
app/controllers/posts_controller.rb:22:in `post_params'
app/controllers/posts_controller.rb:18:in `new'
As a side note: I left out “multipart: true” in the form because based on the Rails documentation, I understood it was needed only for “form_tag” and not for “form_for” (http://guides.rubyonrails.org/form_helpers.html).
Here is the controller:
class PostsController < ApplicationController
before_action :authenticate_user!, :except => [:index, :show]
def index
@post = Post.all
end
def show
@post = Post.find(params[:id])
end
def create
@post = Post.new(post_params)
redirect_to '/'
end
def new
@post = Post.new
end
def post_params
params.require(:post).permit(:caption, :image)
end
end
Here is the form (posts/new.html.erb):
<%= form_for @post do |f| %>
<%= f.label :caption %>
<%= f.text_field :caption %>
<%= f.file_field :image %>
<%= f.submit %>
<% end %>
<br><a href=/posts> back to all posts </a>
Unfortunately I refactored the form with @post at the same time that I added the image upload to the form; before this, the form was working fine and data was being stored in db and displayed on site correctly (and by "correct" I mean as intended :)
After starting the sever and loading the page locally, I’m not seeing errors that give me clues about saving the form data to the DB. The errors I see are something about missing.png — I’m assuming this is because there is no default image loaded, one called “missing.png”.
Started GET "/images/medium/missing.png" for ::1 at 2015-07-14 12:06:59 +0200
ActionController::RoutingError (No route matches [GET] "/images/medium/missing.png"):
actionpack (4.2.1)
lib/action_dispatch/middleware/debug_exceptions.rb:21:in `call'
Edited here to include Post model:
class Post < ActiveRecord::Base
belongs_to :user
has_attached_file :image, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :default_url => "/images/:style/missing.png"
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
end
This is the DB schema:
create_table "posts", force: :cascade do |t|
t.text "caption"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "user_id"
t.string "image_file_name"
t.string "image_content_type"
t.integer "image_file_size"
t.datetime "image_updated_at"
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
My questions are:
— what is the correct way to pass in parameters for the methods ‘create' and ‘new’?
— If this is not in fact the cause of the error, is there anything else in the code given here that might be preventing posts from being saved to DB?
Bonus Question:
The current RSpec failure is also not very detailed (probably speaks to my tests -- yikes).
— Is there a better way to test this? What should a test for this look like? Currently, the only unit tests are for associations and they pass; the section of the feature test that is currently failing is below.
context 'creating posts' do
scenario 'prompts user to fill out a form, then displays the new post' do
user_sign_in
visit '/posts'
click_link 'add a post'
fill_in 'Caption', with: 'sunny Saturday'
attach_file 'post_image', './public/IMG.jpg'
click_button 'Create Post'
expect(page).to have_content 'sunny Saturday'
expect(current_path).to eq '/'
end
end
Which just confirms what I'm seeing locally.
Failures:
1) posts - creating posts prompts user to fill out a form, then displays the new post
Failure/Error: expect(page).to have_content 'sunny Saturday'
expected to find text "sunny Saturday" in "sign out no posts yet add a post"
Edited here with development log details:
Started POST "/posts" for ::1 at 2015-07-14 13:28:20 +0200
Processing by PostsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"mc4hUr1Kzf4P+EsW09518zUWOUHsldj5cHiIbi427THxti76PG0Yvr+a7/KMHIsgJMln+YugyDdRNOXy4LvDRw==", "post"=>{"caption"=>"new post", "image"=>#<ActionDispatch::Http::UploadedFile:0x007fe121b00b30 @tempfile=#<Tempfile:/var/folders/cc/nyvtq7hj62s98br08bcfzg6w0000gn/T/RackMultipart20150714-93392-arzgnw.jpg>, @original_filename="cat1.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"post[image]\"; filename=\"cat1.jpg\"\r\nContent-Type: image/jpeg\r\n">}, "commit"=>"Create Post"}
[1m[35mUser Load (0.3ms)[0m SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
Command :: PATH=C:\Program Files (x86)\GnuWin32\bin:$PATH; file -b --mime '/var/folders/cc/nyvtq7hj62s98br08bcfzg6w0000gn/T/a980d10665f268b0ec6c13ebea43034f20150714-93392-1qoui22.jpg'
[paperclip] Content Type Spoof: Filename cat1.jpg (["image/jpeg"]), content type discovered from file command: . See documentation to allow this combination.
[1m[36m (0.2ms)[0m [1mBEGIN[0m
Command :: PATH=C:\Program Files (x86)\GnuWin32\bin:$PATH; file -b --mime '/var/folders/cc/nyvtq7hj62s98br08bcfzg6w0000gn/T/a980d10665f268b0ec6c13ebea43034f20150714-93392-7beczf.jpg'
[paperclip] Content Type Spoof: Filename cat1.jpg (["image/jpeg"]), content type discovered from file command: . See documentation to allow this combination.
[1m[35m (0.1ms)[0m ROLLBACK
Redirected to http://localhost:3000/
Completed 302 Found in 21ms (ActiveRecord: 0.6ms)
Started GET "/" for ::1 at 2015-07-14 13:28:20 +0200
Processing by PostsController#index as HTML
[1m[36m (0.2ms)[0m [1mSELECT COUNT(*) FROM "posts"[0m
[1m[35mPost Load (0.2ms)[0m SELECT "posts".* FROM "posts"
Rendered posts/index.html.erb within layouts/application (4.6ms)
[1m[36mUser Load (0.4ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1[0m [["id", 1]]
Completed 200 OK in 28ms (Views: 26.3ms | ActiveRecord: 0.8ms)
Started GET "/images/medium/missing.png" for ::1 at 2015-07-14 13:28:20 +0200
ActionController::RoutingError (No route matches [GET] "/images/medium/missing.png"):
And yes, in the future, I will refactor only after things work.
What is the correct way to pass in parameters for the methods ‘create' and ‘new’?
Your form looks good for me.
is there anything else in the code given here that might be preventing posts from being saved to DB?
Your create
action doesn't save a record.
def create
@post = Post.new(post_params)
@post.save
redirect_to '/'
end
The errors I see are something about missing.png — I’m assuming this is because there is no default image loaded, one called “missing.png”.
Right