【问题标题】:Rails - ActiveRecord error on insert into PostgreSqlRails - 插入 PostgreSql 时出现 ActiveRecord 错误
【发布时间】:2015-02-03 14:13:17
【问题描述】:

我已经接管了一个现有的 Rails 3.2.9 应用程序并试图在我的本地 Windows 7 机器上设置它,但在尝试注册用户时出现以下错误:

ActiveRecord::StatementInvalid in Workers::RegistrationsController#create

PG::Error: 错误:“id”列中的空值违反非空值 约束细节:

失败的行包含 (null, 8f9f248b33a121ec83a38310,ZqddTnkfmB7Afu9Ukwcx,0,空,空,空, 空,空,2014 年 11 月 25 日 17:55:43.8317,2014 年 11 月 25 日 17:55:43.8317,空, dtest@gmail.com,空,空,空,空,空,空,空,空,空, 空,空,待定,唐尼,伯茨,空,f,f,f,空,空,空, 空,空,空,test.com,yEqp4FV5XCKS9xaRnnwz,空,2014-11-25 17:55:43.8307,空,空,空,0,空,空,工作,空,空, 空,空,空,f,空,f,空,0,0,0,空,f,0,空,空, 空,空,空)。 :

INSERT INTO "users" ("active", "keys", "address", “admin”、“avail”、“availof”、“content_type”、“file_name”、“file_size”、 “a_updated_at”、“calendar_json”、“员工”、“company_1”、 “company_2”、“company_3”、“confirmation_sent_at”、 “confirmation_token”、“confirmed_at”、“created_at”、 “current_sign_in_at”、“current_sign_in_ip”、“数据”、“域”、“电子邮件”、 “encrypted_pa​​ssword”、“extra_links”、“f1”、“failed_attempts”、 “first_name”、“fulltime”、“general_help”、“headline”、“intro”、 “jobs_count”、“关键字”、“last_name”、“last_request_at”、 “last_sign_in_at”、“last_sign_in_ip”、“l1”、“locked_at”、 “metric_units”、“opt_out”、“password_salt”、“phone”、“credit”、“rate”、 “rating_count”,“receive_correspondence”,“remember_created_at”, “remember_token”、“远程”、“reset_password_sent_at”、 “reset_password_token”、“sign_in_count”、“avatar_url”、“状态”、 “time_zone”、“t1”、“类型”、“unconfirmed_email”、“unlock_token”、 “updated_at”、“used_credits”、“video_url”、“wizard_step”、“zipcode”) 价值(1 美元、2 美元、3 美元、4 美元、5 美元、6 美元、7 美元、8 美元、9 美元、10 美元、11 美元、12 美元、13 美元、14 美元、 15 美元、16 美元、17 美元、18 美元、19 美元、20 美元、21 美元、22 美元、23 美元、24 美元、25 美元、26 美元、27 美元、28 美元, 29 美元、30 美元、31 美元、32 美元、33 美元、34 美元、35 美元、36 美元、37 美元、38 美元、39 美元、40 美元、41 美元、42 美元, $43, $44, $45, $46, $47, $48, $49, $50, $51, $52, $53, $54, $55, $56, $57, $58, $59, $60, $61, $62, $63, $64, $65, $66, $67) 返回“id”

最初,我收到 ActiveRecord::NotNullViolation 错误,并且 :id 字段包含在插入语句中。为了解决这个问题,我在用户模型中添加了self.primary_key = :id。这从插入中删除了 :id,但我现在注意到,虽然插入语句在错误消息中看起来没问题,但“失败行”实际上有一个额外的列 (68),并且它们的顺序与列表中列出的顺序不同insert 语句(按字母顺序列出列)。

应用程序正在使用 devise 和 omniauth,如果其中任何一个相关。

schema.rb:

create_table "users", :force => true do |t|
    t.string   "encrypted_password",                                 :null => false
    t.string   "password_salt"
    t.integer  "sign_in_count",          :default => 0,              :null => false
    t.datetime "last_request_at"
    t.datetime "last_sign_in_at" 
    .
    .
    . 
    t.string   "unconfirmed_email"   
end

编辑 1

SQL:

CREATE TABLE users (
id integer NOT NULL,
created_at timestamp without time zone,
updated_at timestamp without time zone,
encrypted_password character varying(255) NOT NULL,
password_salt character varying(255),
sign_in_count integer DEFAULT 0 NOT NULL,
last_request_at timestamp without time zone,
last_sign_in_at timestamp without time zone,
current_sign_in_at timestamp without time zone,
last_sign_in_ip character varying(255),
current_sign_in_ip character varying(255),
email character varying(255) NOT NULL,
.
.
.
reset_password_sent_at timestamp without time zone,
unconfirmed_email character varying(255),
data hstore
);

ALTER TABLE ONLY users
    ADD CONSTRAINT users_pkey PRIMARY KEY (id);

我还应该提到,原始开发人员的唯一指示是首先手动创建用户表,以解决 ActiveAdmin 问题。

编辑 2 - '违规' 代码

class Employers::RegistrationsController < Devise::RegistrationsController
  def create
    super
    session[:omniauth] = nil unless @employer.new_record?
  end

  private

  def build_resource(*args)
    super
    if session[:omniauth]
      @employer.apply_omniauth(session[:omniauth])
    end
  end

  #Overwrite signin to make sure only users are signed in (for backward compatibility)
  def sign_in(resource_or_scope, *args)
    super(:user, *args)
  end

end

【问题讨论】:

  • 你能告诉我们你的表定义吗? (CREATE TABLE sql 语句,不仅仅是你的 ruby​​ 迁移)
  • @pozs - 添加了额外的细节
  • 谢谢,真的很奇怪。 Rails 应该生成一个 auto-incrementid 列(在 Postgres 的情况下,它应该键入 serial 而不是 int - 或者至少它应该有一个默认值,它是序列的下一个值)——从你的CREATE TABLE看来情况并非如此,这就是为什么你必须在INSERT语句中提供id,否则它将违反非空约束。
  • 看起来 id 没有在 Postgres 中正确定义为 serial primary key。如果没有将其声明为自动递增键,则必须在 insert 语句中提供它的值。从 SQL 中删除 id 是在错误的方向上移动。您在(上面)写道,最初的错误是ActiveRecord::NotNullViolation,但您没有说明错误是否表明是哪个字段导致了违规。也许您可以详细说明原始错误?请参阅此内容以供参考:stackoverflow.com/questions/7718585/…
  • @aks - 感谢您的帮助。最后,您对原始错误的评论促使我回到起点,这一次我以正确的顺序找到了正确的步骤,并将其全部启动并运行——按照最初的编码,没有任何调整。干杯。

标签: postgresql ruby-on-rails-3.2 rails-activerecord


【解决方案1】:

你需要写一个alter table migration。

首先,生成迁移

$ rails g migration add_uniqueness_to_users

打开您的迁移文件,并在其中执行以下操作:

class AddUniquenessToUsers < ActiveRecord::Migration
  def up
    change_column(:events, :id, 'SERIAL PRIMARY KEY')
    add_index :events, :id, :unique => true
  end
  def down
    remove_index :events, :id
    change_column(:events, :id, :integer)
  end
end

这完成了您需要的一切,将列类型更新为 SERIAL PRIMARY KEY,这是对列进行增量更新所必需的,在列上添加唯一约束,并确保如果您要在反之亦然。

【讨论】:

  • 感谢您的建议 - 干杯。最后,解决方案如上。
猜你喜欢
  • 1970-01-01
  • 2010-10-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-01
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多