运行 变成 PG::NotNullViolation
Running into PG::NotNullViolation
好的,所以我将 money-rails gem 集成到我的基本计算应用程序中......
当我现在尝试 运行 时,我得到这个错误:
ActiveRecord::StatementInvalid in TippiesController#create
下面这行:
PG::NotNullViolation: ERROR: null value in column "tip" violates not-null constraint DETAIL: Failing row contains (37, null, null, 2017-03-10 07:47:36.152504, 2017-03-10 07:47:36.152504, 3300, USD, 10, USD). : INSERT INTO "tippies" ("created_at", "updated_at", "cost_cents", "tip_cents") VALUES (, , , ) RETURNING "id""
...
所以,我认为这意味着它正在生成这个,因为我的模型规定 validates :tip, presence: true
...所以我将其注释掉,但仍然收到此错误。
不确定如何解决。任何帮助解决问题的帮助将不胜感激。
当前型号
class Tippy < ApplicationRecord
validates :tip_cents, presence: true
validates :cost_cents, presence: true
monetize :tip_cents
monetize :cost_cents
TIP_CHOICES = { "10%" => ".10", "20%" => ".20", "30%" => ".30", "40%" => ".40", "50%" => ".50",
"60%" => ".60", "70%" => ".70", "80%" => ".80", "90%" => ".90" }
def calculation_of_total_cost
cost_cents + (tip_cents * cost_cents)
end
end
电流控制器
class TippiesController < ApplicationController
before_action :set_tippy, only: [:show, :edit, :update, :destroy]
# GET /tippies
# GET /tippies.json
def index
@tippies = Tippy.all
end
# GET /tippies/1
# GET /tippies/1.json
def show
#@calculation_of_total_cost
end
# GET /tippies/new
def new
@tippy = Tippy.new
end
# GET /tippies/1/edit
def edit
end
# POST /tippies
# POST /tippies.json
def create
@tippy = Tippy.new(tippy_params)
respond_to do |format|
if @tippy.save
format.html { redirect_to @tippy, notice: 'Tippy was successfully created.' }
format.json { render :show, status: :created, location: @tippy }
else
format.html { render :new }
format.json { render json: @tippy.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /tippies/1
# PATCH/PUT /tippies/1.json
def update
respond_to do |format|
if @tippy.update(tippy_params)
format.html { redirect_to @tippy, notice: 'Tippy was successfully updated.' }
format.json { render :show, status: :ok, location: @tippy }
else
format.html { render :edit }
format.json { render json: @tippy.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tippies/1
# DELETE /tippies/1.json
def destroy
@tippy.destroy
respond_to do |format|
format.html { redirect_to tippies_url, notice: 'Tippy was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_tippy
@tippy = Tippy.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def tippy_params
params.require(:tippy).permit(:tip, :cost, :tip_cents, :tip_currency, :cost_cents, :cost_currency)
end
end
已迁移获利文件
class MonetizeTippy < ActiveRecord::Migration[5.0]
def change
add_monetize :tippies, :cost
add_monetize :tippies, :tip
end
end
架构
ActiveRecord::Schema.define(version: 20170310070749) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "tippies", force: :cascade do |t|
t.float "tip", null: false
t.decimal "cost", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "cost_cents", default: 0, null: false
t.string "cost_currency", default: "USD", null: false
t.integer "tip_cents", default: 0, null: false
t.string "tip_currency", default: "USD", null: false
end
end
Show.html.erb(首页后弹出此页为新动作
<br/><br/>
<h1 class="text-center">Your Total Cost</h1>
<br/><br />
<table class="table table-striped">
<tr>
<td>
Cost of Your Meal:
</td>
<td>
<%= humanized_money_with_symbol @tippy.cost_cents %>
</td>
</tr>
<tr>
<td>
Tip You Picked:
</td>
<td>
<%= number_to_percentage(@tippy.tip_cents * 100, format: "%n%", precision: 0) %>
</td>
</tr>
<tr>
<td>
The Total Cost:
</td>
<td>
<%= humanized_money_with_symbol @tippy.calculation_of_total_cost %>
</td>
</tr>
</table>
new.html.erb
<br /><br />
<h1 class="text-center">Calculate Your Tip!</h1>
<%= render 'form', tippy: @tippy %>
_form.html.erb
<%= form_for(tippy, :html => {'class' => "form-horizontal"}) do |f| %>
<% if tippy.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(tippy.errors.count, "error") %> prohibited this tippy from being saved:</h2>
<ul>
<% tippy.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field form-group">
<%= f.label :cost_of_your_meal, class: "control-label" %>
<%= f.text_field :cost, class: "form-control" %>
</div>
<div class="field form-group">
<%= f.label :pick_your_tip, class: "control-label" %>
<%= f.select(:tip, Tippy::TIP_CHOICES, class: "form-control") %>
</div>
<div class="actions">
<%= f.submit class: "btn btn-primary btn-lg btn-block" %>
</div>
<% end %>
此错误来自数据库,而不是 Rails。
在添加提示列的迁移中,它将如下所示:
t.float :tip, null: false
这转化为 SQL 架构中的 NOT NULL
约束。
数据库约束和验证的目的不同:前者绝对是为了防止不正确的数据被持久化,而后者是一种通过自动添加的 ActiveModel::Errors
对象。
要解决您的问题,您必须添加另一个迁移并再次使 tip
可为空(并可能提供适当的默认值):
change_column :tippies, :tip, :float, null: true, default: 0
好的,所以我将 money-rails gem 集成到我的基本计算应用程序中......
当我现在尝试 运行 时,我得到这个错误:
ActiveRecord::StatementInvalid in TippiesController#create
下面这行:
PG::NotNullViolation: ERROR: null value in column "tip" violates not-null constraint DETAIL: Failing row contains (37, null, null, 2017-03-10 07:47:36.152504, 2017-03-10 07:47:36.152504, 3300, USD, 10, USD). : INSERT INTO "tippies" ("created_at", "updated_at", "cost_cents", "tip_cents") VALUES (, , , ) RETURNING "id""
...
所以,我认为这意味着它正在生成这个,因为我的模型规定 validates :tip, presence: true
...所以我将其注释掉,但仍然收到此错误。
不确定如何解决。任何帮助解决问题的帮助将不胜感激。
当前型号
class Tippy < ApplicationRecord
validates :tip_cents, presence: true
validates :cost_cents, presence: true
monetize :tip_cents
monetize :cost_cents
TIP_CHOICES = { "10%" => ".10", "20%" => ".20", "30%" => ".30", "40%" => ".40", "50%" => ".50",
"60%" => ".60", "70%" => ".70", "80%" => ".80", "90%" => ".90" }
def calculation_of_total_cost
cost_cents + (tip_cents * cost_cents)
end
end
电流控制器
class TippiesController < ApplicationController
before_action :set_tippy, only: [:show, :edit, :update, :destroy]
# GET /tippies
# GET /tippies.json
def index
@tippies = Tippy.all
end
# GET /tippies/1
# GET /tippies/1.json
def show
#@calculation_of_total_cost
end
# GET /tippies/new
def new
@tippy = Tippy.new
end
# GET /tippies/1/edit
def edit
end
# POST /tippies
# POST /tippies.json
def create
@tippy = Tippy.new(tippy_params)
respond_to do |format|
if @tippy.save
format.html { redirect_to @tippy, notice: 'Tippy was successfully created.' }
format.json { render :show, status: :created, location: @tippy }
else
format.html { render :new }
format.json { render json: @tippy.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /tippies/1
# PATCH/PUT /tippies/1.json
def update
respond_to do |format|
if @tippy.update(tippy_params)
format.html { redirect_to @tippy, notice: 'Tippy was successfully updated.' }
format.json { render :show, status: :ok, location: @tippy }
else
format.html { render :edit }
format.json { render json: @tippy.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tippies/1
# DELETE /tippies/1.json
def destroy
@tippy.destroy
respond_to do |format|
format.html { redirect_to tippies_url, notice: 'Tippy was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_tippy
@tippy = Tippy.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def tippy_params
params.require(:tippy).permit(:tip, :cost, :tip_cents, :tip_currency, :cost_cents, :cost_currency)
end
end
已迁移获利文件
class MonetizeTippy < ActiveRecord::Migration[5.0]
def change
add_monetize :tippies, :cost
add_monetize :tippies, :tip
end
end
架构
ActiveRecord::Schema.define(version: 20170310070749) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "tippies", force: :cascade do |t|
t.float "tip", null: false
t.decimal "cost", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "cost_cents", default: 0, null: false
t.string "cost_currency", default: "USD", null: false
t.integer "tip_cents", default: 0, null: false
t.string "tip_currency", default: "USD", null: false
end
end
Show.html.erb(首页后弹出此页为新动作
<br/><br/>
<h1 class="text-center">Your Total Cost</h1>
<br/><br />
<table class="table table-striped">
<tr>
<td>
Cost of Your Meal:
</td>
<td>
<%= humanized_money_with_symbol @tippy.cost_cents %>
</td>
</tr>
<tr>
<td>
Tip You Picked:
</td>
<td>
<%= number_to_percentage(@tippy.tip_cents * 100, format: "%n%", precision: 0) %>
</td>
</tr>
<tr>
<td>
The Total Cost:
</td>
<td>
<%= humanized_money_with_symbol @tippy.calculation_of_total_cost %>
</td>
</tr>
</table>
new.html.erb
<br /><br />
<h1 class="text-center">Calculate Your Tip!</h1>
<%= render 'form', tippy: @tippy %>
_form.html.erb
<%= form_for(tippy, :html => {'class' => "form-horizontal"}) do |f| %>
<% if tippy.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(tippy.errors.count, "error") %> prohibited this tippy from being saved:</h2>
<ul>
<% tippy.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field form-group">
<%= f.label :cost_of_your_meal, class: "control-label" %>
<%= f.text_field :cost, class: "form-control" %>
</div>
<div class="field form-group">
<%= f.label :pick_your_tip, class: "control-label" %>
<%= f.select(:tip, Tippy::TIP_CHOICES, class: "form-control") %>
</div>
<div class="actions">
<%= f.submit class: "btn btn-primary btn-lg btn-block" %>
</div>
<% end %>
此错误来自数据库,而不是 Rails。
在添加提示列的迁移中,它将如下所示:
t.float :tip, null: false
这转化为 SQL 架构中的 NOT NULL
约束。
数据库约束和验证的目的不同:前者绝对是为了防止不正确的数据被持久化,而后者是一种通过自动添加的 ActiveModel::Errors
对象。
要解决您的问题,您必须添加另一个迁移并再次使 tip
可为空(并可能提供适当的默认值):
change_column :tippies, :tip, :float, null: true, default: 0