Rails - 使用NOT NULL约束保存对象

时间:2015-06-21 16:42:54

标签: sql ruby-on-rails ruby ruby-on-rails-4

我有一个名为Issue的模型,它具有以下数据库结构:

class CreateIssues < ActiveRecord::Migration
  def change
    create_table :issues do |t|
      t.string :path, null: false
      t.string :filename, null: false
      t.string :name, null: false
      t.string :year
      t.integer :number
      t.timestamps null: false
    end
  end
end

在我的模型测试中,我使用以下行:

issue = Issue.create path: "test_path", filename: "test_filename", name: "test_name"

...在保存时会引发异常:

 SQLite3::ConstraintException: NOT NULL constraint failed:
 issues.path: INSERT INTO "issues" ("created_at", "updated_at") VALUES (?, ?)

据我所知,在调用createnew/save时,rails首先插入一个只包含时间戳的条目。我希望insert包含我传递给create方法的所有值。我在创作过程中错过了一步吗?

编辑:

基本信息和步骤:

  • 使用SQLite3
  • 使用Rails 4.2.1
  • 使用RSpec
  • 使用be rails generate model Issue
  • 生成问题模型
  • 手动添加NULL约束
  • be rake db:migrate成功了
  • 在各种模型规范文件中尝试我的代码

尝试了其他模型,我得到的生成的SQL只包含时间戳。

编辑2: 这是我的问题模型:

class Issue < ActiveRecord::Base
  has_one :pending_issue
  has_one :watched_issue
  has_many :unmatched_issues

  validates :path, presence: true
  validates :filename, presence: true
  validates :name, presence: true

  attr_accessor :path
  attr_accessor :filename
  attr_accessor :name
  attr_accessor :year
  attr_accessor :number
end

2 个答案:

答案 0 :(得分:1)

你的结果是异常的。这就是我得到的:

# migration
class CreateIssues < ActiveRecord::Migration
  def change
    create_table :issues do |t|
      t.string :path, null: false

      t.timestamps null: false
    end
  end
end

然后在控制台中:

Issue.create path: "path"
# (0.1ms)  begin transaction
# SQL (0.3ms)  INSERT INTO "issues" ("path", "created_at", "updated_at") VALUES (?, ?, ?)  [["path", "path"], ["created_at", "2015-06-21 16:55:08.304653"], ["updated_at", "2015-06-21 16:55:08.304653"]]
# (0.8ms)  commit transaction
# => #<Issue id: 1, path: "path", created_at: "2015-06-21 16:55:08", updated_at: "2015-06-21 16:55:08"> 

我的测试:

require "test_helper"

describe Issue do

  it "can be created" do
    Issue.create path: "test_path"
  end
end

通过。没有例外。

我认为可能发生的是您的数据库架构已经在测试数据库上过时了。

首先,类似的&#39;创造&#39;在开发(默认)rails控制台工作?如果是这样,那么这表明您的测试和开发环境中存在很大差异。

如果强制控制台使用测试环境会怎样?

RAILS_ENV=test rails c

这可以吗?

我认为您可能需要手动将测试数据库回滚到首次创建问题表的迁移,然后重新迁移

RAILS_ENV=test rake db:rollback

继续申请,直至达到适当的迁移,然后:

RAILS_ENV=test rake db:migrate

这有帮助吗?

编辑:

这似乎是个问题:

attr_accessor :path
attr_accessor :filename
attr_accessor :name
attr_accessor :year
attr_accessor :number

这些将覆盖Rails默认访问器,猜测。当然不需要它们。

答案 1 :(得分:0)

您是否意外省略了attr_accessible:path?