[英]ActiveRecord::NotNullViolation (PG::NotNullViolation: ERROR: null value in column “content_id” violates not-null constraint
I'm currently building a rails 5 application in which a shout
can be a TextShout
or a PhotoShout
. 我目前正在构建Rails 5应用程序,其中的
shout
可以是TextShout
或PhotoShout
。 When creating a shout, content_id
is not being pass in the params therefore raising a Not Null Value error. 创建喊叫时,不会在参数中传递
content_id
,因此会引发“非空值”错误。 In the migration for the shout I can not find where the error is coming from. 在大喊大叫的迁移中,我找不到错误的出处。 I have the following files.
我有以下文件。
show.html.erb show.html.erb
<%= form_for @shout do |form| %>
<%= form.hidden_field :content_type, value: "TextShout" %>
<%= form.fields_for :content do |content_form| %>
<%= content_form.text_field :body, placeholder: "shout here!", required: true %>
<%= content_form.submit "Shout!" %>
<% end %>
<% end %>
<%= form_for @shout do |form| %>
<%= form.hidden_field :content_type, value: "PhotoShout" %>
<%= form.fields_for :content do |content_form| %>
<%= content_form.file_field :image, required: true %>
<%= content_form.submit "Shout!" %>
<% end %>
<% end %>
<%= render @shouts %>
migration/_make_shouts_polymorphic.rb 迁移/ _make_shouts_polymorphic.rb
class MakeShoutsPolymorphic < ActiveRecord::Migration[5.1]
class Shout < ApplicationRecord
belongs_to :content, polymorphic: true
end
class TextShout < ApplicationRecord; end
def change
change_table(:shouts) do |t|
t.string :content_type
t.integer :content_id
t.index [:content_type, :content_id]
end
reversible do |dir|
Shout.reset_column_information
Shout.find_each do |shout|
dir.up do
text_shout = TextShout.create(body: shout.body)
shout.update(content_id: text_shout.id, content_type: "TextShout")
end
dir.down do
shout.update(body: shout.content.body)
shout.content.destroy
end
end
end
remove_column :shouts, :body, :string
end
end
shouts_controller.rb shouts_controller.rb
class ShoutsController < ApplicationController
def show
@shout = Shout.find(params[:id])
end
def create
shout = current_user.shouts.create(shout_params)
redirect_to root_path, redirect_options_for(shout)
end
private
def shout_params
{ content: content_from_params }
end
def content_from_params
case params[:shout][:content_type]
when "TextShout" then TextShout.new(text_shout_content_params)
when "PhotoShout" then PhotoShout.new(photo_shout_content_params)
end
end
def text_shout_content_params
params.require(:shout).require(:content).permit(:body)
end
def photo_shout_content_params
params.require(:shout).require(:content).permit(:image)
end
def redirect_options_for(shout)
if shout.persisted?
{notice: "Shouted Successfully"}
else
{alert: "Could not shout"}
end
end
end
neither text_shout_content_params
and photo_shout_content_params
are permitting a content_id
, but it looks like you're trying to (or at least you should be intending to) create one in your content_from_params
无论
text_shout_content_params
和photo_shout_content_params
都不允许content_id
,但似乎您正在尝试(或至少应该打算)在content_from_params
创建一个
def content_from_params
case params[:shout][:content_type]
when "TextShout"
shout = TextShout.new(text_shout_content_params)
when "PhotoShout"
shout = PhotoShout.new(photo_shout_content_params)
end
shout.save!
params[:shout][:content_id] = shout.id
params[:shout]
end
If you want the content to have an id you will have to create the shout using create
instead of new
. 如果您希望内容具有ID,则必须使用
create
而不是new
来创建喊叫。 create
will attempt to add a record to the database and will assign an id. create
将尝试将记录添加到数据库并分配一个ID。
It may also be beneficial to use create!
使用
create!
可能也有好处create!
which will raise an error if the shout has invalid data and cannot be saved. 如果喊叫中包含无效数据并且无法保存,则会引发错误。
def content_from_params
case params[:shout][:content_type]
when "TextShout" then TextShout.create(text_shout_content_params)
when "PhotoShout" then PhotoShout.create(photo_shout_content_params)
end
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.