我正在尝试使用sqlite3来处理rom持久性库。
我运行了以下迁移,其中包括一个NOT NULL约束:
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
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试图运行此脚本会产生以下输出:
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属性时,它为什么认为它是空的呢?
发布于 2018-08-21 22:48:46
注意:在测试和学习了ops gem版本之后,修改了我的答案。
您获得NULL CONSTRAINT错误的原因是因为ROM没有为users表加载模式。
当您定义下面的容器时
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常数关系。之所以这么做很重要,是因为自动生成的关系不会自动从数据库中推断出模式,所以当您将数据写出来时,模式会强制删除所有导致错误的未知键。您要发送到数据库的全部是{}。
要修复错误,只需告诉关系来推断模式-下面可以看到一个例子。
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数据库。
file://时才重要) https://www.sqlite.org/uri.html我在这里的建议是,当使用sqlite和ROM时,使用上面脚本中的opts散列示例,并尝试使用来自当前工作目录的相对路径。这似乎总是有效的。
https://stackoverflow.com/questions/51947597
复制相似问题