表单字段未保存到数据库:这是否与 new/create 控制器方法的表单参数传递方式有关?
Form fields not saving to DB: does this have to do with how form parameters are passed for new/create controller methods?
我是一个新手,正在尝试创建一个简单的 Rails (4.2.1) 应用程序,该应用程序允许用户(登录后>>“设计”gem)添加一个 post 带有图像(“回形针”gem)。
表单数据没有保存在数据库中。我怀疑这可能与传递参数的方式有关,但由于我是新手,我不确定。
它正在工作 — posts 被保存在数据库中,然后在网站上显示 — 直到我重构表单以使用 @post 而不是 Post.new(所以我的观点不直接与模型对话),然后将 'new' 方法添加到控制器,但现在表单数据未被保存。
我尝试使用和省略为 'new' 方法传入的“post_params”。当我将参数传递给 'new' 方法时,出现此错误:
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'
附带说明:我在表格中省略了“multipart: true”,因为根据 Rails 文档,我知道只有“form_tag”而不是“ form_for” (http://guides.rubyonrails.org/form_helpers.html).
这是控制器:
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
这是表格 (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>
不幸的是,我在将图片上传添加到表单的同时用@post重构了表单;在此之前,表格工作正常,数据存储在数据库中并正确显示在网站上("correct" 我的意思是按预期:)
在启动服务器并在本地加载页面后,我没有看到任何错误提示将表单数据保存到数据库。我看到的错误是关于 missing.png 的——我假设这是因为没有加载默认图像,一个叫做“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'
在此处编辑以包括 Post 型号:
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
这是数据库架构:
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
我的问题是:
— ‘create’ 和 ‘new’ 方法传入参数的正确方法是什么?
— 如果这实际上不是错误的原因,此处给出的代码中是否还有其他任何内容可能阻止 posts 被保存到 DB?
奖金问题:
当前的 RSpec 故障也不是很详细(可能与我的测试有关 -- 哎呀)。
— 有没有更好的方法来测试这个?对此的测试应该是什么样的?目前,唯一的单元测试是针对关联的,并且它们通过了;当前失败的功能测试部分如下。
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
这正好证实了我在当地看到的情况。
失败:
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"
在此处编辑了开发日志详细信息:
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" = 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" = 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"):
是的,以后我会在事情正常后进行重构。
What is the correct way to pass in parameters for the methods
‘create' and ‘new’?
你的表格很适合我。
is there anything else in the code given here that might be preventing
posts from being saved to DB?
您的 create
操作没有保存记录。
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”.
正确
非常感谢@Зелёный 指出我的 post 的“创建”方法丢失了 @post.save。
该表格现在可以使用,带有图像的 post 正在保存到数据库并显示在网站上。图像问题源于回形针 gem。
来自类似 Paperclip 问题的以下解决方案 posted to SO,here and here,修复了图像保存问题:
— 下载了 GhostScript
brew install gs
— 将以下代码添加到文件中,config/initializers/paperclip_media_type_spoof_detector_override.rb:
require 'paperclip/media_type_spoof_detector'
Paperclip.options[:command_path] = '/usr/bin'
module Paperclip
class MediaTypeSpoofDetector
old_spoofed = instance_method(:spoofed?)
define_method(:spoofed?) do
if supplied_file_content_types.count > 0
old_spoofed.bind(self).()
else
false
end
end
end
end
我是一个新手,正在尝试创建一个简单的 Rails (4.2.1) 应用程序,该应用程序允许用户(登录后>>“设计”gem)添加一个 post 带有图像(“回形针”gem)。
表单数据没有保存在数据库中。我怀疑这可能与传递参数的方式有关,但由于我是新手,我不确定。
它正在工作 — posts 被保存在数据库中,然后在网站上显示 — 直到我重构表单以使用 @post 而不是 Post.new(所以我的观点不直接与模型对话),然后将 'new' 方法添加到控制器,但现在表单数据未被保存。
我尝试使用和省略为 'new' 方法传入的“post_params”。当我将参数传递给 'new' 方法时,出现此错误:
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'
附带说明:我在表格中省略了“multipart: true”,因为根据 Rails 文档,我知道只有“form_tag”而不是“ form_for” (http://guides.rubyonrails.org/form_helpers.html).
这是控制器:
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
这是表格 (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>
不幸的是,我在将图片上传添加到表单的同时用@post重构了表单;在此之前,表格工作正常,数据存储在数据库中并正确显示在网站上("correct" 我的意思是按预期:)
在启动服务器并在本地加载页面后,我没有看到任何错误提示将表单数据保存到数据库。我看到的错误是关于 missing.png 的——我假设这是因为没有加载默认图像,一个叫做“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'
在此处编辑以包括 Post 型号:
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
这是数据库架构:
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
我的问题是:
— ‘create’ 和 ‘new’ 方法传入参数的正确方法是什么?
— 如果这实际上不是错误的原因,此处给出的代码中是否还有其他任何内容可能阻止 posts 被保存到 DB?
奖金问题:
当前的 RSpec 故障也不是很详细(可能与我的测试有关 -- 哎呀)。
— 有没有更好的方法来测试这个?对此的测试应该是什么样的?目前,唯一的单元测试是针对关联的,并且它们通过了;当前失败的功能测试部分如下。
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
这正好证实了我在当地看到的情况。
失败:
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"
在此处编辑了开发日志详细信息:
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" = 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" = 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"):
是的,以后我会在事情正常后进行重构。
What is the correct way to pass in parameters for the methods ‘create' and ‘new’?
你的表格很适合我。
is there anything else in the code given here that might be preventing posts from being saved to DB?
您的 create
操作没有保存记录。
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”.
正确
非常感谢@Зелёный 指出我的 post 的“创建”方法丢失了 @post.save。
该表格现在可以使用,带有图像的 post 正在保存到数据库并显示在网站上。图像问题源于回形针 gem。
来自类似 Paperclip 问题的以下解决方案 posted to SO,here and here,修复了图像保存问题:
— 下载了 GhostScript
brew install gs
— 将以下代码添加到文件中,config/initializers/paperclip_media_type_spoof_detector_override.rb:
require 'paperclip/media_type_spoof_detector'
Paperclip.options[:command_path] = '/usr/bin'
module Paperclip
class MediaTypeSpoofDetector
old_spoofed = instance_method(:spoofed?)
define_method(:spoofed?) do
if supplied_file_content_types.count > 0
old_spoofed.bind(self).()
else
false
end
end
end
end