ActiveRecord :: NotNullViolation(PG :: NotNullViolation:ERROR:列中的空值" content_id"违反非空约束

时间:2018-01-05 18:50:37

标签: ruby-on-rails ruby polymorphic-associations

我目前正在构建一个rails {5}应用,其中shout可以是TextShoutPhotoShout。在创建一个喊叫时,content_id没有在params中传递,因此引发了Not Null Value错误。在呼叫的迁移中,我无法找到错误的来源。我有以下文件。

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 %>

迁移/ _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

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

2 个答案:

答案 0 :(得分:1)

text_shout_content_paramsphoto_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 {1}}

Smash Mouth - All Star.mp4

答案 1 :(得分:0)

如果您希望内容具有ID,则必须使用import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.sass'] }) export class AppComponent { log = 0; showLog = false; onShowLog(){ this.showLog = true; return this.log = this.log + 1; } } 而不是create来创建喊叫。 new将尝试将记录添加到数据库并分配ID。

使用create可能也是有益的,如果喊号有无效数据且无法保存,则会引发错误。

create!