Проверка нуля завершилась неудачно, если указан атрибут rom-rb
Я пытаюсь справиться с библиотекой постоянства rom-rb, используя sqlite3.
Я запустил следующую миграцию, которая включает в себя 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
атрибут равен нулю, когда я его предоставляю?
1 ответ
ПРИМЕЧАНИЕ: я пересмотрел свой ответ после некоторого тестирования и изучения версий ops gem
Причина, по которой вы получаете NULL CONSTRAINT
ошибка в том, что в ПЗУ не загружена схема для таблицы пользователей.
Когда вы определили контейнер ниже
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)
Если вы хотите использовать автономные классы отношений вместо контейнера config dsl, тогда я предлагаю прочитать в системе автоматической регистрации.
ПРОБЛЕМА СОЗДАНИЯ БАЗЫ ДАННЫХ
Существует целый ряд вещей, которые могут помешать созданию базы данных sqlite.
- Это может быть проблема с разрешениями
- Структура каталогов может не существовать
- Sqlite может быть не скомпилирован для обработки URI (имеет значение, только если вы используете
file://
в ваших путях) [см. документы sqlite]
Мой совет здесь заключается в том, что при работе с sqlite и ROM используйте пример хэша opts из приведенного выше сценария и попробуйте использовать относительный путь из текущего рабочего каталога. Это, кажется, всегда работает.