首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当提供rom-rb属性时,空验证失败。

当提供rom-rb属性时,空验证失败。
EN

Stack Overflow用户
提问于 2018-08-21 11:22:02
回答 1查看 297关注 0票数 1

我正在尝试使用sqlite3来处理rom持久性库。

我运行了以下迁移,其中包括一个NOT NULL约束:

代码语言:javascript
复制
ROM::SQL.migration do
  change do
    create_table :users do
      primary_key :id
      column :name, String, null: false
      column :age, Integer
      column :is_admin, TrueClass
    end
  end
end

这是我的简单app.rb

代码语言:javascript
复制
require 'rom'

rom = ROM.container(:sql, 'sqlite://db/my-db-file.db') do |config|
  class Users < ROM::Relation[:sql]
    schema(infer: true)
  end

  config.relation(:users)
end

users = rom.relations[:users]
puts users.to_a.inspect # => []

create_user = users.command(:create)
create_user.call( name: 'Rob', age: 30, is_admin: true )
puts users.to_a.inspect # never reached

试图运行此脚本会产生以下输出:

代码语言:javascript
复制
Roberts-MacBook-Pro:my-rom-demo Rob$ ruby app.rb 
[]
/Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:108:in `step': SQLite3::ConstraintException: NOT NULL constraint failed: users.name (ROM::SQL::NotNullConstraintError)
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:108:in `block in each'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:107:in `loop'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:107:in `each'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:156:in `to_a'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:156:in `block in execute'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:95:in `prepare'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:137:in `execute'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/sequel-5.11.0/lib/sequel/adapters/sqlite.rb:189:in `block (2 levels) in _execute'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/sequel-5.11.0/lib/sequel/database/logging.rb:38:in `log_connection_yield'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/sequel-5.11.0/lib/sequel/adapters/sqlite.rb:189:in `block in _execute'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/sequel-5.11.0/lib/sequel/database/connecting.rb:253:in `block in synchronize'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/sequel-5.11.0/lib/sequel/connection_pool/threaded.rb:91:in `hold'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/sequel-5.11.0/lib/sequel/database/connecting.rb:253:in `synchronize'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/sequel-5.11.0/lib/sequel/adapters/sqlite.rb:180:in `_execute'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/sequel-5.11.0/lib/sequel/adapters/sqlite.rb:146:in `execute_insert'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/sequel-5.11.0/lib/sequel/dataset/actions.rb:1099:in `execute_insert'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/sequel-5.11.0/lib/sequel/dataset/actions.rb:399:in `insert'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/rom-sql-2.5.0/lib/rom/sql/relation/writing.rb:39:in `insert'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/rom-sql-2.5.0/lib/rom/sql/commands/create.rb:46:in `block in insert'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/rom-sql-2.5.0/lib/rom/sql/commands/create.rb:46:in `map'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/rom-sql-2.5.0/lib/rom/sql/commands/create.rb:46:in `insert'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/rom-sql-2.5.0/lib/rom/sql/commands/create.rb:31:in `execute'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/rom-core-4.2.1/lib/rom/command.rb:280:in `call'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/rom-sql-2.5.0/lib/rom/sql/commands/error_wrapper.rb:16:in `call'
    from /Rob.rvm/gems/ruby-2.4.0@learn-rails/gems/rom-core-4.2.1/lib/rom/commands/composite.rb:17:in `call'
    from app.rb:15:in `<main>'

当我提供name属性时,它为什么认为它是空的呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-08-21 22:48:46

注意:在测试和学习了ops gem版本之后,修改了我的答案。

您获得NULL CONSTRAINT错误的原因是因为ROM没有为users表加载模式。

当您定义下面的容器时

代码语言:javascript
复制
rom = ROM.container(:sql, 'sqlite://db/my-db-file.db') do |config|
  class Users < ROM::Relation[:sql]
    schema(infer: true)
  end

  config.relation(:users)
end

您定义了两件事,一个绑定到一个名为Users的常量的关系类和一个自动生成的名称相同的关系,但实际上是在ROM容器中注册的。有效地忽略了Users常数关系。之所以这么做很重要,是因为自动生成的关系不会自动从数据库中推断出模式,所以当您将数据写出来时,模式会强制删除所有导致错误的未知键。您要发送到数据库的全部是{}

要修复错误,只需告诉关系来推断模式-下面可以看到一个例子。

代码语言:javascript
复制
require 'rom'
require 'rom/sql'
require 'sqlite3'

puts "ROM Version #{ROM::Core::VERSION}" # 4.2.1
puts "ROM Version #{ROM::SQL::VERSION}" # 2.5.0
puts "Sequel Version #{Sequel::VERSION}" # 5.11.0
puts "SQLite3 Gem Version #{SQLite3::VERSION}" # 1.3.13

opts = {
  adapter: :sqlite,
  database: 'c:/mydb.db'
}

rom = ROM.container(:sql, opts) do |c|
  # Just another way to write the same users table
  # c.gateways[:default].create_table(:users) do
  #   column :id,   :integer, primary_key: true
  #   column :name, :string, null: false
  #   column :age,  :integer
  #   column :is_admin, :bool
  # end

  c.gateways[:default].create_table :users do
    primary_key :id
    column :name, String, null: false
    column :age, Integer
    column :is_admin, TrueClass
  end

  c.relation(:users) do
    schema(infer: true)
  end
end

users = rom.relations[:users]
puts users.to_a.inspect # => []

create_user = users.command(:create)
create_user.call(name: 'Rob', age: 30, is_admin: true)
puts users.to_a.inspect # never reached

# Uncomment if you want to see the users schema
# puts users.dataset.db.schema(:users)

如果您想使用独立关系类而不是容器配置dsl,那么我建议阅读自动注册系统

数据库创建问题

有很多事情可能会发生,这些事情可能会阻止创建sqlite数据库。

  • 这可能是权限问题
  • 目录结构可能不存在。
  • Sqlite可能不会被编译来处理URI(仅当您在路径中使用file://时才重要) https://www.sqlite.org/uri.html

我在这里的建议是,当使用sqlite和ROM时,使用上面脚本中的opts散列示例,并尝试使用来自当前工作目录的相对路径。这似乎总是有效的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51947597

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档