diff --git a/.circleci/config.yml b/.circleci/config.yml
index c5552d93..bcd501c3 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -58,7 +58,8 @@ jobs:
- run:
name: install MySQL client
command: |
- sudo apt install -y mysql-client
+ sudo apt-get update
+ sudo apt install -y default-mysql-client
- run:
name: install dependencies
command: |
@@ -100,7 +101,7 @@ jobs:
name: install PostgreSQL client
command: |
wget -q https://www.postgresql.org/media/keys/ACCC4CF8.asc -O - | sudo apt-key add -
- sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ stretch-pgdg main" >> /etc/apt/sources.list.d/pgdg.list'
+ sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ buster-pgdg main" >> /etc/apt/sources.list.d/pgdg.list'
sudo apt-get update
sudo apt install -y postgresql-contrib
- run:
diff --git a/.drone.yml b/.drone.yml
index eac5309d..1475ec98 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -177,186 +177,6 @@ services:
POSTGRES_USER: postgres
POSTGRES_DB: hanami_model
----
-kind: pipeline
-name: ruby-2-4
-group: build
-
-steps:
-- name: install
- image: hanami/ruby-2.4-db
- volumes:
- - name: bundle
- path: /usr/local/bundle
- commands:
- - ruby -v
- - gem install bundler
- - bundle install --jobs=3 --retry=3
-
-- name: unit-sqlite3
- image: hanami/ruby-2.4-db
- volumes:
- - name: bundle
- path: /usr/local/bundle
- environment:
- DB: sqlite3
- DRONE: true
- commands:
- - COVERAGE=true bundle exec rake
-
-- name: unit-mysql
- image: hanami/ruby-2.4-db
- volumes:
- - name: bundle
- path: /usr/local/bundle
- environment:
- DB: mysql
- HANAMI_DATABASE_USERNAME: root
- HANAMI_DATABASE_PASSWORD:
- HANAMI_DATABASE_HOST: mysql-server # see below: services -> name
- commands:
- - mysql -u $HANAMI_DATABASE_USERNAME -h $HANAMI_DATABASE_HOST --execute="SELECT VERSION();" # assert can connect to database
- - COVERAGE=true bundle exec rake
-
-- name: unit-postgres
- image: hanami/ruby-2.4-db
- volumes:
- - name: bundle
- path: /usr/local/bundle
- environment:
- DB: postgres
- HANAMI_DATABASE: hanami_model
- HANAMI_DATABASE_USERNAME: postgres
- HANAMI_DATABASE_PASSWORD:
- HANAMI_DATABASE_HOST: postgres-server # see below: services -> name
- commands:
- - psql -U $HANAMI_DATABASE_USERNAME -d $HANAMI_DATABASE -h $HANAMI_DATABASE_HOST # assert can connect to database
- - COVERAGE=true bundle exec rake
-
-- name: quality
- image: hanami/ruby-2.4-db
- environment:
- CODECOV_TOKEN:
- from_secret: codecov
- volumes:
- - name: bundle
- path: /usr/local/bundle
- commands:
- - bundle exec rubocop
- - CI=true bundle exec rake codecov:upload
-
-volumes:
-- name: bundle
- temp: {}
-
-services:
-- name: mysql-server
- image: mysql
- ports:
- - 3306
- environment:
- MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
- MYSQL_DATABASE: hanami_model
- command: ["--default-authentication-plugin=mysql_native_password"]
-
-- name: postgres-server
- image: postgres:11-alpine
- ports:
- - 5432
- environment:
- POSTGRES_USER: postgres
- POSTGRES_DB: hanami_model
-
----
-kind: pipeline
-name: ruby-2-3
-group: build
-
-steps:
-- name: install
- image: hanami/ruby-2.3-db
- volumes:
- - name: bundle
- path: /usr/local/bundle
- commands:
- - ruby -v
- - gem install bundler
- - bundle install --jobs=3 --retry=3
-
-- name: unit-sqlite3
- image: hanami/ruby-2.3-db
- volumes:
- - name: bundle
- path: /usr/local/bundle
- environment:
- DB: sqlite3
- DRONE: true
- commands:
- - COVERAGE=true bundle exec rake
-
-- name: unit-mysql
- image: hanami/ruby-2.3-db
- volumes:
- - name: bundle
- path: /usr/local/bundle
- environment:
- DB: mysql
- HANAMI_DATABASE_USERNAME: root
- HANAMI_DATABASE_PASSWORD:
- HANAMI_DATABASE_HOST: mysql-server # see below: services -> name
- commands:
- - mysql -u $HANAMI_DATABASE_USERNAME -h $HANAMI_DATABASE_HOST --execute="SELECT VERSION();" # assert can connect to database
- - COVERAGE=true bundle exec rake
-
-- name: unit-postgres
- image: hanami/ruby-2.3-db
- volumes:
- - name: bundle
- path: /usr/local/bundle
- environment:
- DB: postgres
- HANAMI_DATABASE: hanami_model
- HANAMI_DATABASE_USERNAME: postgres
- HANAMI_DATABASE_PASSWORD:
- HANAMI_DATABASE_HOST: postgres-server # see below: services -> name
- commands:
- - psql -U $HANAMI_DATABASE_USERNAME -d $HANAMI_DATABASE -h $HANAMI_DATABASE_HOST # assert can connect to database
- - COVERAGE=true bundle exec rake
-
-- name: quality
- image: hanami/ruby-2.3-db
- environment:
- CODECOV_TOKEN:
- from_secret: codecov
- volumes:
- - name: bundle
- path: /usr/local/bundle
- commands:
- - bundle exec rubocop
- - CI=true bundle exec rake codecov:upload
-
-volumes:
-- name: bundle
- temp: {}
-
-services:
-- name: mysql-server
- image: mysql
- ports:
- - 3306
- environment:
- MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
- MYSQL_DATABASE: hanami_model
- command: ["--default-authentication-plugin=mysql_native_password"]
-
-- name: postgres-server
- image: postgres:11-alpine
- ports:
- - 5432
- environment:
- POSTGRES_USER: postgres
- POSTGRES_DB: hanami_model
-
---
kind: pipeline
name: slack
@@ -366,7 +186,7 @@ clone:
disable: true
depends_on:
- - ruby-2-3
+ - ruby-2-5
steps:
- name: slack
diff --git a/.rubocop.yml b/.rubocop.yml
index 927223c1..a5e64e93 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -1,7 +1,7 @@
# Please keep AllCops, Bundler, Style, Metrics groups and then order cops
# alphabetically
inherit_from:
- - https://raw.githubusercontent.com/hanami/devtools/master/.rubocop.yml
+ - https://raw.githubusercontent.com/hanami/devtools/master/.rubocop-unstable.yml
Naming/RescuedExceptionsVariableName:
PreferredName: "exception"
Style/RescueStandardError:
diff --git a/.travis.yml b/.travis.yml
index b36c941f..004bc81c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,13 +4,9 @@ cache: bundler
script: 'bundle exec rubocop && bundle exec rake spec:unit --trace'
after_script: 'echo `env`'
rvm:
- - 2.3.8
- - 2.4.5
- - 2.5.3
- - 2.6.0
- - jruby-9.1.9.0
+ - 2.5
+ - 2.6
- ruby-head
- - jruby-head
env:
- DB=sqlite
- DB=postgresql
@@ -22,8 +18,7 @@ addons:
matrix:
allow_failures:
- rvm: ruby-head
- - rvm: jruby-head
- - rvm: jruby-9.1.9.0
+ - env: DB=mysql
notifications:
webhooks:
diff --git a/Gemfile b/Gemfile
index 19ba243a..3a1fc9cc 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,19 +1,21 @@
-source 'https://rubygems.org'
+# frozen_string_literal: true
+
+source "https://rubygems.org"
gemspec
-unless ENV['CI']
- gem 'byebug', require: false, platforms: :mri
- gem 'yard', require: false
+unless ENV["CI"]
+ gem "byebug", require: false, platforms: :mri
+ gem "yard", require: false
end
-gem 'hanami-utils', '~> 1.3', require: false, git: 'https://github.com/hanami/utils.git', branch: 'master'
+gem "hanami-utils", "~> 2.0.alpha", require: false, git: "https://github.com/hanami/utils.git", branch: "unstable"
-gem 'sqlite3', require: false, platforms: :mri, group: :sqlite
-gem 'pg', require: false, platforms: :mri, group: :postgres
-gem 'mysql2', require: false, platforms: :mri, group: :mysql
+gem "sqlite3", require: false, platforms: :mri, group: :sqlite
+gem "pg", require: false, platforms: :mri, group: :postgres
+gem "mysql2", require: false, platforms: :mri, group: :mysql
-gem 'jdbc-sqlite3', require: false, platforms: :jruby, group: :sqlite
-gem 'jdbc-postgres', require: false, platforms: :jruby, group: :postgres
-gem 'jdbc-mysql', require: false, platforms: :jruby, group: :mysql
+gem "jdbc-sqlite3", require: false, platforms: :jruby, group: :sqlite
+gem "jdbc-postgres", require: false, platforms: :jruby, group: :postgres
+gem "jdbc-mysql", require: false, platforms: :jruby, group: :mysql
-gem 'hanami-devtools', require: false, git: 'https://github.com/hanami/devtools.git'
+gem "hanami-devtools", require: false, git: "https://github.com/hanami/devtools.git"
diff --git a/README.md b/README.md
index d5e7de28..cce22622 100644
--- a/README.md
+++ b/README.md
@@ -32,7 +32,7 @@ Like all the other Hanami components, it can be used as a standalone framework o
## Rubies
-__Hanami::Model__ supports Ruby (MRI) 2.3+ and JRuby 9.1.5.0+
+__Hanami::Model__ supports Ruby (MRI) 2.5+
## Installation
@@ -295,6 +295,6 @@ __Hanami::Model__ uses [Semantic Versioning 2.0.0](http://semver.org)
## Copyright
-Copyright © 2014-2017 Luca Guidi – Released under MIT License
+Copyright © 2014-2019 Luca Guidi – Released under MIT License
This project was formerly known as Lotus (`lotus-model`).
diff --git a/Rakefile b/Rakefile
index 731a8077..8d1de97a 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,12 +1,14 @@
-require 'rake'
-require 'bundler/gem_tasks'
-require 'rspec/core/rake_task'
-require 'hanami/devtools/rake_tasks'
+# frozen_string_literal: true
+
+require "rake"
+require "bundler/gem_tasks"
+require "rspec/core/rake_task"
+require "hanami/devtools/rake_tasks"
namespace :spec do
RSpec::Core::RakeTask.new(:unit) do |task|
- task.pattern = FileList['spec/**/*_spec.rb']
+ task.pattern = FileList["spec/**/*_spec.rb"]
end
end
-task default: 'spec:unit'
+task default: "spec:unit"
diff --git a/hanami-model.gemspec b/hanami-model.gemspec
index 32c94a62..4bfd76c1 100644
--- a/hanami-model.gemspec
+++ b/hanami-model.gemspec
@@ -1,32 +1,34 @@
-lib = File.expand_path('../lib', __FILE__)
+# frozen_string_literal: true
+
+lib = File.expand_path("../lib", __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
-require 'hanami/model/version'
+require "hanami/model/version"
Gem::Specification.new do |spec|
- spec.name = 'hanami-model'
+ spec.name = "hanami-model"
spec.version = Hanami::Model::VERSION
- spec.authors = ['Luca Guidi']
- spec.email = ['me@lucaguidi.com']
- spec.summary = 'A persistence layer for Hanami'
- spec.description = 'A persistence framework with entities and repositories'
- spec.homepage = 'http://hanamirb.org'
- spec.license = 'MIT'
+ spec.authors = ["Luca Guidi"]
+ spec.email = ["me@lucaguidi.com"]
+ spec.summary = "A persistence layer for Hanami"
+ spec.description = "A persistence framework with entities and repositories"
+ spec.homepage = "http://hanamirb.org"
+ spec.license = "MIT"
spec.files = `git ls-files -z -- lib/* CHANGELOG.md EXAMPLE.md LICENSE.md README.md hanami-model.gemspec`.split("\x0")
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
- spec.require_paths = ['lib']
- spec.required_ruby_version = '>= 2.3.0'
+ spec.require_paths = ["lib"]
+ spec.required_ruby_version = ">= 2.5.0"
- spec.add_runtime_dependency 'hanami-utils', '~> 1.3'
- spec.add_runtime_dependency 'rom', '~> 3.3', '>= 3.3.3'
- spec.add_runtime_dependency 'rom-sql', '~> 1.3', '>= 1.3.5'
- spec.add_runtime_dependency 'rom-repository', '~> 1.4'
- spec.add_runtime_dependency 'dry-types', '~> 0.11.0'
- spec.add_runtime_dependency 'dry-logic', '~> 0.4.2', '< 0.5'
- spec.add_runtime_dependency 'concurrent-ruby', '~> 1.0'
+ spec.add_runtime_dependency "hanami-utils", "~> 2.0.alpha"
+ spec.add_runtime_dependency "rom", "~> 5.2"
+ spec.add_runtime_dependency "rom-repository", "~> 5.2"
+ spec.add_runtime_dependency "rom-sql", "~> 3.2"
+ spec.add_runtime_dependency "dry-types", "~> 1.3"
+ spec.add_runtime_dependency "dry-inflector", "~> 0.1"
+ spec.add_runtime_dependency "concurrent-ruby", "~> 1.0"
- spec.add_development_dependency 'bundler', '>= 1.6', '< 3'
- spec.add_development_dependency 'rake', '~> 12'
- spec.add_development_dependency 'rspec', '~> 3.7'
+ spec.add_development_dependency "bundler", ">= 1.6", "< 3"
+ spec.add_development_dependency "rake", "~> 12"
+ spec.add_development_dependency "rspec", "~> 3.8"
end
diff --git a/lib/hanami-model.rb b/lib/hanami-model.rb
deleted file mode 100644
index 1372783d..00000000
--- a/lib/hanami-model.rb
+++ /dev/null
@@ -1 +0,0 @@
-require 'hanami/model'
diff --git a/lib/hanami/entity.rb b/lib/hanami/entity.rb
index fed77813..f11002e6 100644
--- a/lib/hanami/entity.rb
+++ b/lib/hanami/entity.rb
@@ -1,4 +1,7 @@
-require 'hanami/model/types'
+# frozen_string_literal: true
+
+require "dry/struct"
+require "hanami/model/types"
module Hanami
# An object that is defined by its identity.
@@ -40,7 +43,7 @@ module Hanami
# implements that interface then that object can be used as an Entity in the
# **Hanami::Model** framework.
#
- # However, we suggest to implement this interface by including
+ # However, we suggest to implement this interface by inheriting
# `Hanami::Entity`, in case that future versions of the framework will expand
# it.
#
@@ -49,167 +52,52 @@ module Hanami
# @since 0.1.0
#
# @see Hanami::Repository
- class Entity
- require 'hanami/entity/schema'
-
- # Syntactic shortcut to reference types in custom schema DSL
- #
- # @since 0.7.0
- module Types
- include Hanami::Model::Types
- end
-
- # Class level interface
+ class Entity < ROM::Struct
+ # Note: This is keeping with the previous "Schemaless" interface that we had.
+ # def self.load(attributes = {})
+ # return attributes if attributes.is_a?(self)
#
- # @since 0.7.0
- # @api private
- module ClassMethods
- # Define manual entity schema
- #
- # With a SQL database this setup happens automatically and you SHOULD NOT
- # use this DSL. You should use only when you want to customize the automatic
- # setup.
- #
- # If you're working with an entity that isn't "backed" by a SQL table or
- # with a schema-less database, you may want to manually setup a set of
- # attributes via this DSL. If you don't do any setup, the entity accepts all
- # the given attributes.
- #
- # @param type [Symbol] the type of schema to build
- # @param blk [Proc] the block that defines the attributes
- #
- # @since 0.7.0
- #
- # @see Hanami::Entity
- def attributes(type = nil, &blk)
- self.schema = Schema.new(type, &blk)
- @attributes = true
- end
-
- # Assign a schema
- #
- # @param value [Hanami::Entity::Schema] the schema
- #
- # @since 0.7.0
- # @api private
- def schema=(value)
- return if defined?(@attributes)
+ # super(Utils::Hash.deep_symbolize(attributes.to_hash)).freeze
+ # end
- @schema = value
- end
+ # class << self
+ # alias new load
+ # alias call load
+ # alias call_unsafe load
+ # end
- # @since 0.7.0
- # @api private
- attr_reader :schema
- end
-
- # @since 0.7.0
- # @api private
- def self.inherited(klass)
- klass.class_eval do
- @schema = Schema.new
- extend ClassMethods
- end
- end
-
- # Instantiate a new entity
- #
- # @param attributes [Hash,#to_h,NilClass] data to initialize the entity
- #
- # @return [Hanami::Entity] the new entity instance
- #
- # @raise [TypeError] if the given attributes are invalid
- #
- # @since 0.1.0
- def initialize(attributes = nil)
- @attributes = self.class.schema[attributes]
- freeze
- end
-
- # Entity ID
- #
- # @return [Object,NilClass] the ID, if present
- #
- # @since 0.7.0
def id
- attributes.fetch(:id, nil)
- end
-
- # Handle dynamic accessors
- #
- # If internal attributes set has the requested key, it returns the linked
- # value, otherwise it raises a NoMethodError
- #
- # @since 0.7.0
- def method_missing(method_name, *)
- attribute?(method_name) or super
- attributes.fetch(method_name, nil)
+ attributes.fetch(:id) { nil }
end
- # Implement generic equality for entities
- #
- # Two entities are equal if they are instances of the same class and they
- # have the same id.
- #
- # @param other [Object] the object of comparison
- #
- # @return [FalseClass,TrueClass] the result of the check
- #
- # @since 0.1.0
- def ==(other)
- self.class == other.class &&
- id == other.id
- end
-
- # Implement predictable hashing for hash equality
- #
- # @return [Integer] the object hash
- #
- # @since 0.7.0
def hash
[self.class, id].hash
end
- # Freeze the entity
- #
- # @since 0.7.0
- def freeze
- attributes.freeze
- super
+ def ==(other)
+ self.class.to_s == other.class.to_s && id == other.id
end
- # Serialize entity to a Hash
- #
- # @return [Hash] the result of serialization
- #
- # @since 0.1.0
- def to_h
- Utils::Hash.deep_dup(attributes)
- end
+ # def to_h
+ # Utils::Hash.deep_dup(attributes)
+ # end
+ # alias to_hash to_h
- # @since 0.7.0
- alias to_hash to_h
+ # def inspect
+ # "#<#{self.class.name} #{attributes.map { |k, v| "#{k}=#{v.inspect}" }.join(' ')}>"
+ # end
+ # alias to_s inspect
- protected
+ def method_missing(method_name, *args)
+ # return attributes[method_name] if args.empty? && attributes.key?(method_name)
- # Check if the attribute is allowed to be read
- #
- # @since 0.7.0
- # @api private
- def attribute?(name)
- self.class.schema.attribute?(name)
+ super
+ rescue => exception
+ raise Hanami::Model::Error.for(exception)
end
- private
-
- # @since 0.1.0
- # @api private
- attr_reader :attributes
-
- # @since 0.7.0
- # @api private
- def respond_to_missing?(name, _include_all)
- attribute?(name)
- end
+ # def respond_to_missing?(method_name, include_all)
+ # super || attributes.key?(method_name)
+ # end
end
end
diff --git a/lib/hanami/entity/schema.rb b/lib/hanami/entity/schema.rb
deleted file mode 100644
index 9678ec84..00000000
--- a/lib/hanami/entity/schema.rb
+++ /dev/null
@@ -1,267 +0,0 @@
-require 'hanami/model/types'
-require 'hanami/utils/hash'
-
-module Hanami
- class Entity
- # Entity schema is a definition of a set of typed attributes.
- #
- # @since 0.7.0
- # @api private
- #
- # @example SQL Automatic Setup
- # require 'hanami/model'
- #
- # class Account < Hanami::Entity
- # end
- #
- # account = Account.new(name: "Acme Inc.")
- # account.name # => "Hanami"
- #
- # account = Account.new(foo: "bar")
- # account.foo # => NoMethodError
- #
- # @example Non-SQL Manual Setup
- # require 'hanami/model'
- #
- # class Account < Hanami::Entity
- # attributes do
- # attribute :id, Types::Int
- # attribute :name, Types::String
- # attribute :codes, Types::Array(Types::Int)
- # attribute :users, Types::Array(User)
- # attribute :email, Types::String.constrained(format: /@/)
- # attribute :created_at, Types::DateTime
- # end
- # end
- #
- # account = Account.new(name: "Acme Inc.")
- # account.name # => "Acme Inc."
- #
- # account = Account.new(foo: "bar")
- # account.foo # => NoMethodError
- #
- # @example Schemaless Entity
- # require 'hanami/model'
- #
- # class Account < Hanami::Entity
- # end
- #
- # account = Account.new(name: "Acme Inc.")
- # account.name # => "Acme Inc."
- #
- # account = Account.new(foo: "bar")
- # account.foo # => "bar"
- class Schema
- # Schemaless entities logic
- #
- # @since 0.7.0
- # @api private
- class Schemaless
- # @since 0.7.0
- # @api private
- def initialize
- freeze
- end
-
- # @param attributes [#to_hash] the attributes hash
- #
- # @return [Hash]
- #
- # @since 0.7.0
- # @api private
- def call(attributes)
- if attributes.nil?
- {}
- else
- Utils::Hash.deep_symbolize(attributes.to_hash.dup)
- end
- end
-
- # @since 0.7.0
- # @api private
- def attribute?(_name)
- true
- end
- end
-
- # Schema definition
- #
- # @since 0.7.0
- # @api private
- class Definition
- # Schema DSL
- #
- # @since 0.7.0
- class Dsl
- # @since 1.1.0
- # @api private
- TYPES = %i[schema strict weak permissive strict_with_defaults symbolized].freeze
-
- # @since 1.1.0
- # @api private
- DEFAULT_TYPE = TYPES.first
-
- # @since 0.7.0
- # @api private
- def self.build(type, &blk)
- type ||= DEFAULT_TYPE
- raise Hanami::Model::Error.new("Unknown schema type: `#{type.inspect}'") unless TYPES.include?(type)
-
- attributes = new(&blk).to_h
- [attributes, Hanami::Model::Types::Coercible::Hash.__send__(type, attributes)]
- end
-
- # @since 0.7.0
- # @api private
- def initialize(&blk)
- @attributes = {}
- instance_eval(&blk)
- end
-
- # Define an attribute
- #
- # @param name [Symbol] the attribute name
- # @param type [Dry::Types::Definition] the attribute type
- #
- # @since 0.7.0
- #
- # @example
- # require 'hanami/model'
- #
- # class Account < Hanami::Entity
- # attributes do
- # attribute :id, Types::Int
- # attribute :name, Types::String
- # attribute :codes, Types::Array(Types::Int)
- # attribute :users, Types::Array(User)
- # attribute :email, Types::String.constrained(format: /@/)
- # attribute :created_at, Types::DateTime
- # end
- # end
- #
- # account = Account.new(name: "Acme Inc.")
- # account.name # => "Acme Inc."
- #
- # account = Account.new(foo: "bar")
- # account.foo # => NoMethodError
- def attribute(name, type)
- @attributes[name] = type
- end
-
- # @since 0.7.0
- # @api private
- def to_h
- @attributes
- end
- end
-
- # Instantiate a new DSL instance for an entity
- #
- # @param blk [Proc] the block that defines the attributes
- #
- # @return [Hanami::Entity::Schema::Dsl] the DSL
- #
- # @since 0.7.0
- # @api private
- def initialize(type = nil, &blk)
- raise LocalJumpError unless block_given?
-
- @attributes, @schema = Dsl.build(type, &blk)
- @attributes = Hash[@attributes.map { |k, _| [k, true] }]
- freeze
- end
-
- # Process attributes
- #
- # @param attributes [#to_hash] the attributes hash
- #
- # @raise [TypeError] if the process fails
- # @raise [ArgumentError] if data is missing, or unknown keys are given
- #
- # @since 0.7.0
- # @api private
- def call(attributes)
- schema.call(attributes)
- rescue Dry::Types::SchemaError => exception
- raise TypeError.new(exception.message)
- rescue Dry::Types::MissingKeyError, Dry::Types::UnknownKeysError => exception
- raise ArgumentError.new(exception.message)
- end
-
- # Check if the attribute is known
- #
- # @param name [Symbol] the attribute name
- #
- # @return [TrueClass,FalseClass] the result of the check
- #
- # @since 0.7.0
- # @api private
- def attribute?(name)
- attributes.key?(name)
- end
-
- private
-
- # @since 0.7.0
- # @api private
- attr_reader :schema
-
- # @since 0.7.0
- # @api private
- attr_reader :attributes
- end
-
- # Build a new instance of Schema with the attributes defined by the given block
- #
- # @param blk [Proc] the optional block that defines the attributes
- #
- # @return [Hanami::Entity::Schema] the schema
- #
- # @since 0.7.0
- # @api private
- def initialize(type = nil, &blk)
- @schema = if block_given?
- Definition.new(type, &blk)
- else
- Schemaless.new
- end
- end
-
- # Process attributes
- #
- # @param attributes [#to_hash] the attributes hash
- #
- # @raise [TypeError] if the process fails
- #
- # @since 0.7.0
- # @api private
- def call(attributes)
- Utils::Hash.deep_symbolize(
- schema.call(attributes)
- )
- end
-
- # @since 0.7.0
- # @api private
- alias [] call
-
- # Check if the attribute is known
- #
- # @param name [Symbol] the attribute name
- #
- # @return [TrueClass,FalseClass] the result of the check
- #
- # @since 0.7.0
- # @api private
- def attribute?(name)
- schema.attribute?(name)
- end
-
- protected
-
- # @since 0.7.0
- # @api private
- attr_reader :schema
- end
- end
-end
diff --git a/lib/hanami/entity/schemaless.rb b/lib/hanami/entity/schemaless.rb
new file mode 100644
index 00000000..b887f8b2
--- /dev/null
+++ b/lib/hanami/entity/schemaless.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require "dry/struct"
+require "hanami/utils/hash"
+
+module Hanami
+ class OldEntity < Dry::Struct
+ # Schemaless entity
+ #
+ # @since 2.0.0
+ class Schemaless < Dry::Struct
+ def self.load(attributes = {})
+ return attributes if attributes.is_a?(self)
+
+ super(Utils::Hash.deep_symbolize(attributes.to_hash)).freeze
+ end
+
+ class << self
+ alias new load
+ alias call load
+ alias call_unsafe load
+ end
+
+ def id
+ attributes.fetch(:id, nil)
+ end
+
+ def method_missing(method_name, *args)
+ if args.empty? && attributes.key?(method_name)
+ attributes[method_name]
+ else
+ super
+ end
+ end
+
+ def respond_to_missing?(method_name, include_all)
+ super || attributes.key?(method_name)
+ end
+
+ def freeze
+ attributes.freeze
+ super
+ end
+
+ def to_h
+ Utils::Hash.deep_dup(attributes)
+ end
+
+ alias to_hash to_h
+
+ def inspect
+ "#<#{self.class.name} #{attributes.map { |k, v| "#{k}=#{v.inspect}" }.join(' ')}>"
+ end
+ alias to_s inspect
+
+ protected
+
+ # Check if the attribute is allowed to be read
+ #
+ # @since 0.7.0
+ # @api private
+ def attribute?(name)
+ self.class.has_attribute?(name)
+ end
+ end
+ end
+end
diff --git a/lib/hanami/entity/strict.rb b/lib/hanami/entity/strict.rb
new file mode 100644
index 00000000..649df59d
--- /dev/null
+++ b/lib/hanami/entity/strict.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Hanami
+ class OldEntity < Dry::Struct
+ # Strict entity
+ #
+ # @since 2.0.0
+ class Strict < OldEntity
+ def self.schema_policy
+ lambda do |entity|
+ entity.class_eval do
+ schema schema.strict
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/hanami/model.rb b/lib/hanami/model.rb
index eed332eb..371d61b2 100644
--- a/lib/hanami/model.rb
+++ b/lib/hanami/model.rb
@@ -1,7 +1,10 @@
-require 'rom'
-require 'concurrent'
-require 'hanami/entity'
-require 'hanami/repository'
+# frozen_string_literal: true
+
+require "rom"
+require "concurrent"
+require "hanami/entity"
+require "hanami/relation"
+require "hanami/repository"
# Hanami
#
@@ -11,12 +14,11 @@ module Hanami
#
# @since 0.1.0
module Model
- require 'hanami/model/version'
- require 'hanami/model/error'
- require 'hanami/model/configuration'
- require 'hanami/model/configurator'
- require 'hanami/model/mapping'
- require 'hanami/model/plugins'
+ require "hanami/model/version"
+ require "hanami/model/error"
+ require "hanami/model/configuration"
+ require "hanami/model/configurator"
+ require "hanami/model/plugins"
# @api private
# @since 0.7.0
@@ -70,17 +72,11 @@ def self.repositories
# @since 0.7.0
# @api private
def self.container
- raise 'Not loaded' unless loaded?
+ raise "Not loaded" unless loaded?
@container
end
- # @since 0.1.0
- def self.load!(&blk)
- @container = configuration.load!(repositories, &blk)
- @loaded = true
- end
-
# Disconnect from the database
#
# This is useful for rebooting applications in production and to ensure that
diff --git a/lib/hanami/model/association.rb b/lib/hanami/model/association.rb
deleted file mode 100644
index 897e7600..00000000
--- a/lib/hanami/model/association.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-require 'rom-sql'
-require 'hanami/model/associations/belongs_to'
-require 'hanami/model/associations/has_many'
-require 'hanami/model/associations/has_one'
-require 'hanami/model/associations/many_to_many'
-
-module Hanami
- module Model
- # Association factory
- #
- # @since 0.7.0
- # @api private
- class Association
- # Instantiate an association
- #
- # @since 0.7.0
- # @api private
- def self.build(repository, target, subject)
- lookup(repository.root.associations[target])
- .new(repository, repository.root.name.to_sym, target, subject)
- end
-
- # Translate ROM SQL associations into Hanami::Model associations
- #
- # @since 0.7.0
- # @api private
- # rubocop:disable Metrics/MethodLength
- def self.lookup(association)
- case association
- when ROM::SQL::Association::ManyToMany
- Associations::ManyToMany
- when ROM::SQL::Association::OneToOne
- Associations::HasOne
- when ROM::SQL::Association::OneToMany
- Associations::HasMany
- when ROM::SQL::Association::ManyToOne
- Associations::BelongsTo
- else
- raise "Unsupported association: #{association}"
- end
- end
- # rubocop:enable Metrics/MethodLength
- end
- end
-end
diff --git a/lib/hanami/model/associations/belongs_to.rb b/lib/hanami/model/associations/belongs_to.rb
deleted file mode 100644
index bc2e7f95..00000000
--- a/lib/hanami/model/associations/belongs_to.rb
+++ /dev/null
@@ -1,107 +0,0 @@
-require 'hanami/model/types'
-
-module Hanami
- module Model
- module Associations
- # Many-To-One association
- #
- # @since 1.1.0
- # @api private
- class BelongsTo
- # @since 1.1.0
- # @api private
- def self.schema_type(entity)
- Sql::Types::Schema::AssociationType.new(entity)
- end
-
- # @since 1.1.0
- # @api private
- attr_reader :repository
-
- # @since 1.1.0
- # @api private
- attr_reader :source
-
- # @since 1.1.0
- # @api private
- attr_reader :target
-
- # @since 1.1.0
- # @api private
- attr_reader :subject
-
- # @since 1.1.0
- # @api private
- attr_reader :scope
-
- # @since 1.1.0
- # @api private
- def initialize(repository, source, target, subject, scope = nil)
- @repository = repository
- @source = source
- @target = target
- @subject = subject.to_hash unless subject.nil?
- @scope = scope || _build_scope
- freeze
- end
-
- # @since 1.1.0
- # @api private
- def one
- scope.one
- end
-
- private
-
- # @since 1.1.0
- # @api private
- def container
- repository.container
- end
-
- # @since 1.1.0
- # @api private
- def primary_key
- association_keys.first
- end
-
- # @since 1.1.0
- # @api private
- def relation(name)
- repository.relations[Hanami::Utils::String.pluralize(name)]
- end
-
- # @since 1.1.0
- # @api private
- def foreign_key
- association_keys.last
- end
-
- # Returns primary key and foreign key
- #
- # @since 1.1.0
- # @api private
- def association_keys
- association
- .__send__(:join_key_map, container.relations)
- end
-
- # Return the ROM::Associations for the source relation
- #
- # @since 1.1.9
- # @api private
- def association
- relation(source).associations[target]
- end
-
- # @since 1.1.0
- # @api private
- def _build_scope
- result = relation(association.target.to_sym)
- result = result.where(foreign_key => subject.fetch(primary_key)) unless subject.nil?
- result.as(Model::MappedRelation.mapper_name)
- end
- end
- end
- end
-end
diff --git a/lib/hanami/model/associations/dsl.rb b/lib/hanami/model/associations/dsl.rb
deleted file mode 100644
index 78120c79..00000000
--- a/lib/hanami/model/associations/dsl.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-module Hanami
- module Model
- module Associations
- # Auto-infer relations linked to repository's associations
- #
- # @since 0.7.0
- # @api private
- #
- # rubocop:disable Naming/PredicateName
- class Dsl
- # @since 0.7.0
- # @api private
- def initialize(repository, &blk)
- @repository = repository
- instance_eval(&blk)
- end
-
- # @since 0.7.0
- # @api private
- def has_many(relation, **args)
- @repository.__send__(:relations, relation)
- @repository.__send__(:relations, args[:through]) if args[:through]
- end
-
- # @since 1.1.0
- # @api private
- def has_one(relation, *)
- @repository.__send__(:relations, Hanami::Utils::String.pluralize(relation).to_sym)
- end
-
- # @since 1.1.0
- # @api private
- def belongs_to(relation, *)
- @repository.__send__(:relations, Hanami::Utils::String.pluralize(relation).to_sym)
- end
- end
- # rubocop:enable Naming/PredicateName
- end
- end
-end
diff --git a/lib/hanami/model/associations/has_many.rb b/lib/hanami/model/associations/has_many.rb
deleted file mode 100644
index f8724237..00000000
--- a/lib/hanami/model/associations/has_many.rb
+++ /dev/null
@@ -1,212 +0,0 @@
-require 'hanami/model/types'
-
-module Hanami
- module Model
- module Associations
- # One-To-Many association
- #
- # @since 0.7.0
- # @api private
- class HasMany # rubocop:disable Metrics/ClassLength
- # @since 0.7.0
- # @api private
- def self.schema_type(entity)
- type = Sql::Types::Schema::AssociationType.new(entity)
- Types::Strict::Array.member(type)
- end
-
- # @since 0.7.0
- # @api private
- attr_reader :repository
-
- # @since 0.7.0
- # @api private
- attr_reader :source
-
- # @since 0.7.0
- # @api private
- attr_reader :target
-
- # @since 0.7.0
- # @api private
- attr_reader :subject
-
- # @since 0.7.0
- # @api private
- attr_reader :scope
-
- # @since 0.7.0
- # @api private
- def initialize(repository, source, target, subject, scope = nil)
- @repository = repository
- @source = source
- @target = target
- @subject = subject.to_hash unless subject.nil?
- @scope = scope || _build_scope
- freeze
- end
-
- # @since 0.7.0
- # @api private
- def create(data)
- entity.new(command(:create, aggregate(target), mapper: nil, use: [:timestamps])
- .call(serialize(data)))
- rescue => exception
- raise Hanami::Model::Error.for(exception)
- end
-
- # @since 0.7.0
- # @api private
- def add(data)
- command(:create, relation(target), use: [:timestamps])
- .call(associate(serialize(data)))
- rescue => exception
- raise Hanami::Model::Error.for(exception)
- end
-
- # @since 0.7.0
- # @api private
- def remove(id)
- command(:update, relation(target), use: [:timestamps])
- .by_pk(id)
- .call(unassociate)
- end
-
- # @since 0.7.0
- # @api private
- def delete
- scope.delete
- end
-
- # @since 0.7.0
- # @api private
- def each(&blk)
- scope.each(&blk)
- end
-
- # @since 0.7.0
- # @api private
- def map(&blk)
- to_a.map(&blk)
- end
-
- # @since 0.7.0
- # @api private
- def to_a
- scope.to_a
- end
-
- # @since 0.7.0
- # @api private
- def where(condition)
- __new__(scope.where(condition))
- end
-
- # @since 0.7.0
- # @api private
- def count
- scope.count
- end
-
- private
-
- # @since 0.7.0
- # @api private
- def command(target, relation, options = {})
- repository.command(target, relation, options)
- end
-
- # @since 0.7.0
- # @api private
- def entity
- repository.class.entity
- end
-
- # @since 0.7.0
- # @api private
- def relation(name)
- repository.relations[name]
- end
-
- # @since 0.7.0
- # @api private
- def aggregate(name)
- repository.aggregate(name)
- end
-
- # @since 0.7.0
- # @api private
- def association(name)
- relation(target).associations[name]
- end
-
- # @since 0.7.0
- # @api private
- def associate(data)
- relation(source)
- .associations[target]
- .associate(container.relations, data, subject)
- end
-
- # @since 0.7.0
- # @api private
- def unassociate
- { foreign_key => nil }
- end
-
- # @since 0.7.0
- # @api private
- def container
- repository.container
- end
-
- # @since 0.7.0
- # @api private
- def primary_key
- association_keys.first
- end
-
- # @since 0.7.0
- # @api private
- def foreign_key
- association_keys.last
- end
-
- # Returns primary key and foreign key
- #
- # @since 0.7.0
- # @api private
- def association_keys
- target_association
- .__send__(:join_key_map, container.relations)
- end
-
- # Returns the targeted association for a given source
- #
- # @since 0.7.0
- # @api private
- def target_association
- relation(source).associations[target]
- end
-
- # @since 0.7.0
- # @api private
- def _build_scope
- result = relation(target_association.target.to_sym)
- result = result.where(foreign_key => subject.fetch(primary_key)) unless subject.nil?
- result.as(Model::MappedRelation.mapper_name)
- end
-
- # @since 0.7.0
- # @api private
- def __new__(new_scope)
- self.class.new(repository, source, target, subject, new_scope)
- end
-
- def serialize(data)
- Utils::Hash.deep_serialize(data)
- end
- end
- end
- end
-end
diff --git a/lib/hanami/model/associations/has_one.rb b/lib/hanami/model/associations/has_one.rb
deleted file mode 100644
index d4640386..00000000
--- a/lib/hanami/model/associations/has_one.rb
+++ /dev/null
@@ -1,165 +0,0 @@
-require "hanami/utils/hash"
-
-module Hanami
- module Model
- module Associations
- # Many-To-One association
- #
- # @since 1.1.0
- # @api private
- class HasOne
- # @since 1.1.0
- # @api private
- def self.schema_type(entity)
- Sql::Types::Schema::AssociationType.new(entity)
- end
- #
- # @since 1.1.0
- # @api private
- attr_reader :repository
-
- # @since 1.1.0
- # @api private
- attr_reader :source
-
- # @since 1.1.0
- # @api private
- attr_reader :target
-
- # @since 1.1.0
- # @api private
- attr_reader :subject
-
- # @since 1.1.0
- # @api private
- attr_reader :scope
-
- # @since 1.1.0
- # @api private
- def initialize(repository, source, target, subject, scope = nil)
- @repository = repository
- @source = source
- @target = target
- @subject = subject.to_hash unless subject.nil?
- @scope = scope || _build_scope
- freeze
- end
-
- def one
- scope.one
- end
-
- def create(data)
- entity.new(
- command(:create, aggregate(target), mapper: nil).call(serialize(data))
- )
- rescue => exception
- raise Hanami::Model::Error.for(exception)
- end
-
- def add(data)
- command(:create, relation(target), mapper: nil).call(associate(serialize(data)))
- rescue => exception
- raise Hanami::Model::Error.for(exception)
- end
-
- def update(data)
- command(:update, relation(target), mapper: nil)
- .by_pk(
- one.public_send(relation(target).primary_key)
- ).call(serialize(data))
- rescue => exception
- raise Hanami::Model::Error.for(exception)
- end
-
- def delete
- scope.delete
- end
- alias remove delete
-
- def replace(data)
- repository.transaction do
- delete
- add(serialize(data))
- end
- end
-
- private
-
- # @since 1.1.0
- # @api private
- def entity
- repository.class.entity
- end
-
- # @since 1.1.0
- # @api private
- def aggregate(name)
- repository.aggregate(name)
- end
-
- # @since 1.1.0
- # @api private
- def command(target, relation, options = {})
- repository.command(target, relation, options)
- end
-
- # @since 1.1.0
- # @api private
- def relation(name)
- repository.relations[Hanami::Utils::String.pluralize(name)]
- end
-
- # @since 1.1.0
- # @api private
- def container
- repository.container
- end
-
- # @since 1.1.0
- # @api private
- def primary_key
- association_keys.first
- end
-
- # @since 1.1.0
- # @api private
- def foreign_key
- association_keys.last
- end
-
- # @since 1.1.0
- # @api private
- def associate(data)
- relation(source)
- .associations[target]
- .associate(container.relations, data, subject)
- end
-
- # Returns primary key and foreign key
- #
- # @since 1.1.0
- # @api private
- def association_keys
- relation(source)
- .associations[target]
- .__send__(:join_key_map, container.relations)
- end
-
- # @since 1.1.0
- # @api private
- def _build_scope
- result = relation(target)
- result = result.where(foreign_key => subject.fetch(primary_key)) unless subject.nil?
- result.as(Model::MappedRelation.mapper_name)
- end
-
- # @since 1.1.0
- # @api private
- def serialize(data)
- Utils::Hash.deep_serialize(data)
- end
- end
- end
- end
-end
diff --git a/lib/hanami/model/associations/many_to_many.rb b/lib/hanami/model/associations/many_to_many.rb
deleted file mode 100644
index 52c0fc98..00000000
--- a/lib/hanami/model/associations/many_to_many.rb
+++ /dev/null
@@ -1,203 +0,0 @@
-require "hanami/utils/hash"
-
-module Hanami
- module Model
- module Associations
- # Many-To-Many association
- #
- # @since 0.7.0
- # @api private
- class ManyToMany # rubocop:disable Metrics/ClassLength
- # @since 0.7.0
- # @api private
- def self.schema_type(entity)
- type = Sql::Types::Schema::AssociationType.new(entity)
- Types::Strict::Array.member(type)
- end
-
- # @since 1.1.0
- # @api private
- attr_reader :repository
-
- # @since 1.1.0
- # @api private
- attr_reader :source
-
- # @since 1.1.0
- # @api private
- attr_reader :target
-
- # @since 1.1.0
- # @api private
- attr_reader :subject
-
- # @since 1.1.0
- # @api private
- attr_reader :scope
-
- # @since 1.1.0
- # @api private
- attr_reader :through
-
- def initialize(repository, source, target, subject, scope = nil)
- @repository = repository
- @source = source
- @target = target
- @subject = subject.to_hash unless subject.nil?
- @through = relation(source).associations[target].through.to_sym
- @scope = scope || _build_scope
- freeze
- end
-
- def to_a
- scope.to_a
- end
-
- def map(&blk)
- to_a.map(&blk)
- end
-
- def each(&blk)
- scope.each(&blk)
- end
-
- def count
- scope.count
- end
-
- def where(condition)
- __new__(scope.where(condition))
- end
-
- # Return the association table object. Would need an aditional query to return the entity
- #
- # @since 1.1.0
- # @api private
- def add(*data)
- command(:create, relation(through), use: [:timestamps])
- .call(associate(serialize(data)))
- rescue => exception
- raise Hanami::Model::Error.for(exception)
- end
-
- # @since 1.1.0
- # @api private
- def delete
- relation(through).where(source_foreign_key => subject.fetch(source_primary_key)).delete
- end
-
- # @since 1.1.0
- # @api private
- # rubocop:disable Metrics/AbcSize
- def remove(target_id)
- association_record = relation(through)
- .where(target_foreign_key => target_id, source_foreign_key => subject.fetch(source_primary_key))
- .one
-
- return if association_record.nil?
-
- ar_id = association_record.public_send relation(through).primary_key
- command(:delete, relation(through)).by_pk(ar_id).call
- end
- # rubocop:enable Metrics/AbcSize
-
- private
-
- # @since 1.1.0
- # @api private
- def container
- repository.container
- end
-
- # @since 1.1.0
- # @api private
- def relation(name)
- repository.relations[name]
- end
-
- # @since 1.1.0
- # @api private
- def command(target, relation, options = {})
- repository.command(target, relation, options)
- end
-
- # @since 1.1.0
- # @api private
- def associate(data)
- relation(target)
- .associations[source]
- .associate(container.relations, data, subject)
- end
-
- # @since 1.1.0
- # @api private
- def source_primary_key
- association_keys[0].first
- end
-
- # @since 1.1.0
- # @api private
- def source_foreign_key
- association_keys[0].last
- end
-
- # @since 1.1.0
- # @api private
- def association_keys
- relation(source)
- .associations[target]
- .__send__(:join_key_map, container.relations)
- end
-
- # @since 1.1.0
- # @api private
- def target_foreign_key
- association_keys[1].first
- end
-
- # @since 1.1.0
- # @api private
- def target_primary_key
- association_keys[1].last
- end
-
- # Return the ROM::Associations for the source relation
- #
- # @since 1.1.0
- # @api private
- def association
- relation(source).associations[target]
- end
-
- # @since 1.1.0
- #
- # @api private
- # rubocop:disable Metrics/AbcSize
- def _build_scope
- result = relation(association.target.to_sym).qualified
- unless subject.nil?
- result = result
- .join(through, target_foreign_key => target_primary_key)
- .where(source_foreign_key => subject.fetch(source_primary_key))
- end
- result.as(Model::MappedRelation.mapper_name)
- end
- # rubocop:enable Metrics/AbcSize
-
- # @since 1.1.0
- # @api private
- def __new__(new_scope)
- self.class.new(repository, source, target, subject, new_scope)
- end
-
- # @since 1.1.0
- # @api private
- def serialize(data)
- data.map do |d|
- Utils::Hash.deep_serialize(d)
- end
- end
- end
- end
- end
-end
diff --git a/lib/hanami/model/configuration.rb b/lib/hanami/model/configuration.rb
index 2cadbcce..ac147d5b 100644
--- a/lib/hanami/model/configuration.rb
+++ b/lib/hanami/model/configuration.rb
@@ -1,4 +1,7 @@
-require 'rom/configuration'
+# frozen_string_literal: true
+
+require "rom/configuration"
+require "hanami/utils/blank"
module Hanami
module Model
@@ -25,25 +28,42 @@ class Configuration
# @api private
attr_reader :migrations_logger
+ # @since x.x.x
+ # @api private
+ attr_reader :inflector
+
# @since 0.2.0
# @api private
- def initialize(configurator)
+ def initialize(configurator) # rubocop:disable Metrics/MethodLength
@backend = configurator.backend
@url = configurator.url
- @migrations = configurator._migrations
- @schema = configurator._schema
- @gateway_config = configurator._gateway
- @logger = configurator._logger
+ @container = nil
+ @migrations = configurator._migrations
+ @schema = configurator._schema
+ @gateway_config = configurator._gateway
+ @logger = configurator._logger
@migrations_logger = configurator.migrations_logger
+ @inflector = configurator.inflector
@mappings = {}
@entities = {}
+ @directory = configurator.directory
+ end
+
+ def container
+ @container or raise "not loaded"
end
# NOTE: This must be changed when we want to support several adapters at the time
#
+ # @raise [Hanami::Model::UnknownDatabaseAdapterError] if @url is blank
+ #
# @since 0.7.0
# @api private
- attr_reader :url
+ def url
+ raise Hanami::Model::UnknownDatabaseAdapterError.new(@url) if Utils::Blank.blank?(@url)
+
+ @url
+ end
# NOTE: This must be changed when we want to support several adapters at the time
#
@@ -102,19 +122,6 @@ def register_entity(plural, singular, klass)
@entities[singular] = klass
end
- # @since 0.7.0
- # @api private
- def define_entities_mappings(container, repositories)
- return unless defined?(Sql::Entity::Schema)
-
- repositories.each do |r|
- relation = r.relation
- entity = r.entity
-
- entity.schema = Sql::Entity::Schema.new(entities, container.relations[relation], mappings.fetch(relation))
- end
- end
-
# @since 1.0.0
# @api private
def configure_gateway
@@ -135,11 +142,7 @@ def logger=(value)
# @since 1.0.0
# @api private
def rom
- @rom ||= ROM::Configuration.new(@backend, @url, infer_relations: false)
- rescue => exception
- raise UnknownDatabaseAdapterError.new(@url) if exception.message =~ /adapters/
-
- raise exception
+ @rom ||= ROM::Configuration.new(@backend, url)
end
# @raise [Hanami::Model::UnknownDatabaseAdapterError] if `url` is blank,
@@ -147,20 +150,26 @@ def rom
#
# @since 1.0.0
# @api private
- def load!(repositories, &blk) # rubocop:disable Metrics/AbcSize
- rom.setup.auto_registration(config.directory.to_s) unless config.directory.nil?
- rom.instance_eval(&blk) if block_given?
+ #
+ # rubocop:disable Metrics/AbcSize
+ def load!(&blk)
+ rom.auto_registration(@directory) unless @directory.nil?
+ rom.plugin(:sql, relations: :auto_restrictions)
+
+ rom.instance_eval(&blk) if block_given?
configure_gateway
- repositories.each(&:load!)
self.logger = logger
- container = ROM.container(rom)
- define_entities_mappings(container, repositories)
- container
+ # FIXME: without "touching" the db, inferrer crashes on sqlite, wtf?
+ gateway.connection.tables
+
+ @container = ROM.container(rom)
rescue => exception
raise Hanami::Model::Error.for(exception)
end
+ # rubocop:enable Metrics/AbcSize
+
# @since 1.0.0
# @api private
def method_missing(method_name, *args, &blk)
diff --git a/lib/hanami/model/configurator.rb b/lib/hanami/model/configurator.rb
index 1c097cc7..265d2335 100644
--- a/lib/hanami/model/configurator.rb
+++ b/lib/hanami/model/configurator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Hanami
module Model
# Configuration DSL
@@ -42,10 +44,21 @@ def self.build(&block)
# @since 1.0.0
# @api private
def migrations_logger(stream = $stdout)
- require 'hanami/model/migrator/logger'
+ require "hanami/model/migrator/logger"
@migrations_logger ||= Hanami::Model::Migrator::Logger.new(stream)
end
+ # @since x.x.x
+ # @api private
+ def inflector(inflector = nil, &blk)
+ @inflector ||= if inflector
+ inflector
+ else
+ require "dry/inflector"
+ Dry::Inflector.new(&blk)
+ end
+ end
+
private
# @since 0.7.0
@@ -76,10 +89,10 @@ def schema(path)
# @since 1.0.0
# @api private
def logger(stream, options = {})
- require 'hanami/logger'
+ require "hanami/logger"
opts = options.merge(stream: stream)
- @_logger = Hanami::Logger.new('hanami.model', opts)
+ @_logger = Hanami::Logger.new("hanami.model", **opts)
end
# @since 1.0.0
diff --git a/lib/hanami/model/entity_name.rb b/lib/hanami/model/entity_name.rb
deleted file mode 100644
index 88bca9be..00000000
--- a/lib/hanami/model/entity_name.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-module Hanami
- module Model
- # Conventional name for entities.
- #
- # Given a repository named SourceFileRepository, the associated
- # entity will be SourceFile.
- #
- # @since 0.7.0
- # @api private
- class EntityName
- # @since 0.7.0
- # @api private
- SUFFIX = /Repository\z/.freeze
-
- # @param name [Class,String] the class or its name
- # @return [String] the entity name
- #
- # @since 0.7.0
- # @api private
- def initialize(name)
- @name = name.sub(SUFFIX, '')
- end
-
- # @since 0.7.0
- # @api private
- def underscore
- Utils::String.underscore(@name).to_sym
- end
-
- # @since 0.7.0
- # @api private
- def to_s
- @name
- end
- end
- end
-end
diff --git a/lib/hanami/model/error.rb b/lib/hanami/model/error.rb
index 21fe379f..c0e7728a 100644
--- a/lib/hanami/model/error.rb
+++ b/lib/hanami/model/error.rb
@@ -1,4 +1,6 @@
-require 'concurrent'
+# frozen_string_literal: true
+
+require "concurrent"
module Hanami
module Model
@@ -41,7 +43,7 @@ class DatabaseError < Error
class InvalidCommandError < Error
# @since 0.5.0
# @api private
- def initialize(message = 'Invalid command')
+ def initialize(message = "Invalid command")
super
end
end
@@ -52,7 +54,7 @@ def initialize(message = 'Invalid command')
class ConstraintViolationError < Error
# @since 0.7.0
# @api private
- def initialize(message = 'Constraint has been violated')
+ def initialize(message = "Constraint has been violated")
super
end
end
@@ -63,7 +65,7 @@ def initialize(message = 'Constraint has been violated')
class UniqueConstraintViolationError < ConstraintViolationError
# @since 0.6.1
# @api private
- def initialize(message = 'Unique constraint has been violated')
+ def initialize(message = "Unique constraint has been violated")
super
end
end
@@ -74,7 +76,7 @@ def initialize(message = 'Unique constraint has been violated')
class ForeignKeyConstraintViolationError < ConstraintViolationError
# @since 0.6.1
# @api private
- def initialize(message = 'Foreign key constraint has been violated')
+ def initialize(message = "Foreign key constraint has been violated")
super
end
end
@@ -85,7 +87,7 @@ def initialize(message = 'Foreign key constraint has been violated')
class NotNullConstraintViolationError < ConstraintViolationError
# @since 0.6.1
# @api private
- def initialize(message = 'NOT NULL constraint has been violated')
+ def initialize(message = "NOT NULL constraint has been violated")
super
end
end
@@ -96,7 +98,7 @@ def initialize(message = 'NOT NULL constraint has been violated')
class CheckConstraintViolationError < ConstraintViolationError
# @since 0.6.1
# @api private
- def initialize(message = 'Check constraint has been violated')
+ def initialize(message = "Check constraint has been violated")
super
end
end
@@ -127,5 +129,11 @@ def initialize(url)
super("Unknown database adapter for URL: #{url.inspect}. Please check your database configuration (hint: ENV['DATABASE_URL']).")
end
end
+
+ class MissingAttributeError < Error
+ def initialize(error)
+ super(error.message)
+ end
+ end
end
end
diff --git a/lib/hanami/model/mapped_relation.rb b/lib/hanami/model/mapped_relation.rb
index 70e260b4..962b0a03 100644
--- a/lib/hanami/model/mapped_relation.rb
+++ b/lib/hanami/model/mapped_relation.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Hanami
module Model
# Mapped proxy for ROM relations.
diff --git a/lib/hanami/model/mapping.rb b/lib/hanami/model/mapping.rb
index aa80fe9d..c3ff60f1 100644
--- a/lib/hanami/model/mapping.rb
+++ b/lib/hanami/model/mapping.rb
@@ -1,4 +1,6 @@
-require 'transproc/all'
+# frozen_string_literal: true
+
+require "transproc/all"
module Hanami
module Model
diff --git a/lib/hanami/model/migration.rb b/lib/hanami/model/migration.rb
index f4926784..ca4a0bc8 100644
--- a/lib/hanami/model/migration.rb
+++ b/lib/hanami/model/migration.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Hanami
module Model
# Database migration
diff --git a/lib/hanami/model/migrator.rb b/lib/hanami/model/migrator.rb
index daba55ca..f066ab08 100644
--- a/lib/hanami/model/migrator.rb
+++ b/lib/hanami/model/migrator.rb
@@ -1,5 +1,7 @@
-require 'sequel'
-require 'sequel/extensions/migration'
+# frozen_string_literal: true
+
+require "sequel"
+require "sequel/extensions/migration"
module Hanami
module Model
@@ -13,8 +15,8 @@ class MigrationError < Hanami::Model::Error
#
# @since 0.4.0
class Migrator
- require 'hanami/model/migrator/connection'
- require 'hanami/model/migrator/adapter'
+ require "hanami/model/migrator/connection"
+ require "hanami/model/migrator/adapter"
# Create database defined by current configuration.
#
@@ -327,7 +329,7 @@ def apply
# @see Hanami::Model::Migrator.prepare
def prepare
drop
- rescue # rubocop:disable Lint/HandleExceptions
+ rescue # rubocop:disable Lint/SuppressedException
ensure
create
adapter.load
diff --git a/lib/hanami/model/migrator/adapter.rb b/lib/hanami/model/migrator/adapter.rb
index 589305b5..f4f62f44 100644
--- a/lib/hanami/model/migrator/adapter.rb
+++ b/lib/hanami/model/migrator/adapter.rb
@@ -1,6 +1,8 @@
-require 'uri'
-require 'shellwords'
-require 'open3'
+# frozen_string_literal: true
+
+require "uri"
+require "shellwords"
+require "open3"
module Hanami
module Model
@@ -31,13 +33,13 @@ def self.for(configuration) # rubocop:disable Metrics/MethodLength
case connection.database_type
when :sqlite
- require 'hanami/model/migrator/sqlite_adapter'
+ require "hanami/model/migrator/sqlite_adapter"
SQLiteAdapter
when :postgres
- require 'hanami/model/migrator/postgres_adapter'
+ require "hanami/model/migrator/postgres_adapter"
PostgresAdapter
when :mysql
- require 'hanami/model/migrator/mysql_adapter'
+ require "hanami/model/migrator/mysql_adapter"
MySQLAdapter
else
self
diff --git a/lib/hanami/model/migrator/connection.rb b/lib/hanami/model/migrator/connection.rb
index 4e156ffd..ba7ed445 100644
--- a/lib/hanami/model/migrator/connection.rb
+++ b/lib/hanami/model/migrator/connection.rb
@@ -1,4 +1,6 @@
-require 'cgi'
+# frozen_string_literal: true
+
+require "cgi"
module Hanami
module Model
@@ -36,7 +38,7 @@ def raw
# @since 0.5.0
# @api private
def host
- @host ||= parsed_uri.host || parsed_opt('host')
+ @host ||= parsed_uri.host || parsed_opt("host")
end
# Returns DB connection port
@@ -46,7 +48,7 @@ def host
# @since 0.5.0
# @api private
def port
- @port ||= parsed_uri.port || parsed_opt('port').to_i.nonzero?
+ @port ||= parsed_uri.port || parsed_opt("port").to_i.nonzero?
end
# Returns DB name from conenction
@@ -85,7 +87,7 @@ def database_type
# @since 0.5.0
# @api private
def user
- @user ||= parsed_opt('user') || parsed_uri.user
+ @user ||= parsed_opt("user") || parsed_uri.user
end
# Returns user from DB connection
@@ -95,7 +97,7 @@ def user
# @since 0.5.0
# @api private
def password
- @password ||= parsed_opt('password') || parsed_uri.password
+ @password ||= parsed_opt("password") || parsed_uri.password
end
# Returns DB connection URI directly from adapter
@@ -111,7 +113,7 @@ def uri
# @since 0.5.0
# @api private
def global_uri
- uri.sub(parsed_uri.select(:path).first, '')
+ uri.sub(parsed_uri.select(:path).first, "")
end
# Returns a boolean telling if a DB connection is from JDBC or not
@@ -119,7 +121,7 @@ def global_uri
# @since 0.5.0
# @api private
def jdbc?
- !uri.scan('jdbc:').empty?
+ !uri.scan("jdbc:").empty?
end
# Returns database connection URI instance without JDBC namespace
@@ -127,7 +129,7 @@ def jdbc?
# @since 0.5.0
# @api private
def parsed_uri
- @parsed_uri ||= URI.parse(uri.sub('jdbc:', ''))
+ @parsed_uri ||= URI.parse(uri.sub("jdbc:", ""))
end
# @api private
diff --git a/lib/hanami/model/migrator/logger.rb b/lib/hanami/model/migrator/logger.rb
index 265733c7..aa45f325 100644
--- a/lib/hanami/model/migrator/logger.rb
+++ b/lib/hanami/model/migrator/logger.rb
@@ -1,4 +1,6 @@
-require 'hanami/logger'
+# frozen_string_literal: true
+
+require "hanami/logger"
module Hanami
module Model
diff --git a/lib/hanami/model/migrator/mysql_adapter.rb b/lib/hanami/model/migrator/mysql_adapter.rb
index 91a622f2..df8c6be4 100644
--- a/lib/hanami/model/migrator/mysql_adapter.rb
+++ b/lib/hanami/model/migrator/mysql_adapter.rb
@@ -1,3 +1,7 @@
+# frozen_string_literal: true
+
+require "hanami/utils/blank"
+
module Hanami
module Model
class Migrator
@@ -8,20 +12,22 @@ class Migrator
class MySQLAdapter < Adapter
# @since 0.7.0
# @api private
- PASSWORD = 'MYSQL_PWD'.freeze
+ PASSWORD = "MYSQL_PWD"
+
+ CLI_OPTIONS = %w[host port user].freeze
# @since 1.0.0
# @api private
- DB_CREATION_ERROR = 'Database creation failed. If the database exists, ' \
- 'then its console may be open. See this issue for more details: ' \
- 'https://github.com/hanami/model/issues/250'.freeze
+ DB_CREATION_ERROR = "Database creation failed. If the database exists, " \
+ "then its console may be open. See this issue for more details: " \
+ "https://github.com/hanami/model/issues/250"
# @since 0.4.0
# @api private
def create
new_connection(global: true).run %(CREATE DATABASE `#{database}`;)
rescue Sequel::DatabaseError => exception
- message = if exception.message.match(/database exists/)
+ message = if exception.message.match?(/database exists/)
DB_CREATION_ERROR
else
exception.message
@@ -35,7 +41,7 @@ def create
def drop
new_connection(global: true).run %(DROP DATABASE `#{database}`;)
rescue Sequel::DatabaseError => exception
- message = if exception.message.match(/doesn\'t exist/)
+ message = if exception.message.match?(/doesn\'t exist/)
"Cannot find database: #{database}"
else
exception.message
@@ -68,19 +74,30 @@ def password
# @since 0.4.0
# @api private
def dump_structure
- execute "mysqldump --host=#{host} --port=#{port} --user=#{username} --no-data --skip-comments --ignore-table=#{database}.#{migrations_table} #{database} > #{schema}", env: { PASSWORD => password }
+ execute "mysqldump #{cli_options} --no-data --skip-comments --ignore-table=#{database}.#{migrations_table} #{database} > #{schema}", env: { PASSWORD => password }
end
# @since 0.4.0
# @api private
def load_structure
- execute("mysql --host=#{host} --port=#{port} --user=#{username} #{database} < #{escape(schema)}", env: { PASSWORD => password }) if schema.exist?
+ execute("mysql #{cli_options} #{database} < #{escape(schema)}", env: { PASSWORD => password }) if schema.exist?
end
# @since 0.4.0
# @api private
def dump_migrations_data
- execute "mysqldump --host=#{host} --port=#{port} --user=#{username} --skip-comments #{database} #{migrations_table} >> #{schema}", env: { PASSWORD => password }
+ execute "mysqldump #{cli_options} --skip-comments #{database} #{migrations_table} >> #{schema}", env: { PASSWORD => password }
+ end
+
+ alias user username
+
+ def cli_options
+ CLI_OPTIONS.map do |option|
+ value = send(option)
+ next if Utils::Blank.blank?(value)
+
+ "--#{option}=#{value}"
+ end.compact.join(" ")
end
end
end
diff --git a/lib/hanami/model/migrator/postgres_adapter.rb b/lib/hanami/model/migrator/postgres_adapter.rb
index 9b534327..be5691dd 100644
--- a/lib/hanami/model/migrator/postgres_adapter.rb
+++ b/lib/hanami/model/migrator/postgres_adapter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "hanami/utils/blank"
module Hanami
@@ -10,32 +12,32 @@ class Migrator
class PostgresAdapter < Adapter
# @since 0.4.0
# @api private
- HOST = 'PGHOST'.freeze
+ HOST = "PGHOST"
# @since 0.4.0
# @api private
- PORT = 'PGPORT'.freeze
+ PORT = "PGPORT"
# @since 0.4.0
# @api private
- USER = 'PGUSER'.freeze
+ USER = "PGUSER"
# @since 0.4.0
# @api private
- PASSWORD = 'PGPASSWORD'.freeze
+ PASSWORD = "PGPASSWORD"
# @since 1.0.0
# @api private
- DB_CREATION_ERROR = 'createdb: database creation failed. If the database exists, ' \
- 'then its console may be open. See this issue for more details: ' \
- 'https://github.com/hanami/model/issues/250'.freeze
+ DB_CREATION_ERROR = "createdb: database creation failed. If the database exists, " \
+ "then its console may be open. See this issue for more details: " \
+ "https://github.com/hanami/model/issues/250"
# @since 0.4.0
# @api private
def create
set_environment_variables
- call_db_command('createdb')
+ call_db_command("createdb")
end
# @since 0.4.0
@@ -43,7 +45,7 @@ def create
def drop
set_environment_variables
- call_db_command('dropdb')
+ call_db_command("dropdb")
end
# @since 0.4.0
@@ -94,7 +96,7 @@ def dump_migrations_data
# @since 0.5.1
# @api private
def call_db_command(command)
- require 'open3'
+ require "open3"
begin
Open3.popen3(*command_with_credentials(command)) do |_stdin, _stdout, stderr, wait_thr|
diff --git a/lib/hanami/model/migrator/sqlite_adapter.rb b/lib/hanami/model/migrator/sqlite_adapter.rb
index daa62cd3..bef38c4e 100644
--- a/lib/hanami/model/migrator/sqlite_adapter.rb
+++ b/lib/hanami/model/migrator/sqlite_adapter.rb
@@ -1,6 +1,8 @@
-require 'pathname'
-require 'hanami/utils'
-require 'English'
+# frozen_string_literal: true
+
+require "pathname"
+require "hanami/utils"
+require "English"
module Hanami
module Model
@@ -71,7 +73,7 @@ def load
# @api private
def path
root.join(
- @connection.uri.sub(/\A(jdbc:sqlite:\/\/|sqlite:\/\/)/, '')
+ @connection.uri.sub(/\A(jdbc:sqlite:\/\/|sqlite:\/\/)/, "")
)
end
@@ -105,22 +107,18 @@ def load_structure
# @api private
#
# rubocop:disable Metrics/AbcSize
- # rubocop:disable Metrics/MethodLength
def dump_migrations_data
execute "sqlite3 #{escape(path)} .dump" do |stdout|
- begin
- contents = stdout.read.split($INPUT_RECORD_SEPARATOR)
- contents = contents.grep(/^INSERT INTO "?#{migrations_table}"?/)
-
- ::File.open(schema, ::File::CREAT | ::File::BINARY | ::File::WRONLY | ::File::APPEND) do |file|
- file.write(contents.join($INPUT_RECORD_SEPARATOR))
- end
- rescue => exception
- raise MigrationError.new(exception.message)
+ contents = stdout.read.split($INPUT_RECORD_SEPARATOR)
+ contents = contents.grep(/^INSERT INTO "#{migrations_table}"/)
+
+ ::File.open(schema, ::File::CREAT | ::File::BINARY | ::File::WRONLY | ::File::APPEND) do |file|
+ file.write(contents.join($INPUT_RECORD_SEPARATOR))
end
+ rescue => exception
+ raise MigrationError.new(exception.message)
end
end
- # rubocop:enable Metrics/MethodLength
# rubocop:enable Metrics/AbcSize
end
end
diff --git a/lib/hanami/model/plugins.rb b/lib/hanami/model/plugins.rb
index b36077ce..397f8909 100644
--- a/lib/hanami/model/plugins.rb
+++ b/lib/hanami/model/plugins.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Hanami
module Model
# Plugins to extend read/write operations from/to the database
@@ -13,13 +15,13 @@ class WrappingInput
# @since 0.7.0
# @api private
def initialize(_relation, input)
- @input = input || Hash
+ @input = input || ::Hash
end
end
- require 'hanami/model/plugins/mapping'
- require 'hanami/model/plugins/schema'
- require 'hanami/model/plugins/timestamps'
+ require "hanami/model/plugins/mapping"
+ require "hanami/model/plugins/schema"
+ require "hanami/model/plugins/timestamps"
end
end
end
diff --git a/lib/hanami/model/plugins/mapping.rb b/lib/hanami/model/plugins/mapping.rb
index 4717e830..dedf1725 100644
--- a/lib/hanami/model/plugins/mapping.rb
+++ b/lib/hanami/model/plugins/mapping.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Hanami
module Model
module Plugins
diff --git a/lib/hanami/model/plugins/schema.rb b/lib/hanami/model/plugins/schema.rb
index c4d4c889..bac8c096 100644
--- a/lib/hanami/model/plugins/schema.rb
+++ b/lib/hanami/model/plugins/schema.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Hanami
module Model
module Plugins
diff --git a/lib/hanami/model/plugins/timestamps.rb b/lib/hanami/model/plugins/timestamps.rb
index 70eee085..482e1830 100644
--- a/lib/hanami/model/plugins/timestamps.rb
+++ b/lib/hanami/model/plugins/timestamps.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Hanami
module Model
module Plugins
@@ -93,7 +95,7 @@ module ClassMethods
#
# @since 0.7.0
# @api private
- def build(relation, options = {})
+ def build(relation, **options)
plugin = if self < ROM::Commands::Create
InputWithCreateTimestamp
else
diff --git a/lib/hanami/model/relation_name.rb b/lib/hanami/model/relation_name.rb
deleted file mode 100644
index 43ef3853..00000000
--- a/lib/hanami/model/relation_name.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-require_relative 'entity_name'
-require 'hanami/utils/string'
-
-module Hanami
- module Model
- # Conventional name for relations.
- #
- # Given a repository named SourceFileRepository, the associated
- # relation will be :source_files.
- #
- # @since 0.7.0
- # @api private
- class RelationName < EntityName
- # @param name [Class,String] the class or its name
- # @return [String] the relation name
- #
- # @since 0.7.0
- # @api private
- def self.new(name)
- Utils::String.transform(super, :underscore, :pluralize)
- end
- end
- end
-end
diff --git a/lib/hanami/model/sql.rb b/lib/hanami/model/sql.rb
index d6c69689..037c6e70 100644
--- a/lib/hanami/model/sql.rb
+++ b/lib/hanami/model/sql.rb
@@ -1,12 +1,13 @@
-require 'rom-sql'
-require 'hanami/utils'
+# frozen_string_literal: true
+
+require "rom-sql"
+require "hanami/utils"
module Hanami
# Hanami::Model migrations
module Model
- require 'hanami/model/error'
- require 'hanami/model/association'
- require 'hanami/model/migration'
+ require "hanami/model/error"
+ require "hanami/model/migration"
# Define a migration
#
@@ -53,8 +54,7 @@ def self.migration(&blk)
#
# @since 0.7.0
module Sql
- require 'hanami/model/sql/types'
- require 'hanami/model/sql/entity/schema'
+ require "hanami/model/sql/types"
# Returns a SQL fragment that references a database function by the given name
# This is useful for database migrations
@@ -147,6 +147,7 @@ def self.desc(column)
Error.register(ROM::SQL::ForeignKeyConstraintError, ForeignKeyConstraintViolationError)
Error.register(ROM::SQL::UnknownDBTypeError, UnknownDatabaseTypeError)
Error.register(ROM::SQL::MissingPrimaryKeyError, MissingPrimaryKeyError)
+ Error.register(ROM::Struct::MissingAttribute, MissingAttributeError)
Error.register(Java::JavaSql::SQLException, DatabaseError) if Utils.jruby?
end
diff --git a/lib/hanami/model/sql/console.rb b/lib/hanami/model/sql/console.rb
index f9b9cd1a..cb4c9cb1 100644
--- a/lib/hanami/model/sql/console.rb
+++ b/lib/hanami/model/sql/console.rb
@@ -1,4 +1,6 @@
-require 'uri'
+# frozen_string_literal: true
+
+require "uri"
module Hanami
module Model
@@ -26,14 +28,14 @@ def initialize(uri)
# @api private
def console # rubocop:disable Metrics/MethodLength
case @uri.scheme
- when 'sqlite'
- require 'hanami/model/sql/consoles/sqlite'
+ when "sqlite"
+ require "hanami/model/sql/consoles/sqlite"
Sql::Consoles::Sqlite.new(@uri)
- when 'postgres', 'postgresql'
- require 'hanami/model/sql/consoles/postgresql'
+ when "postgres", "postgresql"
+ require "hanami/model/sql/consoles/postgresql"
Sql::Consoles::Postgresql.new(@uri)
- when 'mysql', 'mysql2'
- require 'hanami/model/sql/consoles/mysql'
+ when "mysql", "mysql2"
+ require "hanami/model/sql/consoles/mysql"
Sql::Consoles::Mysql.new(@uri)
end
end
diff --git a/lib/hanami/model/sql/consoles/abstract.rb b/lib/hanami/model/sql/consoles/abstract.rb
index 8acfb853..f2569d84 100644
--- a/lib/hanami/model/sql/consoles/abstract.rb
+++ b/lib/hanami/model/sql/consoles/abstract.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Hanami
module Model
module Sql
@@ -18,7 +20,7 @@ def initialize(uri)
# @since 0.7.0
# @api private
def database_name
- @uri.path.sub(/^\//, '')
+ @uri.path.sub(/^\//, "")
end
# @since 0.7.0
diff --git a/lib/hanami/model/sql/consoles/mysql.rb b/lib/hanami/model/sql/consoles/mysql.rb
index 8f5c193d..30e5ca3c 100644
--- a/lib/hanami/model/sql/consoles/mysql.rb
+++ b/lib/hanami/model/sql/consoles/mysql.rb
@@ -1,4 +1,6 @@
-require_relative 'abstract'
+# frozen_string_literal: true
+
+require_relative "abstract"
module Hanami
module Model
@@ -11,7 +13,7 @@ module Consoles
class Mysql < Abstract
# @since 0.7.0
# @api private
- COMMAND = 'mysql'.freeze
+ COMMAND = "mysql"
# @since 0.7.0
# @api private
diff --git a/lib/hanami/model/sql/consoles/postgresql.rb b/lib/hanami/model/sql/consoles/postgresql.rb
index 2dac1568..82fc5e39 100644
--- a/lib/hanami/model/sql/consoles/postgresql.rb
+++ b/lib/hanami/model/sql/consoles/postgresql.rb
@@ -1,5 +1,7 @@
-require_relative 'abstract'
-require 'cgi'
+# frozen_string_literal: true
+
+require_relative "abstract"
+require "cgi"
module Hanami
module Model
@@ -12,11 +14,11 @@ module Consoles
class Postgresql < Abstract
# @since 0.7.0
# @api private
- COMMAND = 'psql'.freeze
+ COMMAND = "psql"
# @since 0.7.0
# @api private
- PASSWORD = 'PGPASSWORD'.freeze
+ PASSWORD = "PGPASSWORD"
# @since 0.7.0
# @api private
@@ -48,22 +50,22 @@ def database
# @since 0.7.0
# @api private
def port
- port = query['port'] || @uri.port
+ port = query["port"] || @uri.port
" -p #{port}" if port
end
# @since 0.7.0
# @api private
def username
- username = query['user'] || @uri.user
+ username = query["user"] || @uri.user
" -U #{username}" if username
end
# @since 0.7.0
# @api private
def configure_password
- password = query['password'] || @uri.password
- ENV[PASSWORD] = CGI.unescape(query['password'] || @uri.password) if password
+ password = query["password"] || @uri.password
+ ENV[PASSWORD] = CGI.unescape(query["password"] || @uri.password) if password
end
# @since 1.1.0
@@ -72,7 +74,7 @@ def query
return {} if @uri.query.nil? || @uri.query.empty?
parsed_query = @uri.query.split("&").map { |a| a.split("=") }
- @query ||= Hash[parsed_query]
+ @query ||= ::Hash[parsed_query]
end
end
end
diff --git a/lib/hanami/model/sql/consoles/sqlite.rb b/lib/hanami/model/sql/consoles/sqlite.rb
index 3587410d..7548518b 100644
--- a/lib/hanami/model/sql/consoles/sqlite.rb
+++ b/lib/hanami/model/sql/consoles/sqlite.rb
@@ -1,5 +1,7 @@
-require_relative 'abstract'
-require 'shellwords'
+# frozen_string_literal: true
+
+require_relative "abstract"
+require "shellwords"
module Hanami
module Model
@@ -12,12 +14,12 @@ module Consoles
class Sqlite < Abstract
# @since 0.7.0
# @api private
- COMMAND = 'sqlite3'.freeze
+ COMMAND = "sqlite3"
# @since 0.7.0
# @api private
def connection_string
- concat(command, ' ', host, database)
+ concat(command, " ", host, database)
end
private
diff --git a/lib/hanami/model/sql/entity/schema.rb b/lib/hanami/model/sql/entity/schema.rb
deleted file mode 100644
index 05e7312d..00000000
--- a/lib/hanami/model/sql/entity/schema.rb
+++ /dev/null
@@ -1,141 +0,0 @@
-require 'hanami/entity/schema'
-require 'hanami/model/types'
-require 'hanami/model/association'
-
-module Hanami
- module Model
- module Sql
- module Entity
- # SQL Entity schema
- #
- # This schema setup is automatic.
- #
- # Hanami looks at the database columns, associations and potentially to
- # the mapping in the repository (optional, only for legacy databases).
- #
- # @since 0.7.0
- # @api private
- #
- # @see Hanami::Entity::Schema
- class Schema < Hanami::Entity::Schema
- # Build a new instance of Schema according to database columns,
- # associations and potentially to mapping defined by the repository.
- #
- # @param registry [Hash] a registry that keeps reference between
- # entities class and their underscored names
- # @param relation [ROM::Relation] the database relation
- # @param mapping [Hanami::Model::Mapping] the optional repository
- # mapping
- #
- # @return [Hanami::Model::Sql::Entity::Schema] the schema
- #
- # @since 0.7.0
- # @api private
- def initialize(registry, relation, mapping)
- attributes = build(registry, relation, mapping)
- @schema = Types::Coercible::Hash.schema(attributes)
- @attributes = Hash[attributes.map { |k, _| [k, true] }]
- freeze
- end
-
- # Process attributes
- #
- # @param attributes [#to_hash] the attributes hash
- #
- # @raise [TypeError] if the process fails
- #
- # @since 1.0.1
- # @api private
- def call(attributes)
- schema.call(attributes)
- end
-
- # @since 1.0.1
- # @api private
- alias [] call
-
- # Check if the attribute is known
- #
- # @param name [Symbol] the attribute name
- #
- # @return [TrueClass,FalseClass] the result of the check
- #
- # @since 0.7.0
- # @api private
- def attribute?(name)
- attributes.key?(name)
- end
-
- private
-
- # @since 0.7.0
- # @api private
- attr_reader :attributes
-
- # Build the schema
- #
- # @param registry [Hash] a registry that keeps reference between
- # entities class and their underscored names
- # @param relation [ROM::Relation] the database relation
- # @param mapping [Hanami::Model::Mapping] the optional repository
- # mapping
- #
- # @return [Dry::Types::Constructor] the inner schema
- #
- # @since 0.7.0
- # @api private
- def build(registry, relation, mapping)
- build_attributes(relation, mapping).merge(
- build_associations(registry, relation.associations)
- )
- end
-
- # Extract a set of attributes from the database table or from the
- # optional repository mapping.
- #
- # @param relation [ROM::Relation] the database relation
- # @param mapping [Hanami::Model::Mapping] the optional repository
- # mapping
- #
- # @return [Hash] a set of attributes
- #
- # @since 0.7.0
- # @api private
- def build_attributes(relation, mapping)
- schema = relation.schema.to_h
- schema.each_with_object({}) do |(attribute, type), result|
- attribute = mapping.translate(attribute) if mapping.reverse?
- result[attribute] = coercible(type)
- end
- end
-
- # Merge attributes and associations
- #
- # @param registry [Hash] a registry that keeps reference between
- # entities class and their underscored names
- # @param associations [ROM::AssociationSet] a set of associations for
- # the current relation
- #
- # @return [Hash] attributes with associations
- #
- # @since 0.7.0
- # @api private
- def build_associations(registry, associations)
- associations.each_with_object({}) do |(name, association), result|
- target = registry.fetch(association.target.to_sym)
- result[name] = Association.lookup(association).schema_type(target)
- end
- end
-
- # Converts given ROM type into coercible type for entity attribute
- #
- # @since 0.7.0
- # @api private
- def coercible(type)
- Types::Schema.coercible(type)
- end
- end
- end
- end
- end
-end
diff --git a/lib/hanami/model/sql/types.rb b/lib/hanami/model/sql/types.rb
index 0c997bb4..e72cb84c 100644
--- a/lib/hanami/model/sql/types.rb
+++ b/lib/hanami/model/sql/types.rb
@@ -1,5 +1,7 @@
-require 'hanami/model/types'
-require 'rom/types'
+# frozen_string_literal: true
+
+require "hanami/model/types"
+require "rom/types"
module Hanami
module Model
@@ -8,28 +10,28 @@ module Sql
#
# @since 0.7.0
module Types
- include Dry::Types.module
+ include Hanami::Model::Types
# Types for schema definitions
#
# @since 0.7.0
module Schema
- require 'hanami/model/sql/types/schema/coercions'
+ require "hanami/model/sql/types/schema/coercions"
String = Types::Optional::Coercible::String
- Int = Types::Strict::Nil | Types::Int.constructor(Coercions.method(:int))
- Float = Types::Strict::Nil | Types::Float.constructor(Coercions.method(:float))
- Decimal = Types::Strict::Nil | Types::Float.constructor(Coercions.method(:decimal))
+ Integer = Types::Strict::Nil | Types::Strict::Integer.constructor(Coercions.method(:int))
+ Float = Types::Strict::Nil | Types::Strict::Float.constructor(Coercions.method(:float))
+ Decimal = Types::Strict::Nil | Types::Strict::Decimal.constructor(Coercions.method(:decimal))
Bool = Types::Strict::Nil | Types::Strict::Bool
- Date = Types::Strict::Nil | Types::Date.constructor(Coercions.method(:date))
- DateTime = Types::Strict::Nil | Types::DateTime.constructor(Coercions.method(:datetime))
- Time = Types::Strict::Nil | Types::Time.constructor(Coercions.method(:time))
+ Date = Types::Strict::Nil | Types::Strict::Date.constructor(Coercions.method(:date))
+ DateTime = Types::Strict::Nil | Types::Strict::DateTime.constructor(Coercions.method(:datetime))
+ Time = Types::Strict::Nil | Types::Strict::Time.constructor(Coercions.method(:time))
- Array = Types::Strict::Nil | Types::Array.constructor(Coercions.method(:array))
- Hash = Types::Strict::Nil | Types::Hash.constructor(Coercions.method(:hash))
+ Array = Types::Strict::Nil | Types::Strict::Array.constructor(Coercions.method(:array))
+ Hash = Types::Strict::Nil | Types::Strict::Hash.constructor(Coercions.method(:hash))
PG_JSON = Types::Strict::Nil | Types::Any.constructor(Coercions.method(:pg_json))
@@ -37,7 +39,7 @@ module Schema
# @api private
MAPPING = {
Types::String.pristine => Schema::String,
- Types::Int.pristine => Schema::Int,
+ Types::Integer.pristine => Schema::Integer,
Types::Float.pristine => Schema::Float,
Types::Decimal.pristine => Schema::Decimal,
Types::Bool.pristine => Schema::Bool,
@@ -47,7 +49,7 @@ module Schema
Types::Array.pristine => Schema::Array,
Types::Hash.pristine => Schema::Hash,
Types::String.optional.pristine => Schema::String,
- Types::Int.optional.pristine => Schema::Int,
+ Types::Integer.optional.pristine => Schema::Integer,
Types::Float.optional.pristine => Schema::Float,
Types::Decimal.optional.pristine => Schema::Decimal,
Types::Bool.optional.pristine => Schema::Bool,
@@ -93,35 +95,11 @@ def self.pg_json_pristines
# @since 1.0.2
# @api private
def self.pg_json?(pristine)
- pristine == pg_json_pristines['JSONB'.freeze] || # rubocop:disable Style/MultipleComparison
- pristine == pg_json_pristines['JSON'.freeze]
+ pristine == pg_json_pristines["JSONB"] || # rubocop:disable Style/MultipleComparison
+ pristine == pg_json_pristines["JSON"]
end
private_class_method :pg_json?
-
- # Coercer for SQL associations target
- #
- # @since 0.7.0
- # @api private
- class AssociationType < Hanami::Model::Types::Schema::CoercibleType
- # Check if value can be coerced
- #
- # @param value [Object] the value
- #
- # @return [TrueClass,FalseClass] the result of the check
- #
- # @since 0.7.0
- # @api private
- def valid?(value)
- value.inspect =~ /\[#{primitive}\]/ || super
- end
-
- # @since 0.7.0
- # @api private
- def success(*args)
- result(Dry::Types::Result::Success, primitive.new(args.first.to_h))
- end
- end
end
end
end
diff --git a/lib/hanami/model/sql/types/schema/coercions.rb b/lib/hanami/model/sql/types/schema/coercions.rb
index 23b57930..994a8df0 100644
--- a/lib/hanami/model/sql/types/schema/coercions.rb
+++ b/lib/hanami/model/sql/types/schema/coercions.rb
@@ -1,5 +1,7 @@
-require 'hanami/utils/string'
-require 'hanami/utils/hash'
+# frozen_string_literal: true
+
+require "hanami/utils/string"
+require "hanami/utils/hash"
module Hanami
module Model
@@ -184,7 +186,7 @@ def self.array(arg)
def self.hash(arg)
case arg
when ::Hash
- arg
+ Utils::Hash.deep_symbolize(arg)
when ->(a) { a.respond_to?(:to_hash) }
Utils::Hash.deep_symbolize(
::Kernel.Hash(arg)
diff --git a/lib/hanami/model/types.rb b/lib/hanami/model/types.rb
index 15dba1f1..dec85291 100644
--- a/lib/hanami/model/types.rb
+++ b/lib/hanami/model/types.rb
@@ -1,4 +1,6 @@
-require 'rom/types'
+# frozen_string_literal: true
+
+require "rom/types"
module Hanami
module Model
@@ -29,10 +31,8 @@ module ClassMethods
# require "hanami/model"
#
# class Account < Hanami::Entity
- # attributes do
- # # ...
- # attribute :owner, Types::Entity(User)
- # end
+ # # ...
+ # attribute :owner, Types::Entity(User)
# end
#
# account = Account.new(owner: User.new(name: "Luca"))
@@ -43,8 +43,7 @@ module ClassMethods
# account.owner.class # => User
# account.owner.name # => "MG"
def Entity(type)
- type = Schema::CoercibleType.new(type) unless type.is_a?(Dry::Types::Definition)
- type
+ Hanami::Model::Types.Constructor(type).optional
end
# Define an array of given type
@@ -73,81 +72,10 @@ def Entity(type)
# user.class # => User
# user.name # => "MG"
def Collection(type)
- type = Schema::CoercibleType.new(type) unless type.is_a?(Dry::Types::Definition)
- Types::Array.member(type)
+ Hanami::Model::Types.Array(type)
end
end
# rubocop:enable Naming/MethodName
-
- # Types for schema definitions
- #
- # @since 0.7.0
- module Schema
- # Coercer for objects within custom schema definition
- #
- # @since 0.7.0
- # @api private
- class CoercibleType < Dry::Types::Definition
- # Coerce given value into the wrapped object type
- #
- # @param value [Object] the value
- #
- # @return [Object] the coerced value of `object` type
- #
- # @raise [TypeError] if value can't be coerced
- #
- # @since 0.7.0
- # @api private
- def call(value)
- return if value.nil?
-
- if valid?(value) # rubocop:disable Style/GuardClause
- coerce(value)
- else
- raise TypeError.new("#{value.inspect} must be coercible into #{object}")
- end
- end
-
- # Check if value can be coerced
- #
- # It is true if value is an instance of `object` type or if value
- # responds to `#to_hash`.
- #
- # @param value [Object] the value
- #
- # @return [TrueClass,FalseClass] the result of the check
- #
- # @since 0.7.0
- # @api private
- def valid?(value)
- value.is_a?(object) ||
- value.respond_to?(:to_hash)
- end
-
- # Coerce given value into an instance of `object` type
- #
- # @param value [Object] the value
- #
- # @return [Object] the coerced value of `object` type
- def coerce(value)
- case value
- when object
- value
- else
- object.new(value.to_hash)
- end
- end
-
- # @since 0.7.0
- # @api private
- def object
- result = primitive
- return result unless result.respond_to?(:primitive)
-
- result.primitive
- end
- end
- end
end
end
end
diff --git a/lib/hanami/model/version.rb b/lib/hanami/model/version.rb
index 3e154d3c..c83ee629 100644
--- a/lib/hanami/model/version.rb
+++ b/lib/hanami/model/version.rb
@@ -1,8 +1,10 @@
+# frozen_string_literal: true
+
module Hanami
module Model
# Defines the version
#
# @since 0.1.0
- VERSION = '1.3.2'.freeze
+ VERSION = "2.0.0.alpha1"
end
end
diff --git a/lib/hanami/relation.rb b/lib/hanami/relation.rb
new file mode 100644
index 00000000..8a55ceb9
--- /dev/null
+++ b/lib/hanami/relation.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+module Hanami
+ # TODO: Document?
+ Relation = ROM::Relation
+end
diff --git a/lib/hanami/repository.rb b/lib/hanami/repository.rb
index cd553e17..47a6c12b 100644
--- a/lib/hanami/repository.rb
+++ b/lib/hanami/repository.rb
@@ -1,19 +1,14 @@
-require 'rom-repository'
-require 'hanami/model/entity_name'
-require 'hanami/model/relation_name'
-require 'hanami/model/mapped_relation'
-require 'hanami/model/associations/dsl'
-require 'hanami/model/association'
-require 'hanami/utils/class'
-require 'hanami/utils/class_attribute'
-require 'hanami/utils/io'
+# frozen_string_literal: true
+
+require "rom-repository"
+require "hanami/model/mapped_relation"
module Hanami
# Mediates between the entities and the persistence layer, by offering an API
# to query and execute commands on a database.
#
#
- #
+ # TODO: Update docs
# By default, a repository is named after an entity, by appending the
# `Repository` suffix to the entity class name.
#
@@ -73,7 +68,7 @@ module Hanami
# # * If we change the storage, we are forced to change the code of the
# # caller(s).
#
- # ArticleRepository.new.where(author_id: 23).order(:published_at).limit(8)
+ # ArticleRepository.new(configuration: config).where(author_id: 23).order(:published_at).limit(8)
#
#
#
@@ -91,11 +86,11 @@ module Hanami
# #
# # * If we change the storage, the callers aren't affected.
#
- # ArticleRepository.new.most_recent_by_author(author)
+ # ArticleRepository.new(configuration: config).most_recent_by_author(author)
#
# class ArticleRepository < Hanami::Repository
# def most_recent_by_author(author, limit = 8)
- # articles.
+ # root.
# where(author_id: author.id).
# order(:published_at).
# limit(limit)
@@ -107,30 +102,14 @@ module Hanami
# @see Hanami::Entity
# @see http://martinfowler.com/eaaCatalog/repository.html
# @see http://en.wikipedia.org/wiki/Dependency_inversion_principle
- class Repository < ROM::Repository::Root # rubocop:disable Metrics/ClassLength
+ class Repository < ROM::Repository::Root
# Plugins for database commands
#
# @since 0.7.0
# @api private
#
# @see Hanami::Model::Plugins
- COMMAND_PLUGINS = %i[schema mapping timestamps].freeze
-
- # Configuration
- #
- # @since 0.7.0
- # @api private
- def self.configuration
- Hanami::Model.configuration
- end
-
- # Container
- #
- # @since 0.7.0
- # @api private
- def self.container
- Hanami::Model.container
- end
+ COMMAND_PLUGINS = %i[timestamps].freeze
# Define a new ROM::Command while preserving the defaults used by Hanami itself.
#
@@ -152,187 +131,28 @@ def self.container
# end
#
# @since 1.2.0
- def command(*args, **opts, &block)
+ def command(type, relation: root, **opts, &block)
opts[:use] = COMMAND_PLUGINS | Array(opts[:use])
- opts[:mapper] = opts.fetch(:mapper, Model::MappedRelation.mapper_name)
- super(*args, **opts, &block)
+ relation.command(type, **opts, &block)
end
- # Define a database relation, which describes how data is fetched from the
- # database.
- #
- # It auto-infers the underlying database table.
- #
- # @since 0.7.0
- # @api private
- #
- # rubocop:disable Metrics/MethodLength
- # rubocop:disable Metrics/AbcSize
- def self.define_relation
- a = @associations
- s = @schema
-
- configuration.relation(relation) do
- if s.nil?
- schema(infer: true) do
- associations(&a) unless a.nil?
- end
- else
- schema(&s)
- end
+ # @api
+ # @since x.x.x
+ def [](name)
+ super
+ fetch_or_store(name) do
+ klass = Class.new(self < ROM::Repository::Root ? self : ROM::Repository::Root)
+ klass.root(name)
end
-
- relations(relation)
- root(relation)
- class_eval %{
- def #{relation}
- Hanami::Model::MappedRelation.new(@#{relation})
- end
- }, __FILE__, __LINE__ - 4
- end
- # rubocop:enable Metrics/AbcSize
- # rubocop:enable Metrics/MethodLength
-
- # Defines the mapping between a database table and an entity.
- #
- # It's also responsible to associate table columns to entity attributes.
- #
- # @since 0.7.0
- # @api private
- #
- # rubocop:disable Metrics/MethodLength
- # rubocop:disable Metrics/AbcSize
- def self.define_mapping
- self.entity = Utils::Class.load!(entity_name)
- e = entity
- m = @mapping
-
- blk = lambda do |_|
- model e
- register_as Model::MappedRelation.mapper_name
- instance_exec(&m) unless m.nil?
- end
-
- root = self.root
- configuration.mappers { define(root, &blk) }
- configuration.define_mappings(root, &blk)
- configuration.register_entity(relation, entity_name.underscore, e)
- end
- # rubocop:enable Metrics/AbcSize
- # rubocop:enable Metrics/MethodLength
-
- # It defines associations, by adding relations to the repository
- #
- # @since 0.7.0
- # @api private
- #
- # @see Hanami::Model::Associations::Dsl
- def self.define_associations
- Model::Associations::Dsl.new(self, &@associations) unless @associations.nil?
- end
-
- # Declare associations for the repository
- #
- # NOTE: This is an experimental feature
- #
- # @since 0.7.0
- # @api private
- #
- # @example
- # class BookRepository < Hanami::Repository
- # associations do
- # has_many :books
- # end
- # end
- def self.associations(&blk)
- @associations = blk
- end
-
- # Declare database schema
- #
- # NOTE: This should be used **only** when Hanami can't find a corresponding Ruby type for your column.
- #
- # @since 1.0.0
- #
- # @example
- # # In this example `name` is a PostgreSQL Enum type that we want to treat like a string.
- #
- # class ColorRepository < Hanami::Repository
- # schema do
- # attribute :id, Hanami::Model::Sql::Types::Int
- # attribute :name, Hanami::Model::Sql::Types::String
- # attribute :created_at, Hanami::Model::Sql::Types::DateTime
- # attribute :updated_at, Hanami::Model::Sql::Types::DateTime
- # end
- # end
- def self.schema(&blk)
- @schema = blk
end
- # Declare mapping between database columns and entity's attributes
- #
- # NOTE: This should be used **only** when there is a name mismatch (eg. in legacy databases).
- #
- # @since 0.7.0
- #
- # @example
- # class BookRepository < Hanami::Repository
- # self.relation = :t_operator
- #
- # mapping do
- # attribute :id, from: :operator_id
- # attribute :name, from: :s_name
- # end
- # end
- def self.mapping(&blk)
- @mapping = blk
- end
-
- # Define relations, mapping and associations
- #
- # @since 0.7.0
- # @api private
- def self.load!
- define_relation
- define_mapping
- define_associations
- end
-
- # @since 0.7.0
- # @api private
- #
- # rubocop:disable Metrics/MethodLength
- # rubocop:disable Metrics/AbcSize
+ # @api
+ # @since x.x.x
def self.inherited(klass)
- klass.class_eval do
- include Utils::ClassAttribute
- auto_struct true
-
- @associations = nil
- @mapping = nil
- @schema = nil
-
- class_attribute :entity
- class_attribute :entity_name
- class_attribute :relation
-
- Hanami::Utils::IO.silence_warnings do
- def self.relation=(name)
- @relation = name.to_sym
- end
- end
-
- self.entity_name = Model::EntityName.new(name)
- self.relation = Model::RelationName.new(name)
-
- commands :create, update: :by_pk, delete: :by_pk, mapper: Model::MappedRelation.mapper_name, use: COMMAND_PLUGINS
- prepend Commands
- end
-
- Hanami::Model.repositories << klass
+ super
+ klass.commands :create, update: :by_pk, delete: :by_pk, use: COMMAND_PLUGINS
+ klass.prepend Commands
end
- # rubocop:enable Metrics/AbcSize
- # rubocop:enable Metrics/MethodLength
# Extend commands from ROM::Repository with error management
#
@@ -347,14 +167,14 @@ module Commands
# @since 0.7.0
#
# @example Create From Hash
- # user = UserRepository.new.create(name: 'Luca')
+ # user = UserRepository.new(configuration: config).create(name: 'Luca')
#
# @example Create From Entity
- # entity = User.new(name: 'Luca')
- # user = UserRepository.new.create(entity)
+ # entity = { name: 'Luca' }
+ # user = UserRepository.new(configuration: config).create(entity)
#
# user.id # => 23
- # entity.id # => nil - It doesn't mutate original entity
+ # entity[:id] # => nil - It doesn't mutate original entity
def create(*args)
super
rescue => exception
@@ -379,11 +199,11 @@ def create(*args)
# repository = UserRepository.new
# user = repository.create(name: 'Luca')
#
- # entity = User.new(age: 34)
+ # entity = { age: 34 }
# user = repository.update(user.id, entity)
#
# user.age # => 34
- # entity.id # => nil - It doesn't mutate original entity
+ # entity[:id] # => nil - It doesn't mutate original entity
def update(*args)
super
rescue => exception
@@ -415,8 +235,8 @@ def delete(*args)
# @return [Hanami::Repository] the new instance
#
# @since 0.7.0
- def initialize
- super(self.class.container)
+ def self.new(configuration:, **options)
+ super(configuration.container, **options)
end
# Find by primary key
@@ -434,7 +254,7 @@ def initialize
#
# user = repository.find(user.id)
def find(id)
- root.by_pk(id).as(:entity).one
+ root.by_pk(id).one
rescue => exception
raise Hanami::Model::Error.for(exception)
end
@@ -448,7 +268,7 @@ def find(id)
# @example
# UserRepository.new.all
def all
- root.as(:entity).to_a
+ root.to_a
end
# Returns the first record for the relation
@@ -460,7 +280,7 @@ def all
# @example
# UserRepository.new.first
def first
- root.as(:entity).limit(1).one
+ root.limit(1).one
end
# Returns the last record for the relation
@@ -472,7 +292,7 @@ def first
# @example
# UserRepository.new.last
def last
- root.as(:entity).limit(1).reverse.one
+ root.limit(1).reverse.one
end
# Deletes all the records from the relation
@@ -484,17 +304,5 @@ def last
def clear
root.delete
end
-
- private
-
- # Returns an association
- #
- # NOTE: This is an experimental feature
- #
- # @since 0.7.0
- # @api private
- def assoc(target, subject = nil)
- Hanami::Model::Association.build(self, target, subject)
- end
end
end
diff --git a/spec/integration/hanami/model/associations/belongs_to_spec.rb b/spec/integration/hanami/model/associations/belongs_to_spec.rb
index a66eb2ba..81e2db7e 100644
--- a/spec/integration/hanami/model/associations/belongs_to_spec.rb
+++ b/spec/integration/hanami/model/associations/belongs_to_spec.rb
@@ -1,25 +1,27 @@
-RSpec.describe 'Associations (belongs_to)' do
+# frozen_string_literal: true
+
+RSpec.describe "Associations (belongs_to)" do
it "returns nil if association wasn't preloaded" do
- repository = BookRepository.new
- book = repository.create(name: 'L')
+ repository = BookRepository.new(configuration: configuration)
+ book = repository.create(name: "L")
found = repository.find(book.id)
expect(found.author).to be(nil)
end
- it 'preloads the associated record' do
- repository = BookRepository.new
- author = AuthorRepository.new.create(name: 'Michel Foucault')
- book = repository.create(author_id: author.id, title: 'Surveiller et punir')
+ it "preloads the associated record" do
+ repository = BookRepository.new(configuration: configuration)
+ author = AuthorRepository.new(configuration: configuration).create(name: "Michel Foucault")
+ book = repository.create(author_id: author.id, title: "Surveiller et punir")
found = repository.find_with_author(book.id)
expect(found).to eq(book)
expect(found.author).to eq(author)
end
- it 'returns an author' do
- repository = BookRepository.new
- author = AuthorRepository.new.create(name: 'Maurice Leblanc')
+ it "returns an author" do
+ repository = BookRepository.new(configuration: configuration)
+ author = AuthorRepository.new(configuration: configuration).create(name: "Maurice Leblanc")
book = repository.create(author_id: author.id, title: "L'Aguille Creuse")
found = repository.author_for(book)
@@ -27,8 +29,8 @@
end
it "returns nil if there's no associated record" do
- repository = BookRepository.new
- book = repository.create(title: 'The no author book')
+ repository = BookRepository.new(configuration: configuration)
+ book = repository.create(title: "The no author book")
expect { repository.find_with_author(book.id) }.to_not raise_error
end
diff --git a/spec/integration/hanami/model/associations/has_many_spec.rb b/spec/integration/hanami/model/associations/has_many_spec.rb
index 617aba21..613c2ead 100644
--- a/spec/integration/hanami/model/associations/has_many_spec.rb
+++ b/spec/integration/hanami/model/associations/has_many_spec.rb
@@ -1,17 +1,19 @@
-RSpec.describe 'Associations (has_many)' do
- let(:authors) { AuthorRepository.new }
- let(:books) { BookRepository.new }
+# frozen_string_literal: true
+
+RSpec.describe "Associations (has_many)" do
+ let(:authors) { AuthorRepository.new(configuration: configuration) }
+ let(:books) { BookRepository.new(configuration: configuration) }
it "returns nil if association wasn't preloaded" do
- author = authors.create(name: 'L')
+ author = authors.create(name: "L")
found = authors.find(author.id)
expect(found.books).to be_nil
end
- it 'preloads associated records' do
- author = authors.create(name: 'Umberto Eco')
- book = books.create(author_id: author.id, title: 'Foucault Pendulum')
+ it "preloads associated records" do
+ author = authors.create(name: "Umberto Eco")
+ book = books.create(author_id: author.id, title: "Foucault Pendulum")
found = authors.find_with_books(author.id)
@@ -19,24 +21,24 @@
expect(found.books).to eq([book])
end
- it 'creates an object with a collection of associated objects' do
- author = authors.create_with_books(name: 'Henry Thoreau', books: [{ title: 'Walden' }])
+ it "creates an object with a collection of associated objects" do
+ author = authors.create_with_books(name: "Henry Thoreau", books: [{ title: "Walden" }])
- expect(author).to be_an_instance_of(Author)
- expect(author.name).to eq('Henry Thoreau')
- expect(author.books).to be_an_instance_of(Array)
- expect(author.books.first).to be_an_instance_of(Book)
- expect(author.books.first.title).to eq('Walden')
+ expect(author).to be_a(Project::Entities::Author)
+ expect(author.name).to eq("Henry Thoreau")
+ expect(author.books).to be_an(Array)
+ expect(author.books.first).to be_a(Project::Entities::Book)
+ expect(author.books.first.title).to eq("Walden")
end
- it 'creates associated records when it receives a collection of serializable data' do
- author = authors.create_with_books(name: 'Sandi Metz', books: [BaseParams.new(title: 'Practical Object-Oriented Design in Ruby')])
+ it "creates associated records when it receives a collection of serializable data" do
+ author = authors.create_with_books(name: "Sandi Metz", books: [BaseParams.new(title: "Practical Object-Oriented Design in Ruby")])
- expect(author).to be_an_instance_of(Author)
- expect(author.name).to eq('Sandi Metz')
- expect(author.books).to be_an_instance_of(Array)
- expect(author.books.first).to be_an_instance_of(Book)
- expect(author.books.first.title).to eq('Practical Object-Oriented Design in Ruby')
+ expect(author).to be_a(Project::Entities::Author)
+ expect(author.name).to eq("Sandi Metz")
+ expect(author.books).to be_an(Array)
+ expect(author.books.first).to be_a(Project::Entities::Book)
+ expect(author.books.first.title).to eq("Practical Object-Oriented Design in Ruby")
end
##############################################################################
@@ -46,38 +48,38 @@
##
# ADD
#
- it 'adds an object to the collection' do
- author = authors.create(name: 'Alexandre Dumas')
- book = authors.add_book(author, title: 'The Count of Monte Cristo')
+ it "adds an object to the collection" do
+ author = authors.create(name: "Alexandre Dumas")
+ book = authors.add_book(author, title: "The Count of Monte Cristo")
expect(book.id).to_not be_nil
- expect(book.title).to eq('The Count of Monte Cristo')
+ expect(book.title).to eq("The Count of Monte Cristo")
expect(book.author_id).to eq(author.id)
end
- it 'adds an object to the collection with serializable data' do
- author = authors.create(name: 'David Foster Wallace')
- book = authors.add_book(author, BaseParams.new(title: 'Infinite Jest'))
+ it "adds an object to the collection with serializable data" do
+ author = authors.create(name: "David Foster Wallace")
+ book = authors.add_book(author, BaseParams.new(title: "Infinite Jest"))
expect(book.id).to_not be_nil
- expect(book.title).to eq('Infinite Jest')
+ expect(book.title).to eq("Infinite Jest")
expect(book.author_id).to eq(author.id)
end
##
# REMOVE
#
- it 'removes an object from the collection' do
- authors = AuthorRepository.new
- books = BookRepository.new
+ it "removes an object from the collection" do
+ authors = AuthorRepository.new(configuration: configuration)
+ books = BookRepository.new(configuration: configuration)
# Book under test
- author = authors.create(name: 'Douglas Adams')
+ author = authors.create(name: "Douglas Adams")
book = books.create(author_id: author.id, title: "The Hitchhiker's Guide to the Galaxy")
# Different book
- a = authors.create(name: 'William Finnegan')
- b = books.create(author_id: a.id, title: 'Barbarian Days: A Surfing Life')
+ a = authors.create(name: "William Finnegan")
+ b = books.create(author_id: a.id, title: "Barbarian Days: A Surfing Life")
authors.remove_book(author, book.id)
@@ -97,10 +99,10 @@
##
# TO_A
#
- it 'returns an array of books' do
- author = authors.create(name: 'Nikolai Gogol')
- expected = books.create(author_id: author.id, title: 'Dead Souls')
- expect(expected).to be_an_instance_of(Book)
+ it "returns an array of books" do
+ author = authors.create(name: "Nikolai Gogol")
+ expected = books.create(author_id: author.id, title: "Dead Souls")
+ expect(expected).to be_a(Project::Entities::Book)
actual = authors.books_for(author).to_a
expect(actual).to eq([expected])
@@ -109,13 +111,13 @@
##
# EACH
#
- it 'iterates through the books' do
- author = authors.create(name: 'José Saramago')
- expected = books.create(author_id: author.id, title: 'The Cave')
+ it "iterates through the books" do
+ author = authors.create(name: "José Saramago")
+ expected = books.create(author_id: author.id, title: "The Cave")
actual = []
authors.books_for(author).each do |book|
- expect(book).to be_an_instance_of(Book)
+ expect(book).to be_a(Project::Entities::Book)
actual << book
end
@@ -125,10 +127,10 @@
##
# MAP
#
- it 'iterates through the books and returns an array' do
- author = authors.create(name: 'José Saramago')
- expected = books.create(author_id: author.id, title: 'The Cave')
- expect(expected).to be_an_instance_of(Book)
+ it "iterates through the books and returns an array" do
+ author = authors.create(name: "José Saramago")
+ expected = books.create(author_id: author.id, title: "The Cave")
+ expect(expected).to be_a(Project::Entities::Book)
actual = authors.books_for(author).map { |book| book }
expect(actual).to eq([expected])
@@ -137,17 +139,18 @@
##
# COUNT
#
- it 'returns the count of the associated books' do
- author = authors.create(name: 'Fyodor Dostoevsky')
- books.create(author_id: author.id, title: 'Crime and Punishment')
- books.create(author_id: author.id, title: 'The Brothers Karamazov')
+ it "returns the count of the associated books" do
+ author = authors.create(name: "Fyodor Dostoevsky")
+ books.create(author_id: author.id, title: "Crime and Punishment")
+ books.create(author_id: author.id, title: "The Brothers Karamazov")
expect(authors.books_count(author)).to eq(2)
end
- it 'returns the count of on sale associated books' do
- author = authors.create(name: 'Steven Pinker')
- books.create(author_id: author.id, title: 'The Sense of Style', on_sale: true)
+ it "returns the count of on sale associated books" do
+ author = authors.create(name: "Steven Pinker")
+ books.create(author_id: author.id, title: "The Sense of Style", on_sale: true)
+ books.create(author_id: author.id, title: "The Blank Slate", on_sale: false)
expect(authors.on_sales_books_count(author)).to eq(1)
end
@@ -155,19 +158,19 @@
##
# DELETE
#
- it 'deletes all the books' do
- author = authors.create(name: 'Grazia Deledda')
- book = books.create(author_id: author.id, title: 'Reeds In The Wind')
+ it "deletes all the books" do
+ author = authors.create(name: "Grazia Deledda")
+ book = books.create(author_id: author.id, title: "Reeds In The Wind")
authors.delete_books(author)
expect(books.find(book.id)).to be_nil
end
- it 'deletes scoped books' do
- author = authors.create(name: 'Harper Lee')
- book = books.create(author_id: author.id, title: 'To Kill A Mockingbird')
- on_sale = books.create(author_id: author.id, title: 'Go Set A Watchman', on_sale: true)
+ it "deletes scoped books" do
+ author = authors.create(name: "Harper Lee")
+ book = books.create(author_id: author.id, title: "To Kill A Mockingbird")
+ on_sale = books.create(author_id: author.id, title: "Go Set A Watchman", on_sale: true)
authors.delete_on_sales_books(author)
@@ -175,21 +178,18 @@
expect(books.find(on_sale.id)).to be_nil
end
- context 'raises a Hanami::Model::Error wrapped exception on' do
- it '#create' do
+ xcontext "raises a Hanami::Model::Error wrapped exception on" do
+ it "#create" do
expect do
- authors.create_with_books(name: 'Noam Chomsky')
+ authors.create_with_books(name: "Noam Chomsky")
end.to raise_error Hanami::Model::Error
end
- it '#add' do
- author = authors.create(name: 'Machado de Assis')
+ it "#add" do
+ author = authors.create(name: "Machado de Assis")
expect do
- authors.add_book(author, title: 'O Alienista', on_sale: nil)
+ authors.add_book(author, title: "O Alienista", on_sale: nil)
end.to raise_error Hanami::Model::NotNullConstraintViolationError
end
-
- # skipped spec
- it '#remove'
end
end
diff --git a/spec/integration/hanami/model/associations/has_one_spec.rb b/spec/integration/hanami/model/associations/has_one_spec.rb
index f472513a..381e0962 100644
--- a/spec/integration/hanami/model/associations/has_one_spec.rb
+++ b/spec/integration/hanami/model/associations/has_one_spec.rb
@@ -1,68 +1,68 @@
-require 'spec_helper'
+# frozen_string_literal: true
-RSpec.describe 'Associations (has_one)' do
+RSpec.describe "Associations (has_one)" do
extend PlatformHelpers
- let(:users) { UserRepository.new }
- let(:avatars) { AvatarRepository.new }
+ let(:users) { UserRepository.new(configuration: configuration) }
+ let(:avatars) { AvatarRepository.new(configuration: configuration) }
it "returns nil if the association wasn't preloaded" do
- user = users.create(name: 'John Doe')
+ user = users.create(name: "John Doe")
found = users.find(user.id)
expect(found.avatar).to be_nil
end
- it 'preloads the associated record' do
- user = users.create(name: 'Baruch Spinoza')
- avatar = avatars.create(user_id: user.id, url: 'http://www.notarealurl.com/avatar.png')
+ it "preloads the associated record" do
+ user = users.create(name: "Baruch Spinoza")
+ avatar = avatars.create(user_id: user.id, url: "http://www.notarealurl.com/avatar.png")
found = users.find_with_avatar(user.id)
expect(found).to eq(user)
expect(found.avatar).to eq(avatar)
end
- it 'returns an Avatar' do
- user = users.create(name: 'Simone de Beauvoir')
- avatar = avatars.create(user_id: user.id, url: 'http://www.notarealurl.com/simone.png')
+ it "returns an Avatar" do
+ user = users.create(name: "Simone de Beauvoir")
+ avatar = avatars.create(user_id: user.id, url: "http://www.notarealurl.com/simone.png")
found = users.avatar_for(user)
expect(found).to eq(avatar)
end
- it 'returns nil if the association was preloaded but no associated object is set' do
- user = users.create(name: 'Henry Jenkins')
+ it "returns nil if the association was preloaded but no associated object is set" do
+ user = users.create(name: "Henry Jenkins")
found = users.find_with_avatar(user.id)
expect(found).to eq(user)
expect(found.avatar).to be_nil
end
- context '#add' do
- it 'adds an an Avatar to an existing User' do
- user = users.create(name: 'Jean Paul-Sartre')
- avatar = users.add_avatar(user, url: 'http://www.notarealurl.com/sartre.png')
+ context "#add" do
+ it "adds an an Avatar to an existing User" do
+ user = users.create(name: "Jean Paul-Sartre")
+ avatar = users.add_avatar(user, url: "http://www.notarealurl.com/sartre.png")
found = users.find_with_avatar(user.id)
expect(found).to eq(user)
expect(found.avatar.id).to eq(avatar.id)
- expect(found.avatar.url).to eq('http://www.notarealurl.com/sartre.png')
+ expect(found.avatar.url).to eq("http://www.notarealurl.com/sartre.png")
end
- it 'adds an an Avatar to an existing User when serializable data is received' do
- user = users.create(name: 'Jean Paul-Sartre')
- avatar = users.add_avatar(user, BaseParams.new(url: 'http://www.notarealurl.com/sartre.png'))
+ it "adds an an Avatar to an existing User when serializable data is received" do
+ user = users.create(name: "Jean Paul-Sartre")
+ avatar = users.add_avatar(user, BaseParams.new(url: "http://www.notarealurl.com/sartre.png"))
found = users.find_with_avatar(user.id)
expect(found).to eq(user)
expect(found.avatar.id).to eq(avatar.id)
- expect(found.avatar.url).to eq('http://www.notarealurl.com/sartre.png')
+ expect(found.avatar.url).to eq("http://www.notarealurl.com/sartre.png")
end
end
- context '#update' do
- it 'updates the avatar' do
- user = users.create_with_avatar(name: 'Bakunin', avatar: { url: 'bakunin.jpg' })
- users.update_avatar(user, url: url = 'http://history.com/bakunin.png')
+ context "#update" do
+ it "updates the avatar" do
+ user = users.create_with_avatar(name: "Bakunin", avatar: { url: "bakunin.jpg" })
+ users.update_avatar(user, url: url = "http://history.com/bakunin.png")
found = users.find_with_avatar(user.id)
@@ -71,9 +71,9 @@
expect(found.avatar.url).to eq(url)
end
- it 'updates the avatar when serializable data is received' do
- user = users.create_with_avatar(name: 'Bakunin', avatar: { url: 'bakunin.jpg' })
- users.update_avatar(user, BaseParams.new(url: url = 'http://history.com/bakunin.png'))
+ it "updates the avatar when serializable data is received" do
+ user = users.create_with_avatar(name: "Bakunin", avatar: { url: "bakunin.jpg" })
+ users.update_avatar(user, BaseParams.new(url: url = "http://history.com/bakunin.png"))
found = users.find_with_avatar(user.id)
@@ -83,43 +83,43 @@
end
end
- context '#create' do
- it 'creates a User and an Avatar' do
- user = users.create_with_avatar(name: 'Lao Tse', avatar: { url: 'http://lao-tse.io/me.jpg' })
+ context "#create" do
+ it "creates a User and an Avatar" do
+ user = users.create_with_avatar(name: "Lao Tse", avatar: { url: "http://lao-tse.io/me.jpg" })
found = users.find_with_avatar(user.id)
expect(found.name).to eq(user.name)
expect(found.avatar).to eq(user.avatar)
- expect(found.avatar.url).to eq('http://lao-tse.io/me.jpg')
+ expect(found.avatar.url).to eq("http://lao-tse.io/me.jpg")
end
- it 'creates a User and an Avatar when serializable data is received' do
- user = users.create_with_avatar(name: 'Lao Tse', avatar: BaseParams.new(url: 'http://lao-tse.io/me.jpg'))
+ it "creates a User and an Avatar when serializable data is received" do
+ user = users.create_with_avatar(name: "Lao Tse", avatar: BaseParams.new(url: "http://lao-tse.io/me.jpg"))
found = users.find_with_avatar(user.id)
expect(found.name).to eq(user.name)
expect(found.avatar).to eq(user.avatar)
- expect(found.avatar.url).to eq('http://lao-tse.io/me.jpg')
+ expect(found.avatar.url).to eq("http://lao-tse.io/me.jpg")
end
end
- context '#delete' do
- it 'removes the Avatar' do
- user = users.create_with_avatar(name: 'Bob Ross', avatar: { url: 'http://bobross/happy_little_avatar.jpg' })
- other = users.create_with_avatar(name: 'Candido Portinari', avatar: { url: 'some_mugshot.jpg' })
+ context "#delete" do
+ it "removes the Avatar" do
+ user = users.create_with_avatar(name: "Bob Ross", avatar: { url: "http://bobross/happy_little_avatar.jpg" })
+ other = users.create_with_avatar(name: "Candido Portinari", avatar: { url: "some_mugshot.jpg" })
users.remove_avatar(user)
found = users.find_with_avatar(user.id)
other_found = users.find_with_avatar(other.id)
expect(found.avatar).to be_nil
- expect(other_found.avatar).to be_an Avatar
+ expect(other_found.avatar).to be_an Project::Entities::Avatar
end
end
- context '#replace' do
- it 'replaces the associated object' do
- user = users.create_with_avatar(name: 'Frank Herbert', avatar: { url: 'http://not-real.com/avatar.jpg' })
- users.replace_avatar(user, url: 'http://totally-correct.com/avatar.jpg')
+ context "#replace" do
+ it "replaces the associated object" do
+ user = users.create_with_avatar(name: "Frank Herbert", avatar: { url: "http://not-real.com/avatar.jpg" })
+ users.replace_avatar(user, url: "http://totally-correct.com/avatar.jpg")
found = users.find_with_avatar(user.id)
expect(found.avatar).to_not eq(user.avatar)
@@ -127,9 +127,9 @@
expect(avatars.by_user(user.id).size).to eq(1)
end
- it 'replaces the associated object when serializable data is received' do
- user = users.create_with_avatar(name: 'Frank Herbert', avatar: { url: 'http://not-real.com/avatar.jpg' })
- users.replace_avatar(user, BaseParams.new(url: 'http://totally-correct.com/avatar.jpg'))
+ it "replaces the associated object when serializable data is received" do
+ user = users.create_with_avatar(name: "Frank Herbert", avatar: { url: "http://not-real.com/avatar.jpg" })
+ users.replace_avatar(user, BaseParams.new(url: "http://totally-correct.com/avatar.jpg"))
found = users.find_with_avatar(user.id)
expect(found.avatar).to_not eq(user.avatar)
@@ -138,22 +138,22 @@
end
end
- context 'raises a Hanami::Model::Error wrapped exception on' do
- it '#create' do
+ xcontext "raises a Hanami::Model::Error wrapped exception on" do
+ it "#create" do
expect do
- users.create_with_avatar(name: 'Noam Chomsky')
+ users.create_with_avatar(name: "Noam Chomsky")
end.to raise_error Hanami::Model::Error
end
- it '#add' do
- user = users.create_with_avatar(name: 'Stephen Fry', avatar: { url: 'fry_mugshot.png' })
- expect { users.add_avatar(user, url: 'new_mugshot.png') }.to raise_error Hanami::Model::UniqueConstraintViolationError
+ it "#add" do
+ user = users.create_with_avatar(name: "Stephen Fry", avatar: { url: "fry_mugshot.png" })
+ expect { users.add_avatar(user, url: "new_mugshot.png") }.to raise_error Hanami::Model::UniqueConstraintViolationError
end
# by default it seems that MySQL allows you to update a NOT NULL column to a NULL value
unless_platform(db: :mysql) do
- it '#update' do
- user = users.create_with_avatar(name: 'Dan North', avatar: { url: 'bdd_creator.png' })
+ it "#update" do
+ user = users.create_with_avatar(name: "Dan North", avatar: { url: "bdd_creator.png" })
expect do
users.update_avatar(user, url: nil)
@@ -161,8 +161,8 @@
end
end
- it '#replace' do
- user = users.create_with_avatar(name: 'Eric Evans', avatar: { url: 'ddd_man.png' })
+ it "#replace" do
+ user = users.create_with_avatar(name: "Eric Evans", avatar: { url: "ddd_man.png" })
expect { users.replace_avatar(user, url: nil) }.to raise_error Hanami::Model::NotNullConstraintViolationError
end
end
diff --git a/spec/integration/hanami/model/associations/many_to_many_spec.rb b/spec/integration/hanami/model/associations/many_to_many_spec.rb
index f00ce283..3a20dbf8 100644
--- a/spec/integration/hanami/model/associations/many_to_many_spec.rb
+++ b/spec/integration/hanami/model/associations/many_to_many_spec.rb
@@ -1,19 +1,21 @@
-RSpec.describe 'Associations (has_many :through)' do
+# frozen_string_literal: true
+
+RSpec.describe "Associations (has_many :through)" do
#### REPOS
- let(:books) { BookRepository.new }
- let(:categories) { CategoryRepository.new }
- let(:ontologies) { BookOntologyRepository.new }
+ let(:books) { BookRepository.new(configuration: configuration) }
+ let(:categories) { CategoryRepository.new(configuration: configuration) }
+ let(:ontologies) { BookOntologyRepository.new(configuration: configuration) }
### ENTITIES
- let(:book) { books.create(title: 'Ontology: Encyclopedia of Database Systems') }
- let(:category) { categories.create(name: 'information science') }
+ let(:book) { books.create(title: "Ontology: Encyclopedia of Database Systems") }
+ let(:category) { categories.create(name: "information science") }
it "returns nil if association wasn't preloaded" do
found = books.find(book.id)
expect(found.categories).to be(nil)
end
- it 'preloads the associated record' do
+ it "preloads the associated record" do
ontologies.create(book_id: book.id, category_id: category.id)
found = books.find_with_categories(book.id)
@@ -21,22 +23,22 @@
expect(found.categories).to eq([category])
end
- it 'returns an array of Categories' do
+ it "returns an array of Categories" do
ontologies.create(book_id: book.id, category_id: category.id)
found = books.categories_for(book)
expect(found).to eq([category])
end
- it 'returns the count of on sale associated books' do
- on_sale = books.create(title: 'The Sense of Style', on_sale: true)
+ it "returns the count of on sale associated books" do
+ on_sale = books.create(title: "The Sense of Style", on_sale: true)
ontologies.create(book_id: on_sale.id, category_id: category.id)
expect(categories.on_sales_books_count(category)).to eq(1)
end
- context '#add' do
- it 'adds an object to the collection' do
+ context "#add" do
+ it "adds an object to the collection" do
books.add_category(book, category)
found_book = books.find_with_categories(book.id)
@@ -48,8 +50,8 @@
expect(found_category.books).to eq([book])
end
- it 'associates a collection of records' do
- other_book = books.create(title: 'Ontological Engineering')
+ it "associates a collection of records" do
+ other_book = books.create(title: "Ontological Engineering")
categories.add_books(category, book, other_book)
found = categories.find_with_books(category.id)
@@ -57,8 +59,8 @@
end
end
- context '#delete' do
- it 'removes all association information' do
+ context "#delete" do
+ it "removes all association information" do
books.add_category(book, category)
categorized = books.find_with_categories(book.id)
books.clear_categories(book)
@@ -70,8 +72,8 @@
expect(found).to eq(categorized)
end
- it 'does not touch other books' do
- other_book = books.create(title: 'Do not meddle with')
+ it "does not touch other books" do
+ other_book = books.create(title: "Do not meddle with")
books.add_category(other_book, category)
books.add_category(book, category)
@@ -86,9 +88,9 @@
end
end
- context '#remove' do
- it 'removes the desired association' do
- to_remove = books.create(title: 'The Life of a Stoic')
+ context "#remove" do
+ it "removes the desired association" do
+ to_remove = books.create(title: "The Life of a Stoic")
books.add_category(to_remove, category)
categories.remove_book(category, to_remove.id)
@@ -98,35 +100,35 @@
end
end
- context 'collection methods' do
- it 'returns an array of books' do
+ context "collection methods" do
+ it "returns an array of books" do
ontologies.create(book_id: book.id, category_id: category.id)
actual = categories.books_for(category).to_a
expect(actual).to eq([book])
end
- it 'iterates through the categories' do
+ it "iterates through the categories" do
ontologies.create(book_id: book.id, category_id: category.id)
actual = []
categories.books_for(category).each do |book|
- expect(book).to be_an_instance_of(Book)
+ expect(book).to be_a(Project::Entities::Book)
actual << book
end
expect(actual).to eq([book])
end
- it 'iterates through the books and returns an array' do
+ it "iterates through the books and returns an array" do
ontologies.create(book_id: book.id, category_id: category.id)
actual = categories.books_for(category).map(&:id)
expect(actual).to eq([book.id])
end
- it 'returns the count of the associated books' do
- other_book = books.create(title: 'Practical Ontologies for Information Professionals')
+ it "returns the count of the associated books" do
+ other_book = books.create(title: "Practical Ontologies for Information Professionals")
ontologies.create(book_id: book.id, category_id: category.id)
ontologies.create(book_id: other_book.id, category_id: category.id)
@@ -134,8 +136,8 @@
end
end
- context 'raises a Hanami::Model::Error wrapped exception on' do
- it '#add' do
+ xcontext "raises a Hanami::Model::Error wrapped exception on" do
+ it "#add" do
expect do
categories.add_books(category, id: -2)
end.to raise_error Hanami::Model::ForeignKeyConstraintViolationError
diff --git a/spec/integration/hanami/model/associations/relation_alias_spec.rb b/spec/integration/hanami/model/associations/relation_alias_spec.rb
index 35a7e529..e9d443b8 100644
--- a/spec/integration/hanami/model/associations/relation_alias_spec.rb
+++ b/spec/integration/hanami/model/associations/relation_alias_spec.rb
@@ -1,11 +1,13 @@
-RSpec.describe 'Alias (:as) support for associations' do
- let(:users) { UserRepository.new }
- let(:posts) { PostRepository.new }
- let(:comments) { CommentRepository.new }
+# frozen_string_literal: true
- it 'the attribute is named after the association' do
- user = users.create(name: 'Jules Verne')
- post = posts.create(title: 'World Traveling made easy', user_id: user.id)
+RSpec.describe "Alias (:as) support for associations" do
+ let(:users) { UserRepository.new(configuration: configuration) }
+ let(:posts) { PostRepository.new(configuration: configuration) }
+ let(:comments) { CommentRepository.new(configuration: configuration) }
+
+ it "the attribute is named after the association" do
+ user = users.create(name: "Jules Verne")
+ post = posts.create(title: "World Traveling made easy", user_id: user.id)
post_found = posts.find_with_author(post.id)
expect(post_found.author).to eq(user)
@@ -14,10 +16,10 @@
expect(user_found.threads).to match_array([post])
end
- it 'it works with nested aggregates' do
- user = users.create(name: 'Jules Verne')
- post = posts.create(title: 'World Traveling made easy', user_id: user.id)
- commenter = users.create(name: 'Thomas Reid')
+ it "it works with nested aggregates" do
+ user = users.create(name: "Jules Verne")
+ post = posts.create(title: "World Traveling made easy", user_id: user.id)
+ commenter = users.create(name: "Thomas Reid")
comments.create(user_id: commenter.id, post_id: post.id)
found = posts.feed_for(post.id)
@@ -25,11 +27,11 @@
expect(found.comments[0].user).to eq(commenter)
end
- context '#assoc support (calling assoc by the alias)' do
- it 'for #belongs_to' do
- user = users.create(name: 'Jules Verne')
- post = posts.create(title: 'World Traveling made easy', user_id: user.id)
- commenter = users.create(name: 'Thomas Reid')
+ context "#assoc support (calling assoc by the alias)" do
+ it "for #belongs_to" do
+ user = users.create(name: "Jules Verne")
+ post = posts.create(title: "World Traveling made easy", user_id: user.id)
+ commenter = users.create(name: "Thomas Reid")
comment = comments.create(user_id: commenter.id, post_id: post.id)
found_author = posts.author_for(post)
@@ -39,18 +41,18 @@
expect(found_commenter).to eq(commenter)
end
- it 'for #has_many' do
- user = users.create(name: 'Jules Verne')
- post = posts.create(title: 'World Traveling made easy', user_id: user.id)
+ it "for #has_many" do
+ user = users.create(name: "Jules Verne")
+ post = posts.create(title: "World Traveling made easy", user_id: user.id)
found_threads = users.threads_for(user)
expect(found_threads).to match_array [post]
end
- it 'for #has_many :through' do
- user = users.create(name: 'Jules Verne')
- post = posts.create(title: 'World Traveling made easy', user_id: user.id)
- commenter = users.create(name: 'Thomas Reid')
+ it "for #has_many :through" do
+ user = users.create(name: "Jules Verne")
+ post = posts.create(title: "World Traveling made easy", user_id: user.id)
+ commenter = users.create(name: "Thomas Reid")
comments.create(user_id: commenter.id, post_id: post.id)
commenters = posts.commenters_for(post)
diff --git a/spec/integration/hanami/model/migration/mysql.rb b/spec/integration/hanami/model/migration/mysql.rb
index c33b6c7c..c55d961f 100644
--- a/spec/integration/hanami/model/migration/mysql.rb
+++ b/spec/integration/hanami/model/migration/mysql.rb
@@ -1,13 +1,15 @@
-RSpec.shared_examples 'migration_integration_mysql' do
+# frozen_string_literal: true
+
+RSpec.shared_examples "migration_integration_mysql" do
before do
@schema = Pathname.new("#{__dir__}/../../../../../tmp/schema.sql").expand_path
- @connection = Sequel.connect(ENV['HANAMI_DATABASE_URL'])
+ @connection = Sequel.connect(ENV["HANAMI_DATABASE_URL"])
Hanami::Model::Migrator::Adapter.for(Hanami::Model.configuration).dump
end
- describe 'columns' do
- it 'defines column types' do
+ describe "columns" do
+ it "defines column types" do
table = @connection.schema(:column_types)
name, options = table[0]
@@ -16,7 +18,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('int(11)')
+ expect(options.fetch(:db_type)).to eq("int(11)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[1]
@@ -25,7 +27,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('int(11)')
+ expect(options.fetch(:db_type)).to eq("int(11)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[2]
@@ -34,7 +36,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('int(11)')
+ expect(options.fetch(:db_type)).to eq("int(11)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[3]
@@ -43,7 +45,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('varchar(255)')
+ expect(options.fetch(:db_type)).to eq("varchar(255)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[4]
@@ -52,7 +54,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('varchar(3)')
+ expect(options.fetch(:db_type)).to eq("varchar(3)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[5]
@@ -61,7 +63,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('varchar(50)')
+ expect(options.fetch(:db_type)).to eq("varchar(50)")
expect(options.fetch(:max_length)).to eq(50)
expect(options.fetch(:primary_key)).to eq(false)
@@ -71,7 +73,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('char(255)')
+ expect(options.fetch(:db_type)).to eq("char(255)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[7]
@@ -80,7 +82,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('char(64)')
+ expect(options.fetch(:db_type)).to eq("char(64)")
expect(options.fetch(:max_length)).to eq(64)
expect(options.fetch(:primary_key)).to eq(false)
@@ -90,7 +92,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('text')
+ expect(options.fetch(:db_type)).to eq("text")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[9]
@@ -99,7 +101,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:blob)
- expect(options.fetch(:db_type)).to eq('blob')
+ expect(options.fetch(:db_type)).to eq("blob")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[10]
@@ -108,7 +110,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:blob)
- expect(options.fetch(:db_type)).to eq('blob')
+ expect(options.fetch(:db_type)).to eq("blob")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[11]
@@ -117,7 +119,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('int(11)')
+ expect(options.fetch(:db_type)).to eq("int(11)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[12]
@@ -126,7 +128,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('bigint(20)')
+ expect(options.fetch(:db_type)).to eq("bigint(20)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[13]
@@ -135,7 +137,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:float)
- expect(options.fetch(:db_type)).to eq('double')
+ expect(options.fetch(:db_type)).to eq("double")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[14]
@@ -144,7 +146,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('decimal(10,0)')
+ expect(options.fetch(:db_type)).to eq("decimal(10,0)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[15]
@@ -153,7 +155,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
# expect(options.fetch(:type)).to eq(:decimal)
- expect(options.fetch(:db_type)).to eq('decimal(10,0)')
+ expect(options.fetch(:db_type)).to eq("decimal(10,0)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[16]
@@ -162,7 +164,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:decimal)
- expect(options.fetch(:db_type)).to eq('decimal(10,2)')
+ expect(options.fetch(:db_type)).to eq("decimal(10,2)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[17]
@@ -171,7 +173,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('decimal(10,0)')
+ expect(options.fetch(:db_type)).to eq("decimal(10,0)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[18]
@@ -180,7 +182,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:date)
- expect(options.fetch(:db_type)).to eq('date')
+ expect(options.fetch(:db_type)).to eq("date")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[19]
@@ -189,7 +191,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:datetime)
- expect(options.fetch(:db_type)).to eq('datetime')
+ expect(options.fetch(:db_type)).to eq("datetime")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[20]
@@ -198,7 +200,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:datetime)
- expect(options.fetch(:db_type)).to eq('datetime')
+ expect(options.fetch(:db_type)).to eq("datetime")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[21]
@@ -207,7 +209,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:time)
- expect(options.fetch(:db_type)).to eq('time')
+ expect(options.fetch(:db_type)).to eq("time")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[22]
@@ -216,7 +218,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:boolean)
- expect(options.fetch(:db_type)).to eq('tinyint(1)')
+ expect(options.fetch(:db_type)).to eq("tinyint(1)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[23]
@@ -225,105 +227,105 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:boolean)
- expect(options.fetch(:db_type)).to eq('tinyint(1)')
+ expect(options.fetch(:db_type)).to eq("tinyint(1)")
expect(options.fetch(:primary_key)).to eq(false)
end
- it 'defines column defaults' do
+ it "defines column defaults" do
table = @connection.schema(:default_values)
name, options = table[0]
expect(name).to eq(:a)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('23')
+ expect(options.fetch(:default)).to eq("23")
expect(options.fetch(:ruby_default)).to eq(23)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('int(11)')
+ expect(options.fetch(:db_type)).to eq("int(11)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[1]
expect(name).to eq(:b)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('Hanami')
- expect(options.fetch(:ruby_default)).to eq('Hanami')
+ expect(options.fetch(:default)).to eq("Hanami")
+ expect(options.fetch(:ruby_default)).to eq("Hanami")
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('varchar(255)')
+ expect(options.fetch(:db_type)).to eq("varchar(255)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[2]
expect(name).to eq(:c)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('-1')
+ expect(options.fetch(:default)).to eq("-1")
expect(options.fetch(:ruby_default)).to eq(-1)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('int(11)')
+ expect(options.fetch(:db_type)).to eq("int(11)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[3]
expect(name).to eq(:d)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('0')
+ expect(options.fetch(:default)).to eq("0")
expect(options.fetch(:ruby_default)).to eq(0)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('bigint(20)')
+ expect(options.fetch(:db_type)).to eq("bigint(20)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[4]
expect(name).to eq(:e)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('3.14')
+ expect(options.fetch(:default)).to eq("3.14")
expect(options.fetch(:ruby_default)).to eq(3.14)
expect(options.fetch(:type)).to eq(:float)
- expect(options.fetch(:db_type)).to eq('double')
+ expect(options.fetch(:db_type)).to eq("double")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[5]
expect(name).to eq(:f)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('1')
+ expect(options.fetch(:default)).to eq("1")
expect(options.fetch(:ruby_default)).to eq(1.0)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('decimal(10,0)')
+ expect(options.fetch(:db_type)).to eq("decimal(10,0)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[6]
expect(name).to eq(:g)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('943943')
+ expect(options.fetch(:default)).to eq("943943")
expect(options.fetch(:ruby_default)).to eq(943_943)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('decimal(10,0)')
+ expect(options.fetch(:db_type)).to eq("decimal(10,0)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[10]
expect(name).to eq(:k)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('1')
+ expect(options.fetch(:default)).to eq("1")
expect(options.fetch(:ruby_default)).to eq(true)
expect(options.fetch(:type)).to eq(:boolean)
- expect(options.fetch(:db_type)).to eq('tinyint(1)')
+ expect(options.fetch(:db_type)).to eq("tinyint(1)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[11]
expect(name).to eq(:l)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('0')
+ expect(options.fetch(:default)).to eq("0")
expect(options.fetch(:ruby_default)).to eq(false)
expect(options.fetch(:type)).to eq(:boolean)
- expect(options.fetch(:db_type)).to eq('tinyint(1)')
+ expect(options.fetch(:db_type)).to eq("tinyint(1)")
expect(options.fetch(:primary_key)).to eq(false)
end
- it 'defines null constraint' do
+ it "defines null constraint" do
table = @connection.schema(:null_constraints)
name, options = table[0]
@@ -342,7 +344,7 @@
expect(options.fetch(:allow_null)).to eq(true)
end
- it 'defines column index' do
+ it "defines column index" do
indexes = @connection.indexes(:column_indexes)
expect(indexes.fetch(:column_indexes_a_index, nil)).to be_nil
@@ -353,7 +355,7 @@
expect(index[:columns]).to eq([:c])
end
- it 'defines index via #index' do
+ it "defines index via #index" do
indexes = @connection.indexes(:column_indexes)
index = indexes.fetch(:column_indexes_d_index)
@@ -369,7 +371,7 @@
expect(index[:columns]).to eq(%i[lat lng])
end
- it 'defines primary key (via #primary_key :id)' do
+ it "defines primary key (via #primary_key :id)" do
table = @connection.schema(:primary_keys_1)
name, options = table[0]
@@ -378,12 +380,12 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('int(11)')
+ expect(options.fetch(:db_type)).to eq("int(11)")
expect(options.fetch(:primary_key)).to eq(true)
expect(options.fetch(:auto_increment)).to eq(true)
end
- it 'defines composite primary key (via #primary_key [:column1, :column2])' do
+ it "defines composite primary key (via #primary_key [:column1, :column2])" do
table = @connection.schema(:primary_keys_3)
name, options = table[0]
@@ -392,14 +394,14 @@
expect(options.fetch(:allow_null)).to eq(false)
expected = Platform.match do
- ci(:travis) { '0' }
+ ci(:travis) { "0" }
default { nil }
end
expect(options.fetch(:default)).to eq(expected)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('int(11)')
+ expect(options.fetch(:db_type)).to eq("int(11)")
expect(options.fetch(:primary_key)).to eq(true)
expect(options.fetch(:auto_increment)).to eq(false)
@@ -409,19 +411,19 @@
expect(options.fetch(:allow_null)).to eq(false)
expected = Platform.match do
- ci(:travis) { '0' }
+ ci(:travis) { "0" }
default { nil }
end
expect(options.fetch(:default)).to eq(expected)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('int(11)')
+ expect(options.fetch(:db_type)).to eq("int(11)")
expect(options.fetch(:primary_key)).to eq(true)
expect(options.fetch(:auto_increment)).to eq(false)
end
- it 'defines primary key (via #column primary_key: true)' do
+ it "defines primary key (via #column primary_key: true)" do
table = @connection.schema(:primary_keys_2)
name, options = table[0]
@@ -430,12 +432,12 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('varchar(255)')
+ expect(options.fetch(:db_type)).to eq("varchar(255)")
expect(options.fetch(:primary_key)).to eq(true)
expect(options.fetch(:auto_increment)).to eq(false)
end
- it 'defines foreign key (via #foreign_key)' do
+ it "defines foreign key (via #foreign_key)" do
table = @connection.schema(:albums)
name, options = table[1]
@@ -444,7 +446,7 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('int(11)')
+ expect(options.fetch(:db_type)).to eq("int(11)")
expect(options.fetch(:primary_key)).to eq(false)
foreign_key = @connection.foreign_key_list(:albums).first
@@ -455,7 +457,7 @@
# expect(foreign_key.fetch(:on_delete)).to eq(:cascade)
end
- it 'defines column constraint and check'
+ it "defines column constraint and check"
# it 'defines column constraint and check' do
# expect(@schema.read).to include %(CREATE TABLE `table_constraints` (`age` integer, `role` varchar(255), CONSTRAINT `age_constraint` CHECK (`age` > 18), CHECK (role IN("contributor", "manager", "owner")));)
# end
diff --git a/spec/integration/hanami/model/migration/postgresql.rb b/spec/integration/hanami/model/migration/postgresql.rb
index 1922a15f..a4b3c1f6 100644
--- a/spec/integration/hanami/model/migration/postgresql.rb
+++ b/spec/integration/hanami/model/migration/postgresql.rb
@@ -1,13 +1,15 @@
-RSpec.shared_examples 'migration_integration_postgresql' do
+# frozen_string_literal: true
+
+RSpec.shared_examples "migration_integration_postgresql" do
before do
@schema = Pathname.new("#{__dir__}/../../../../../tmp/schema.sql").expand_path
- @connection = Sequel.connect(ENV['HANAMI_DATABASE_URL'])
+ @connection = Sequel.connect(ENV["HANAMI_DATABASE_URL"])
Hanami::Model::Migrator::Adapter.for(Hanami::Model.configuration).dump
end
- describe 'columns' do
- it 'defines column types' do
+ describe "columns" do
+ it "defines column types" do
table = @connection.schema(:column_types)
name, options = table[0]
@@ -16,7 +18,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[1]
@@ -25,7 +27,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[2]
@@ -34,7 +36,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[3]
@@ -43,7 +45,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('text')
+ expect(options.fetch(:db_type)).to eq("text")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[4]
@@ -52,7 +54,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('text')
+ expect(options.fetch(:db_type)).to eq("text")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[5]
@@ -61,7 +63,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('character varying(1)')
+ expect(options.fetch(:db_type)).to eq("character varying(1)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[6]
@@ -70,7 +72,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('character varying(2)')
+ expect(options.fetch(:db_type)).to eq("character varying(2)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[7]
@@ -79,7 +81,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('character(3)')
+ expect(options.fetch(:db_type)).to eq("character(3)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[8]
@@ -88,7 +90,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('character(4)')
+ expect(options.fetch(:db_type)).to eq("character(4)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[9]
@@ -97,7 +99,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('character varying(50)')
+ expect(options.fetch(:db_type)).to eq("character varying(50)")
expect(options.fetch(:max_length)).to eq(50)
expect(options.fetch(:primary_key)).to eq(false)
@@ -107,7 +109,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('character(255)')
+ expect(options.fetch(:db_type)).to eq("character(255)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[11]
@@ -116,7 +118,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('character(64)')
+ expect(options.fetch(:db_type)).to eq("character(64)")
expect(options.fetch(:max_length)).to eq(64)
expect(options.fetch(:primary_key)).to eq(false)
@@ -126,7 +128,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('text')
+ expect(options.fetch(:db_type)).to eq("text")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[13]
@@ -135,7 +137,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:blob)
- expect(options.fetch(:db_type)).to eq('bytea')
+ expect(options.fetch(:db_type)).to eq("bytea")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[14]
@@ -144,7 +146,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:blob)
- expect(options.fetch(:db_type)).to eq('bytea')
+ expect(options.fetch(:db_type)).to eq("bytea")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[15]
@@ -153,7 +155,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[16]
@@ -162,7 +164,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('bigint')
+ expect(options.fetch(:db_type)).to eq("bigint")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[17]
@@ -171,7 +173,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:float)
- expect(options.fetch(:db_type)).to eq('double precision')
+ expect(options.fetch(:db_type)).to eq("double precision")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[18]
@@ -180,7 +182,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:decimal)
- expect(options.fetch(:db_type)).to eq('numeric')
+ expect(options.fetch(:db_type)).to eq("numeric")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[19]
@@ -189,7 +191,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
# expect(options.fetch(:type)).to eq(:decimal)
- expect(options.fetch(:db_type)).to eq('numeric(10,0)')
+ expect(options.fetch(:db_type)).to eq("numeric(10,0)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[20]
@@ -198,7 +200,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:decimal)
- expect(options.fetch(:db_type)).to eq('numeric(10,2)')
+ expect(options.fetch(:db_type)).to eq("numeric(10,2)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[21]
@@ -207,7 +209,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:decimal)
- expect(options.fetch(:db_type)).to eq('numeric')
+ expect(options.fetch(:db_type)).to eq("numeric")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[22]
@@ -216,7 +218,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:date)
- expect(options.fetch(:db_type)).to eq('date')
+ expect(options.fetch(:db_type)).to eq("date")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[23]
@@ -225,7 +227,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:datetime)
- expect(options.fetch(:db_type)).to eq('timestamp without time zone')
+ expect(options.fetch(:db_type)).to eq("timestamp without time zone")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[24]
@@ -234,7 +236,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:datetime)
- expect(options.fetch(:db_type)).to eq('timestamp without time zone')
+ expect(options.fetch(:db_type)).to eq("timestamp without time zone")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[25]
@@ -243,7 +245,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:time)
- expect(options.fetch(:db_type)).to eq('time without time zone')
+ expect(options.fetch(:db_type)).to eq("time without time zone")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[26]
@@ -252,7 +254,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:boolean)
- expect(options.fetch(:db_type)).to eq('boolean')
+ expect(options.fetch(:db_type)).to eq("boolean")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[27]
@@ -261,7 +263,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:boolean)
- expect(options.fetch(:db_type)).to eq('boolean')
+ expect(options.fetch(:db_type)).to eq("boolean")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[28]
@@ -270,7 +272,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer[]')
+ expect(options.fetch(:db_type)).to eq("integer[]")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[29]
@@ -279,7 +281,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer[]')
+ expect(options.fetch(:db_type)).to eq("integer[]")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[30]
@@ -288,7 +290,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('text[]')
+ expect(options.fetch(:db_type)).to eq("text[]")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[31]
@@ -297,7 +299,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
# expect(options.fetch(:type)).to eq(:money)
- expect(options.fetch(:db_type)).to eq('money')
+ expect(options.fetch(:db_type)).to eq("money")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[32]
@@ -306,7 +308,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
# expect(options.fetch(:type)).to eq(:mood)
- expect(options.fetch(:db_type)).to eq('mood')
+ expect(options.fetch(:db_type)).to eq("mood")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[33]
@@ -315,7 +317,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
# expect(options.fetch(:type)).to eq(:point)
- expect(options.fetch(:db_type)).to eq('point')
+ expect(options.fetch(:db_type)).to eq("point")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[34]
@@ -324,7 +326,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
# expect(options.fetch(:type)).to eq(:line)
- expect(options.fetch(:db_type)).to eq('line')
+ expect(options.fetch(:db_type)).to eq("line")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[35]
@@ -333,7 +335,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq("'<(15,15),1>'::circle")
# expect(options.fetch(:type)).to eq(:circle)
- expect(options.fetch(:db_type)).to eq('circle')
+ expect(options.fetch(:db_type)).to eq("circle")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[36]
@@ -342,16 +344,16 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq("'192.168.0.0/24'::cidr")
# expect(options.fetch(:type)).to eq(:cidr)
- expect(options.fetch(:db_type)).to eq('cidr')
+ expect(options.fetch(:db_type)).to eq("cidr")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[37]
expect(name).to eq(:uuid1)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('uuid_generate_v4()')
+ expect(options.fetch(:default)).to eq("uuid_generate_v4()")
# expect(options.fetch(:type)).to eq(:uuid)
- expect(options.fetch(:db_type)).to eq('uuid')
+ expect(options.fetch(:db_type)).to eq("uuid")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[38]
@@ -360,7 +362,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
# expect(options.fetch(:type)).to eq(:xml)
- expect(options.fetch(:db_type)).to eq('xml')
+ expect(options.fetch(:db_type)).to eq("xml")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[39]
@@ -369,7 +371,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
# expect(options.fetch(:type)).to eq(:json)
- expect(options.fetch(:db_type)).to eq('json')
+ expect(options.fetch(:db_type)).to eq("json")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[40]
@@ -378,7 +380,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
# expect(options.fetch(:type)).to eq(:jsonb)
- expect(options.fetch(:db_type)).to eq('jsonb')
+ expect(options.fetch(:db_type)).to eq("jsonb")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[41]
@@ -387,21 +389,21 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq("ROW('fuzzy dice'::text, 42, 1.99)")
# expect(options.fetch(:type)).to eq(:inventory_item)
- expect(options.fetch(:db_type)).to eq('inventory_item')
+ expect(options.fetch(:db_type)).to eq("inventory_item")
expect(options.fetch(:primary_key)).to eq(false)
end
- it 'defines column defaults' do
+ it "defines column defaults" do
table = @connection.schema(:default_values)
name, options = table[0]
expect(name).to eq(:a)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('23')
+ expect(options.fetch(:default)).to eq("23")
expect(options.fetch(:ruby_default)).to eq(23)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[1]
@@ -409,9 +411,9 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq("'Hanami'::text")
- expect(options.fetch(:ruby_default)).to eq('Hanami')
+ expect(options.fetch(:ruby_default)).to eq("Hanami")
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('text')
+ expect(options.fetch(:db_type)).to eq("text")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[2]
@@ -420,7 +422,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expected = Platform.match do
- ci(:travis) { '(-1)' }
+ ci(:travis) { "(-1)" }
default { "'-1'::integer" }
end
@@ -428,71 +430,71 @@
# expect(options.fetch(:ruby_default)).to eq(-1)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[3]
expect(name).to eq(:d)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('0')
+ expect(options.fetch(:default)).to eq("0")
expect(options.fetch(:ruby_default)).to eq(0)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('bigint')
+ expect(options.fetch(:db_type)).to eq("bigint")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[4]
expect(name).to eq(:e)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('3.14')
+ expect(options.fetch(:default)).to eq("3.14")
expect(options.fetch(:ruby_default)).to eq(3.14)
expect(options.fetch(:type)).to eq(:float)
- expect(options.fetch(:db_type)).to eq('double precision')
+ expect(options.fetch(:db_type)).to eq("double precision")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[5]
expect(name).to eq(:f)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('1.0')
+ expect(options.fetch(:default)).to eq("1.0")
expect(options.fetch(:ruby_default)).to eq(1.0)
expect(options.fetch(:type)).to eq(:decimal)
- expect(options.fetch(:db_type)).to eq('numeric')
+ expect(options.fetch(:db_type)).to eq("numeric")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[6]
expect(name).to eq(:g)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('943943')
+ expect(options.fetch(:default)).to eq("943943")
expect(options.fetch(:ruby_default)).to eq(943_943)
expect(options.fetch(:type)).to eq(:decimal)
- expect(options.fetch(:db_type)).to eq('numeric')
+ expect(options.fetch(:db_type)).to eq("numeric")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[10]
expect(name).to eq(:k)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('true')
+ expect(options.fetch(:default)).to eq("true")
expect(options.fetch(:ruby_default)).to eq(true)
expect(options.fetch(:type)).to eq(:boolean)
- expect(options.fetch(:db_type)).to eq('boolean')
+ expect(options.fetch(:db_type)).to eq("boolean")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[11]
expect(name).to eq(:l)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('false')
+ expect(options.fetch(:default)).to eq("false")
expect(options.fetch(:ruby_default)).to eq(false)
expect(options.fetch(:type)).to eq(:boolean)
- expect(options.fetch(:db_type)).to eq('boolean')
+ expect(options.fetch(:db_type)).to eq("boolean")
expect(options.fetch(:primary_key)).to eq(false)
end
- it 'defines null constraint' do
+ it "defines null constraint" do
table = @connection.schema(:null_constraints)
name, options = table[0]
@@ -511,7 +513,7 @@
expect(options.fetch(:allow_null)).to eq(true)
end
- it 'defines column index' do
+ it "defines column index" do
indexes = @connection.indexes(:column_indexes)
expect(indexes.fetch(:column_indexes_a_index, nil)).to be_nil
@@ -522,7 +524,7 @@
expect(index[:columns]).to eq([:c])
end
- it 'defines index via #index' do
+ it "defines index via #index" do
indexes = @connection.indexes(:column_indexes)
index = indexes.fetch(:column_indexes_d_index)
@@ -538,21 +540,22 @@
expect(index[:columns]).to eq(%i[lat lng])
end
- it 'defines primary key (via #primary_key :id)' do
+ it "defines primary key (via #primary_key :id)" do
table = @connection.schema(:primary_keys_1)
name, options = table[0]
expect(name).to eq(:id)
expect(options.fetch(:allow_null)).to eq(false)
- expect(options.fetch(:default)).to eq("nextval('primary_keys_1_id_seq'::regclass)")
+ # FIXME: determine how to assert it's a autoincrement
+ # expect(options.fetch(:default)).to eq("nextval('primary_keys_1_id_seq'::regclass)")
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(true)
expect(options.fetch(:auto_increment)).to eq(true)
end
- it 'defines composite primary key (via #primary_key [:column1, :column2])' do
+ it "defines composite primary key (via #primary_key [:column1, :column2])" do
table = @connection.schema(:primary_keys_3)
name, options = table[0]
@@ -561,7 +564,7 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(true)
expect(options.fetch(:auto_increment)).to eq(false)
@@ -571,12 +574,12 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(true)
expect(options.fetch(:auto_increment)).to eq(false)
end
- it 'defines primary key (via #column primary_key: true)' do
+ it "defines primary key (via #column primary_key: true)" do
table = @connection.schema(:primary_keys_2)
name, options = table[0]
@@ -585,12 +588,12 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('text')
+ expect(options.fetch(:db_type)).to eq("text")
expect(options.fetch(:primary_key)).to eq(true)
expect(options.fetch(:auto_increment)).to eq(false)
end
- it 'defines foreign key (via #foreign_key)' do
+ it "defines foreign key (via #foreign_key)" do
table = @connection.schema(:albums)
name, options = table[1]
@@ -599,7 +602,7 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(false)
foreign_key = @connection.foreign_key_list(:albums).first
@@ -611,7 +614,7 @@
end
unless Platform.ci?
- it 'defines column constraint and check' do
+ it "defines column constraint and check" do
actual = @schema.read
expect(actual).to include %(CONSTRAINT age_constraint CHECK ((age > 18)))
diff --git a/spec/integration/hanami/model/migration/sqlite.rb b/spec/integration/hanami/model/migration/sqlite.rb
index e602efa4..9aacdc3a 100644
--- a/spec/integration/hanami/model/migration/sqlite.rb
+++ b/spec/integration/hanami/model/migration/sqlite.rb
@@ -1,13 +1,15 @@
-RSpec.shared_examples 'migration_integration_sqlite' do
+# frozen_string_literal: true
+
+RSpec.shared_examples "migration_integration_sqlite" do
before do
@schema = Pathname.new("#{__dir__}/../../../../../tmp/schema.sql").expand_path
- @connection = Sequel.connect(ENV['HANAMI_DATABASE_URL'])
+ @connection = Sequel.connect(ENV["HANAMI_DATABASE_URL"])
Hanami::Model::Migrator::Adapter.for(Hanami::Model.configuration).dump
end
- describe 'columns' do
- it 'defines column types' do
+ describe "columns" do
+ it "defines column types" do
table = @connection.schema(:column_types)
name, options = table[0]
@@ -16,7 +18,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[1]
@@ -25,7 +27,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[2]
@@ -34,7 +36,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[3]
@@ -43,7 +45,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('varchar(255)')
+ expect(options.fetch(:db_type)).to eq("varchar(255)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[4]
@@ -52,7 +54,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('string')
+ expect(options.fetch(:db_type)).to eq("string")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[5]
@@ -61,7 +63,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('string')
+ expect(options.fetch(:db_type)).to eq("string")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[6]
@@ -70,7 +72,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('varchar(3)')
+ expect(options.fetch(:db_type)).to eq("varchar(3)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[7]
@@ -79,7 +81,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('varchar(50)')
+ expect(options.fetch(:db_type)).to eq("varchar(50)")
expect(options.fetch(:max_length)).to eq(50)
expect(options.fetch(:primary_key)).to eq(false)
@@ -89,7 +91,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('char(255)')
+ expect(options.fetch(:db_type)).to eq("char(255)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[9]
@@ -98,7 +100,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('char(64)')
+ expect(options.fetch(:db_type)).to eq("char(64)")
expect(options.fetch(:max_length)).to eq(64)
expect(options.fetch(:primary_key)).to eq(false)
@@ -108,7 +110,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('text')
+ expect(options.fetch(:db_type)).to eq("text")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[11]
@@ -117,7 +119,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:blob)
- expect(options.fetch(:db_type)).to eq('blob')
+ expect(options.fetch(:db_type)).to eq("blob")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[12]
@@ -126,7 +128,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:blob)
- expect(options.fetch(:db_type)).to eq('blob')
+ expect(options.fetch(:db_type)).to eq("blob")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[13]
@@ -135,7 +137,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[14]
@@ -144,7 +146,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('bigint')
+ expect(options.fetch(:db_type)).to eq("bigint")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[15]
@@ -153,7 +155,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:float)
- expect(options.fetch(:db_type)).to eq('double precision')
+ expect(options.fetch(:db_type)).to eq("double precision")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[16]
@@ -162,7 +164,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:decimal)
- expect(options.fetch(:db_type)).to eq('numeric')
+ expect(options.fetch(:db_type)).to eq("numeric")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[17]
@@ -171,7 +173,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
# expect(options.fetch(:type)).to eq(:decimal)
- expect(options.fetch(:db_type)).to eq('numeric(10)')
+ expect(options.fetch(:db_type)).to eq("numeric(10)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[18]
@@ -180,7 +182,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:decimal)
- expect(options.fetch(:db_type)).to eq('numeric(10, 2)')
+ expect(options.fetch(:db_type)).to eq("numeric(10, 2)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[19]
@@ -189,7 +191,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:decimal)
- expect(options.fetch(:db_type)).to eq('numeric')
+ expect(options.fetch(:db_type)).to eq("numeric")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[20]
@@ -198,7 +200,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:date)
- expect(options.fetch(:db_type)).to eq('date')
+ expect(options.fetch(:db_type)).to eq("date")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[21]
@@ -207,7 +209,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:datetime)
- expect(options.fetch(:db_type)).to eq('timestamp')
+ expect(options.fetch(:db_type)).to eq("timestamp")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[22]
@@ -216,7 +218,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:datetime)
- expect(options.fetch(:db_type)).to eq('timestamp')
+ expect(options.fetch(:db_type)).to eq("timestamp")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[23]
@@ -225,7 +227,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:time)
- expect(options.fetch(:db_type)).to eq('time')
+ expect(options.fetch(:db_type)).to eq("time")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[24]
@@ -234,7 +236,7 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:boolean)
- expect(options.fetch(:db_type)).to eq('boolean')
+ expect(options.fetch(:db_type)).to eq("boolean")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[25]
@@ -243,21 +245,21 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:boolean)
- expect(options.fetch(:db_type)).to eq('boolean')
+ expect(options.fetch(:db_type)).to eq("boolean")
expect(options.fetch(:primary_key)).to eq(false)
end
- it 'defines column defaults' do
+ it "defines column defaults" do
table = @connection.schema(:default_values)
name, options = table[0]
expect(name).to eq(:a)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('23')
+ expect(options.fetch(:default)).to eq("23")
expect(options.fetch(:ruby_default)).to eq(23)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[1]
@@ -265,83 +267,83 @@
expect(options.fetch(:allow_null)).to eq(true)
expect(options.fetch(:default)).to eq("'Hanami'")
- expect(options.fetch(:ruby_default)).to eq('Hanami')
+ expect(options.fetch(:ruby_default)).to eq("Hanami")
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('varchar(255)')
+ expect(options.fetch(:db_type)).to eq("varchar(255)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[2]
expect(name).to eq(:c)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('-1')
+ expect(options.fetch(:default)).to eq("-1")
expect(options.fetch(:ruby_default)).to eq(-1)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[3]
expect(name).to eq(:d)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('0')
+ expect(options.fetch(:default)).to eq("0")
expect(options.fetch(:ruby_default)).to eq(0)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('bigint')
+ expect(options.fetch(:db_type)).to eq("bigint")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[4]
expect(name).to eq(:e)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('3.14')
+ expect(options.fetch(:default)).to eq("3.14")
expect(options.fetch(:ruby_default)).to eq(3.14)
expect(options.fetch(:type)).to eq(:float)
- expect(options.fetch(:db_type)).to eq('double precision')
+ expect(options.fetch(:db_type)).to eq("double precision")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[5]
expect(name).to eq(:f)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('1.0')
+ expect(options.fetch(:default)).to eq("1.0")
expect(options.fetch(:ruby_default)).to eq(1.0)
expect(options.fetch(:type)).to eq(:decimal)
- expect(options.fetch(:db_type)).to eq('numeric')
+ expect(options.fetch(:db_type)).to eq("numeric")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[6]
expect(name).to eq(:g)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('943943')
+ expect(options.fetch(:default)).to eq("943943")
expect(options.fetch(:ruby_default)).to eq(943_943)
expect(options.fetch(:type)).to eq(:decimal)
- expect(options.fetch(:db_type)).to eq('numeric')
+ expect(options.fetch(:db_type)).to eq("numeric")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[10]
expect(name).to eq(:k)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('1')
+ expect(options.fetch(:default)).to eq("1")
expect(options.fetch(:ruby_default)).to eq(true)
expect(options.fetch(:type)).to eq(:boolean)
- expect(options.fetch(:db_type)).to eq('boolean')
+ expect(options.fetch(:db_type)).to eq("boolean")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[11]
expect(name).to eq(:l)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('0')
+ expect(options.fetch(:default)).to eq("0")
expect(options.fetch(:ruby_default)).to eq(false)
expect(options.fetch(:type)).to eq(:boolean)
- expect(options.fetch(:db_type)).to eq('boolean')
+ expect(options.fetch(:db_type)).to eq("boolean")
expect(options.fetch(:primary_key)).to eq(false)
end
- it 'defines null constraint' do
+ it "defines null constraint" do
table = @connection.schema(:null_constraints)
name, options = table[0]
@@ -360,7 +362,7 @@
expect(options.fetch(:allow_null)).to eq(true)
end
- it 'defines column index' do
+ it "defines column index" do
indexes = @connection.indexes(:column_indexes)
expect(indexes.fetch(:column_indexes_a_index, nil)).to be_nil
@@ -371,7 +373,7 @@
expect(index[:columns]).to eq([:c])
end
- it 'defines index via #index' do
+ it "defines index via #index" do
indexes = @connection.indexes(:column_indexes)
index = indexes.fetch(:column_indexes_d_index)
@@ -387,7 +389,7 @@
expect(index[:columns]).to eq(%i[lat lng])
end
- it 'defines primary key (via #primary_key :id)' do
+ it "defines primary key (via #primary_key :id)" do
table = @connection.schema(:primary_keys_1)
name, options = table[0]
@@ -396,12 +398,12 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(true)
expect(options.fetch(:auto_increment)).to eq(true)
end
- it 'defines composite primary key (via #primary_key [:column1, :column2])' do
+ it "defines composite primary key (via #primary_key [:column1, :column2])" do
table = @connection.schema(:primary_keys_3)
name, options = table[0]
@@ -410,7 +412,7 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(true)
expect(options.fetch(:auto_increment)).to eq(false)
@@ -420,12 +422,12 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(true)
expect(options.fetch(:auto_increment)).to eq(false)
end
- it 'defines primary key (via #column primary_key: true)' do
+ it "defines primary key (via #column primary_key: true)" do
table = @connection.schema(:primary_keys_2)
name, options = table[0]
@@ -434,12 +436,12 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('varchar(255)')
+ expect(options.fetch(:db_type)).to eq("varchar(255)")
expect(options.fetch(:primary_key)).to eq(true)
expect(options.fetch(:auto_increment)).to eq(false)
end
- it 'defines foreign key (via #foreign_key)' do
+ it "defines foreign key (via #foreign_key)" do
table = @connection.schema(:albums)
name, options = table[1]
@@ -448,7 +450,7 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to eq(nil)
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(false)
foreign_key = @connection.foreign_key_list(:albums).first
@@ -459,7 +461,7 @@
expect(foreign_key.fetch(:on_delete)).to eq(:cascade)
end
- it 'defines column constraint and check' do
+ it "defines column constraint and check" do
expect(@schema.read).to include %(CREATE TABLE `table_constraints` (`age` integer, `role` varchar(255), CONSTRAINT `age_constraint` CHECK (`age` > 18), CHECK (role IN("contributor", "manager", "owner")));)
end
end
diff --git a/spec/integration/hanami/model/migration_spec.rb b/spec/integration/hanami/model/migration_spec.rb
index d2d1b49d..fbb02264 100644
--- a/spec/integration/hanami/model/migration_spec.rb
+++ b/spec/integration/hanami/model/migration_spec.rb
@@ -1,5 +1,7 @@
+# frozen_string_literal: true
+
require_relative "./migration/#{Database.engine}.rb"
-RSpec.describe 'Hanami::Model.migration' do
+RSpec.describe "Hanami::Model.migration" do
include_examples "migration_integration_#{Database.engine}"
end
diff --git a/spec/integration/hanami/model/repository/base_spec.rb b/spec/integration/hanami/model/repository/base_spec.rb
index f70e68a0..080f8938 100644
--- a/spec/integration/hanami/model/repository/base_spec.rb
+++ b/spec/integration/hanami/model/repository/base_spec.rb
@@ -1,42 +1,44 @@
-require 'securerandom'
+# frozen_string_literal: true
-RSpec.describe 'Repository (base)' do
+require "securerandom"
+
+RSpec.describe "Repository (base)" do
extend PlatformHelpers
- describe '#find' do
- it 'finds record by primary key' do
- repository = UserRepository.new
- user = repository.create(name: 'L')
+ describe "#find" do
+ it "finds record by primary key" do
+ repository = UserRepository.new(configuration: configuration)
+ user = repository.create(name: "L")
found = repository.find(user.id)
expect(found).to eq(user)
end
- it 'returns nil when nil is given' do
- repository = UserRepository.new
- repository.create(name: 'L')
+ it "returns nil when nil is given" do
+ repository = UserRepository.new(configuration: configuration)
+ repository.create(name: "L")
found = repository.find(nil)
expect(found).to be_nil
end
- it 'returns nil for missing record' do
- repository = UserRepository.new
- found = repository.find('9999999')
+ it "returns nil for missing record" do
+ repository = UserRepository.new(configuration: configuration)
+ found = repository.find("9999999")
expect(found).to be_nil
end
# See https://github.com/hanami/model/issues/374
- describe 'with non-autoincrement primary key' do
+ describe "with non-autoincrement primary key" do
before do
repository.clear
end
- let(:repository) { LabelRepository.new }
+ let(:repository) { LabelRepository.new(configuration: configuration) }
let(:id) { 1 }
- it 'raises error' do
+ it "raises error" do
repository.create(id: id)
expect { repository.find(id) }
@@ -45,9 +47,9 @@
end
# See https://github.com/hanami/model/issues/399
- describe 'with custom relation' do
- it 'finds record by primary key' do
- repository = AccessTokenRepository.new
+ describe "with custom relation" do
+ it "finds record by primary key" do
+ repository = AccessTokenRepository.new(configuration: configuration)
access_token = repository.create(token: "123")
found = repository.find(access_token.id)
@@ -56,168 +58,168 @@
end
end
- describe '#all' do
- it 'returns all the records' do
- repository = UserRepository.new
- user = repository.create(name: 'L')
+ describe "#all" do
+ it "returns all the records" do
+ repository = UserRepository.new(configuration: configuration)
+ user = repository.create(name: "L")
- expect(repository.all).to be_an_instance_of(Array)
+ expect(repository.all).to be_an(Array)
expect(repository.all).to include(user)
end
end
- describe '#first' do
- it 'returns first record from table' do
- repository = UserRepository.new
+ describe "#first" do
+ it "returns first record from table" do
+ repository = UserRepository.new(configuration: configuration)
repository.clear
- user = repository.create(name: 'James Hetfield')
- repository.create(name: 'Tom')
+ user = repository.create(name: "James Hetfield")
+ repository.create(name: "Tom")
expect(repository.first).to eq(user)
end
end
- describe '#last' do
- it 'returns last record from table' do
- repository = UserRepository.new
+ describe "#last" do
+ it "returns last record from table" do
+ repository = UserRepository.new(configuration: configuration)
repository.clear
- repository.create(name: 'Tom')
- user = repository.create(name: 'Ella Fitzgerald')
+ repository.create(name: "Tom")
+ user = repository.create(name: "Ella Fitzgerald")
expect(repository.last).to eq(user)
end
end
# https://github.com/hanami/model/issues/473
- describe 'querying' do
- it 'allows to access relation attributes via square bracket syntax' do
- repository = UserRepository.new
+ describe "querying" do
+ it "allows to access relation attributes via square bracket syntax" do
+ repository = UserRepository.new(configuration: configuration)
repository.clear
- expected = [repository.create(name: 'Ella'),
- repository.create(name: 'Bella')]
- repository.create(name: 'Jon')
+ expected = [repository.create(name: "Ella"),
+ repository.create(name: "Bella")]
+ repository.create(name: "Jon")
- actual = repository.by_matching_name('%ella%')
+ actual = repository.by_matching_name("%ella%")
expect(actual).to eq(expected)
end
end
- describe '#clear' do
- it 'clears all the records' do
- repository = UserRepository.new
- repository.create(name: 'L')
+ describe "#clear" do
+ it "clears all the records" do
+ repository = UserRepository.new(configuration: configuration)
+ repository.create(name: "L")
repository.clear
expect(repository.all).to be_empty
end
end
- describe 'relation' do
- describe 'read' do
- it 'reads records from the database given a raw query string' do
- repository = UserRepository.new
- repository.create(name: 'L')
+ describe "relation" do
+ describe "read" do
+ it "reads records from the database given a raw query string" do
+ repository = UserRepository.new(configuration: configuration)
+ repository.create(name: "L")
users = repository.find_all_by_manual_query
expect(users).to be_a_kind_of(Array)
user = users.first
- expect(user).to be_a_kind_of(User)
+ expect(user).to be_a_kind_of(Project::Entities::User)
end
end
end
- describe '#create' do
- it 'creates record from data' do
- repository = UserRepository.new
- user = repository.create(name: 'L')
+ describe "#create" do
+ it "creates record from data" do
+ repository = UserRepository.new(configuration: configuration)
+ user = repository.create(name: "L")
- expect(user).to be_an_instance_of(User)
+ expect(user).to be_a(Project::Entities::User)
expect(user.id).to_not be_nil
- expect(user.name).to eq('L')
+ expect(user.name).to eq("L")
end
- it 'creates record from entity' do
- entity = User.new(name: 'L')
- repository = UserRepository.new
+ xit "creates record from entity" do
+ entity = Project::Entities::User.new(name: "L")
+ repository = UserRepository.new(configuration: configuration)
user = repository.create(entity)
# It doesn't mutate original entity
expect(entity.id).to be_nil
- expect(user).to be_an_instance_of(User)
+ expect(user).to be_a(User)
expect(user.id).to_not be_nil
- expect(user.name).to eq('L')
+ expect(user.name).to eq("L")
end
with_platform(engine: :jruby, db: :sqlite) do
- it 'automatically touches timestamps'
+ it "automatically touches timestamps"
end
unless_platform(engine: :jruby, db: :sqlite) do
- it 'automatically touches timestamps' do
- repository = UserRepository.new
- user = repository.create(name: 'L')
+ it "automatically touches timestamps" do
+ repository = UserRepository.new(configuration: configuration)
+ user = repository.create(name: "L")
expect(user.created_at).to be_within(2).of(Time.now.utc)
expect(user.updated_at).to be_within(2).of(Time.now.utc)
end
- it 'respects given timestamps' do
- repository = UserRepository.new
- given_time = Time.new(2010, 1, 1, 12, 0, 0, '+00:00')
+ it "respects given timestamps" do
+ repository = UserRepository.new(configuration: configuration)
+ given_time = Time.new(2010, 1, 1, 12, 0, 0, "+00:00")
- user = repository.create(name: 'L', created_at: given_time, updated_at: given_time)
+ user = repository.create(name: "L", created_at: given_time, updated_at: given_time)
expect(user.created_at).to be_within(2).of(given_time)
expect(user.updated_at).to be_within(2).of(given_time)
end
- it 'can update timestamps' do
- repository = UserRepository.new
- user = repository.create(name: 'L')
+ it "can update timestamps" do
+ repository = UserRepository.new(configuration: configuration)
+ user = repository.create(name: "L")
expect(user.created_at).to be_within(2).of(Time.now.utc)
expect(user.updated_at).to be_within(2).of(Time.now.utc)
- given_time = Time.new(2010, 1, 1, 12, 0, 0, '+00:00')
+ given_time = Time.new(2010, 1, 1, 12, 0, 0, "+00:00")
updated = repository.update(
user.id,
created_at: given_time,
updated_at: given_time
)
- expect(updated.name).to eq('L')
+ expect(updated.name).to eq("L")
expect(updated.created_at).to be_within(2).of(given_time)
expect(updated.updated_at).to be_within(2).of(given_time)
end
# Bug: https://github.com/hanami/model/issues/412
- it 'can have only creation timestamp' do
- user = UserRepository.new.create(name: 'L')
- repository = AvatarRepository.new
- account = repository.create(url: 'http://foo.com', user_id: user.id)
+ it "can have only creation timestamp" do
+ user = UserRepository.new(configuration: configuration).create(name: "L")
+ repository = AvatarRepository.new(configuration: configuration)
+ account = repository.create(url: "http://foo.com", user_id: user.id)
expect(account.created_at).to be_within(2).of(Time.now.utc)
end
end
# Bug: https://github.com/hanami/model/issues/237
- it 'respects database defaults' do
- repository = UserRepository.new
- user = repository.create(name: 'L')
+ it "respects database defaults" do
+ repository = UserRepository.new(configuration: configuration)
+ user = repository.create(name: "L")
expect(user.comments_count).to eq(0)
end
# Bug: https://github.com/hanami/model/issues/272
- it 'accepts booleans as attributes' do
- user = UserRepository.new.create(name: 'L', active: false)
+ it "accepts booleans as attributes" do
+ user = UserRepository.new(configuration: configuration).create(name: "L", active: false)
expect(user.active).to eq(false)
end
- it 'raises error when generic database error is raised'
+ it "raises error when generic database error is raised"
# it 'raises error when generic database error is raised' do
# expected_error = Hanami::Model::DatabaseError
# message = Platform.match do
@@ -231,7 +233,7 @@
# engine(:jruby).db(:mysql) { 'bogus' }
# end
- # expect { UserRepository.new.create(name: 'L', bogus: 23) }.to raise_error do |error|
+ # expect { UserRepository.new(configuration: configuration).create(name: 'L', bogus: 23) }.to raise_error do |error|
# expect(error).to be_a(expected_error)
# expect(error.message).to include(message)
# end
@@ -240,8 +242,8 @@
it 'raises error when "not null" database constraint is violated' do
expected_error = Hanami::Model::NotNullConstraintViolationError
message = Platform.match do
- engine(:ruby).db(:sqlite) { 'SQLite3::ConstraintException' }
- engine(:jruby).db(:sqlite) { 'Java::OrgSqlite::SQLiteException: [SQLITE_CONSTRAINT_NOTNULL] A NOT NULL constraint failed (NOT NULL constraint failed: users.active)' }
+ engine(:ruby).db(:sqlite) { "SQLite3::ConstraintException" }
+ engine(:jruby).db(:sqlite) { "Java::OrgSqlite::SQLiteException: [SQLITE_CONSTRAINT_NOTNULL] A NOT NULL constraint failed (NOT NULL constraint failed: users.active)" }
engine(:ruby).db(:postgresql) { 'PG::NotNullViolation: ERROR: null value in column "active" violates not-null constraint' }
engine(:jruby).db(:postgresql) { 'Java::OrgPostgresqlUtil::PSQLException: ERROR: null value in column "active" violates not-null constraint' }
@@ -250,7 +252,7 @@
engine(:jruby).db(:mysql) { "Java::ComMysqlJdbcExceptionsJdbc4::MySQLIntegrityConstraintViolationException: Column 'active' cannot be null" }
end
- expect { UserRepository.new.create(name: 'L', active: nil) }.to raise_error do |error|
+ expect { UserRepository.new(configuration: configuration).create(name: "L", active: nil) }.to raise_error do |error|
expect(error).to be_a(expected_error)
expect(error.message).to include(message)
end
@@ -261,8 +263,8 @@
expected_error = Hanami::Model::UniqueConstraintViolationError
message = Platform.match do
- engine(:ruby).db(:sqlite) { 'SQLite3::ConstraintException' }
- engine(:jruby).db(:sqlite) { 'Java::OrgSqlite::SQLiteException: [SQLITE_CONSTRAINT_UNIQUE] A UNIQUE constraint failed (UNIQUE constraint failed: users.email)' }
+ engine(:ruby).db(:sqlite) { "SQLite3::ConstraintException" }
+ engine(:jruby).db(:sqlite) { "Java::OrgSqlite::SQLiteException: [SQLITE_CONSTRAINT_UNIQUE] A UNIQUE constraint failed (UNIQUE constraint failed: users.email)" }
engine(:ruby).db(:postgresql) { 'PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "users_email_index"' }
engine(:jruby).db(:postgresql) { %(Java::OrgPostgresqlUtil::PSQLException: ERROR: duplicate key value violates unique constraint "users_email_index"\n Detail: Key (email)=(#{email}) already exists.) }
@@ -271,10 +273,10 @@
engine(:jruby).db(:mysql) { "Java::ComMysqlJdbcExceptionsJdbc4::MySQLIntegrityConstraintViolationException: Duplicate entry '#{email}' for key 'users_email_index'" }
end
- repository = UserRepository.new
- repository.create(name: 'Test', email: email)
+ repository = UserRepository.new(configuration: configuration)
+ repository.create(name: "Test", email: email)
- expect { repository.create(name: 'L', email: email) }.to raise_error do |error|
+ expect { repository.create(name: "L", email: email) }.to raise_error do |error|
expect(error).to be_a(expected_error)
expect(error.message).to include(message)
end
@@ -283,17 +285,17 @@
it 'raises error when "foreign key" constraint is violated' do
expected_error = Hanami::Model::ForeignKeyConstraintViolationError
message = Platform.match do
- engine(:ruby).db(:sqlite) { 'SQLite3::ConstraintException' }
- engine(:jruby).db(:sqlite) { 'Java::OrgSqlite::SQLiteException: [SQLITE_CONSTRAINT_FOREIGNKEY] A foreign key constraint failed (FOREIGN KEY constraint failed)' }
+ engine(:ruby).db(:sqlite) { "SQLite3::ConstraintException" }
+ engine(:jruby).db(:sqlite) { "Java::OrgSqlite::SQLiteException: [SQLITE_CONSTRAINT_FOREIGNKEY] A foreign key constraint failed (FOREIGN KEY constraint failed)" }
engine(:ruby).db(:postgresql) { 'PG::ForeignKeyViolation: ERROR: insert or update on table "avatars" violates foreign key constraint "avatars_user_id_fkey"' }
engine(:jruby).db(:postgresql) { 'Java::OrgPostgresqlUtil::PSQLException: ERROR: insert or update on table "avatars" violates foreign key constraint "avatars_user_id_fkey"' }
- engine(:ruby).db(:mysql) { 'Mysql2::Error: Cannot add or update a child row: a foreign key constraint fails' }
- engine(:jruby).db(:mysql) { 'Java::ComMysqlJdbcExceptionsJdbc4::MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`hanami_model`.`avatars`, CONSTRAINT `avatars_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE)' }
+ engine(:ruby).db(:mysql) { "Mysql2::Error: Cannot add or update a child row: a foreign key constraint fails" }
+ engine(:jruby).db(:mysql) { "Java::ComMysqlJdbcExceptionsJdbc4::MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`hanami_model`.`avatars`, CONSTRAINT `avatars_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE)" }
end
- expect { AvatarRepository.new.create(user_id: 999_999_999, url: 'url') }.to raise_error do |error|
+ expect { AvatarRepository.new(configuration: configuration).create(user_id: 999_999_999, url: "url") }.to raise_error do |error|
expect(error).to be_a(expected_error)
expect(error.message).to include(message)
end
@@ -306,31 +308,31 @@
expected = Hanami::Model::CheckConstraintViolationError
message = Platform.match do
- engine(:ruby).db(:sqlite) { 'SQLite3::ConstraintException: CHECK constraint failed' }
- engine(:jruby).db(:sqlite) { 'Java::OrgSqlite::SQLiteException: [SQLITE_CONSTRAINT_CHECK] A CHECK constraint failed (CHECK constraint failed: users)' }
+ engine(:ruby).db(:sqlite) { "SQLite3::ConstraintException: CHECK constraint failed" }
+ engine(:jruby).db(:sqlite) { "Java::OrgSqlite::SQLiteException: [SQLITE_CONSTRAINT_CHECK] A CHECK constraint failed (CHECK constraint failed: users)" }
engine(:ruby).db(:postgresql) { 'PG::CheckViolation: ERROR: new row for relation "users" violates check constraint "users_age_check"' }
engine(:jruby).db(:postgresql) { 'Java::OrgPostgresqlUtil::PSQLException: ERROR: new row for relation "users" violates check constraint "users_age_check"' }
end
- expect { UserRepository.new.create(name: 'L', age: 1) }.to raise_error do |error|
+ expect { UserRepository.new(configuration: configuration).create(name: "L", age: 1) }.to raise_error do |error|
expect(error).to be_a(expected)
expect(error.message).to include(message)
end
end
- it 'raises error when constraint is violated' do
+ it "raises error when constraint is violated" do
expected = Hanami::Model::CheckConstraintViolationError
message = Platform.match do
- engine(:ruby).db(:sqlite) { 'SQLite3::ConstraintException: CHECK constraint failed' }
- engine(:jruby).db(:sqlite) { 'Java::OrgSqlite::SQLiteException: [SQLITE_CONSTRAINT_CHECK] A CHECK constraint failed (CHECK constraint failed: comments_count_constraint)' }
+ engine(:ruby).db(:sqlite) { "SQLite3::ConstraintException: CHECK constraint failed" }
+ engine(:jruby).db(:sqlite) { "Java::OrgSqlite::SQLiteException: [SQLITE_CONSTRAINT_CHECK] A CHECK constraint failed (CHECK constraint failed: comments_count_constraint)" }
engine(:ruby).db(:postgresql) { 'PG::CheckViolation: ERROR: new row for relation "users" violates check constraint "comments_count_constraint"' }
engine(:jruby).db(:postgresql) { 'Java::OrgPostgresqlUtil::PSQLException: ERROR: new row for relation "users" violates check constraint "comments_count_constraint"' }
end
- expect { UserRepository.new.create(name: 'L', comments_count: -1) }.to raise_error do |error|
+ expect { UserRepository.new(configuration: configuration).create(name: "L", comments_count: -1) }.to raise_error do |error|
expect(error).to be_a(expected)
expect(error.message).to include(message)
end
@@ -338,55 +340,55 @@
end
end
- describe '#update' do
- it 'updates record from data' do
- repository = UserRepository.new
- user = repository.create(name: 'L')
- updated = repository.update(user.id, name: 'Luca')
+ describe "#update" do
+ it "updates record from data" do
+ repository = UserRepository.new(configuration: configuration)
+ user = repository.create(name: "L")
+ updated = repository.update(user.id, name: "Luca")
- expect(updated).to be_an_instance_of(User)
+ expect(updated).to be_a(Project::Entities::User)
expect(updated.id).to eq(user.id)
- expect(updated.name).to eq('Luca')
+ expect(updated.name).to eq("Luca")
end
- it 'updates record from entity' do
- entity = User.new(name: 'Luca')
- repository = UserRepository.new
- user = repository.create(name: 'L')
+ xit "updates record from entity" do
+ entity = Project::Entities::User.new(name: "Luca")
+ repository = UserRepository.new(configuration: configuration)
+ user = repository.create(name: "L")
updated = repository.update(user.id, entity)
# It doesn't mutate original entity
expect(entity.id).to be_nil
- expect(updated).to be_an_instance_of(User)
+ expect(updated).to be_a(User)
expect(updated.id).to eq(user.id)
- expect(updated.name).to eq('Luca')
+ expect(updated.name).to eq("Luca")
end
- it 'returns nil when record cannot be found' do
- repository = UserRepository.new
- updated = repository.update('9999999', name: 'Luca')
+ it "returns nil when record cannot be found" do
+ repository = UserRepository.new(configuration: configuration)
+ updated = repository.update("9999999", name: "Luca")
expect(updated).to be_nil
end
with_platform(engine: :jruby, db: :sqlite) do
- it 'automatically touches timestamps'
+ it "automatically touches timestamps"
end
unless_platform(engine: :jruby, db: :sqlite) do
- it 'automatically touches timestamps' do
- repository = UserRepository.new
- user = repository.create(name: 'L')
+ it "automatically touches timestamps" do
+ repository = UserRepository.new(configuration: configuration)
+ user = repository.create(name: "L")
sleep 0.1
- updated = repository.update(user.id, name: 'Luca')
+ updated = repository.update(user.id, name: "Luca")
expect(updated.created_at).to be_within(2).of(user.created_at)
expect(updated.updated_at).to be_within(2).of(Time.now)
end
end
- it 'raises error when generic database error is raised'
+ it "raises error when generic database error is raised"
# it 'raises error when generic database error is raised' do
# expected_error = Hanami::Model::DatabaseError
# message = Platform.match do
@@ -400,7 +402,7 @@
# engine(:jruby).db(:mysql) { 'bogus' }
# end
- # repository = UserRepository.new
+ # repository = UserRepository.new(configuration: configuration)
# user = repository.create(name: 'L')
# expect { repository.update(user.id, bogus: 23) }.to raise_error do |error|
@@ -414,8 +416,8 @@
it 'raises error when "not null" database constraint is violated' do
expected_error = Hanami::Model::NotNullConstraintViolationError
message = Platform.match do
- engine(:ruby).db(:sqlite) { 'SQLite3::ConstraintException' }
- engine(:jruby).db(:sqlite) { 'Java::OrgSqlite::SQLiteException: [SQLITE_CONSTRAINT_NOTNULL] A NOT NULL constraint failed (NOT NULL constraint failed: users.active)' }
+ engine(:ruby).db(:sqlite) { "SQLite3::ConstraintException" }
+ engine(:jruby).db(:sqlite) { "Java::OrgSqlite::SQLiteException: [SQLITE_CONSTRAINT_NOTNULL] A NOT NULL constraint failed (NOT NULL constraint failed: users.active)" }
engine(:ruby).db(:postgresql) { 'PG::NotNullViolation: ERROR: null value in column "active" violates not-null constraint' }
engine(:jruby).db(:postgresql) { 'Java::OrgPostgresqlUtil::PSQLException: ERROR: null value in column "active" violates not-null constraint' }
@@ -424,8 +426,8 @@
engine(:jruby).db(:mysql) { "Java::ComMysqlJdbcExceptionsJdbc4::MySQLIntegrityConstraintViolationException: Column 'active' cannot be null" }
end
- repository = UserRepository.new
- user = repository.create(name: 'L')
+ repository = UserRepository.new(configuration: configuration)
+ user = repository.create(name: "L")
expect { repository.update(user.id, active: nil) }.to raise_error do |error|
expect(error).to be_a(expected_error)
@@ -439,8 +441,8 @@
expected_error = Hanami::Model::UniqueConstraintViolationError
message = Platform.match do
- engine(:ruby).db(:sqlite) { 'SQLite3::ConstraintException' }
- engine(:jruby).db(:sqlite) { 'Java::OrgSqlite::SQLiteException: [SQLITE_CONSTRAINT_UNIQUE] A UNIQUE constraint failed (UNIQUE constraint failed: users.email)' }
+ engine(:ruby).db(:sqlite) { "SQLite3::ConstraintException" }
+ engine(:jruby).db(:sqlite) { "Java::OrgSqlite::SQLiteException: [SQLITE_CONSTRAINT_UNIQUE] A UNIQUE constraint failed (UNIQUE constraint failed: users.email)" }
engine(:ruby).db(:postgresql) { 'PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "users_email_index"' }
engine(:jruby).db(:postgresql) { 'Java::OrgPostgresqlUtil::PSQLException: ERROR: duplicate key value violates unique constraint "users_email_index"' }
@@ -449,9 +451,9 @@
engine(:jruby).db(:mysql) { "Java::ComMysqlJdbcExceptionsJdbc4::MySQLIntegrityConstraintViolationException: Duplicate entry '#{email}' for key 'users_email_index'" }
end
- repository = UserRepository.new
- user = repository.create(name: 'L')
- repository.create(name: 'UpdateTest', email: email)
+ repository = UserRepository.new(configuration: configuration)
+ user = repository.create(name: "L")
+ repository.create(name: "UpdateTest", email: email)
expect { repository.update(user.id, email: email) }.to raise_error do |error|
expect(error).to be_a(expected_error)
@@ -462,19 +464,19 @@
it 'raises error when "foreign key" constraint is violated' do
expected_error = Hanami::Model::ForeignKeyConstraintViolationError
message = Platform.match do
- engine(:ruby).db(:sqlite) { 'SQLite3::ConstraintException' }
- engine(:jruby).db(:sqlite) { 'Java::OrgSqlite::SQLiteException: [SQLITE_CONSTRAINT_FOREIGNKEY] A foreign key constraint failed (FOREIGN KEY constraint failed)' }
+ engine(:ruby).db(:sqlite) { "SQLite3::ConstraintException" }
+ engine(:jruby).db(:sqlite) { "Java::OrgSqlite::SQLiteException: [SQLITE_CONSTRAINT_FOREIGNKEY] A foreign key constraint failed (FOREIGN KEY constraint failed)" }
engine(:ruby).db(:postgresql) { 'PG::ForeignKeyViolation: ERROR: insert or update on table "avatars" violates foreign key constraint "avatars_user_id_fkey"' }
engine(:jruby).db(:postgresql) { 'Java::OrgPostgresqlUtil::PSQLException: ERROR: insert or update on table "avatars" violates foreign key constraint "avatars_user_id_fkey"' }
- engine(:ruby).db(:mysql) { 'Mysql2::Error: Cannot add or update a child row: a foreign key constraint fails' }
- engine(:jruby).db(:mysql) { 'Java::ComMysqlJdbcExceptionsJdbc4::MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`hanami_model`.`avatars`, CONSTRAINT `avatars_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE)' }
+ engine(:ruby).db(:mysql) { "Mysql2::Error: Cannot add or update a child row: a foreign key constraint fails" }
+ engine(:jruby).db(:mysql) { "Java::ComMysqlJdbcExceptionsJdbc4::MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`hanami_model`.`avatars`, CONSTRAINT `avatars_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE)" }
end
- user = UserRepository.new.create(name: 'L')
- repository = AvatarRepository.new
- avatar = repository.create(user_id: user.id, url: 'a valid url')
+ user = UserRepository.new(configuration: configuration).create(name: "L")
+ repository = AvatarRepository.new(configuration: configuration)
+ avatar = repository.create(user_id: user.id, url: "a valid url")
expect { repository.update(avatar.id, user_id: 999_999_999) }.to raise_error do |error|
expect(error).to be_a(expected_error)
@@ -489,15 +491,15 @@
expected = Hanami::Model::CheckConstraintViolationError
message = Platform.match do
- engine(:ruby).db(:sqlite) { 'SQLite3::ConstraintException: CHECK constraint failed' }
- engine(:jruby).db(:sqlite) { 'Java::OrgSqlite::SQLiteException: [SQLITE_CONSTRAINT_CHECK] A CHECK constraint failed (CHECK constraint failed: users)' }
+ engine(:ruby).db(:sqlite) { "SQLite3::ConstraintException: CHECK constraint failed" }
+ engine(:jruby).db(:sqlite) { "Java::OrgSqlite::SQLiteException: [SQLITE_CONSTRAINT_CHECK] A CHECK constraint failed (CHECK constraint failed: users)" }
engine(:ruby).db(:postgresql) { 'PG::CheckViolation: ERROR: new row for relation "users" violates check constraint "users_age_check"' }
engine(:jruby).db(:postgresql) { 'Java::OrgPostgresqlUtil::PSQLException: ERROR: new row for relation "users" violates check constraint "users_age_check"' }
end
- repository = UserRepository.new
- user = repository.create(name: 'L')
+ repository = UserRepository.new(configuration: configuration)
+ user = repository.create(name: "L")
expect { repository.update(user.id, age: 17) }.to raise_error do |error|
expect(error).to be_a(expected)
@@ -505,19 +507,19 @@
end
end
- it 'raises error when constraint is violated' do
+ it "raises error when constraint is violated" do
expected = Hanami::Model::CheckConstraintViolationError
message = Platform.match do
- engine(:ruby).db(:sqlite) { 'SQLite3::ConstraintException: CHECK constraint failed' }
- engine(:jruby).db(:sqlite) { 'Java::OrgSqlite::SQLiteException: [SQLITE_CONSTRAINT_CHECK] A CHECK constraint failed (CHECK constraint failed: comments_count_constraint)' }
+ engine(:ruby).db(:sqlite) { "SQLite3::ConstraintException: CHECK constraint failed" }
+ engine(:jruby).db(:sqlite) { "Java::OrgSqlite::SQLiteException: [SQLITE_CONSTRAINT_CHECK] A CHECK constraint failed (CHECK constraint failed: comments_count_constraint)" }
engine(:ruby).db(:postgresql) { 'PG::CheckViolation: ERROR: new row for relation "users" violates check constraint "comments_count_constraint"' }
engine(:jruby).db(:postgresql) { 'Java::OrgPostgresqlUtil::PSQLException: ERROR: new row for relation "users" violates check constraint "comments_count_constraint"' }
end
- repository = UserRepository.new
- user = repository.create(name: 'L')
+ repository = UserRepository.new(configuration: configuration)
+ user = repository.create(name: "L")
expect { repository.update(user.id, comments_count: -2) }.to raise_error do |error|
expect(error).to be_a(expected)
@@ -527,96 +529,96 @@
end
end
- describe '#delete' do
- it 'deletes record' do
- repository = UserRepository.new
- user = repository.create(name: 'L')
+ describe "#delete" do
+ it "deletes record" do
+ repository = UserRepository.new(configuration: configuration)
+ user = repository.create(name: "L")
deleted = repository.delete(user.id)
- expect(deleted).to be_an_instance_of(User)
+ expect(deleted).to be_a(Project::Entities::User)
expect(deleted.id).to eq(user.id)
- expect(deleted.name).to eq('L')
+ expect(deleted.name).to eq("L")
found = repository.find(user.id)
expect(found).to be_nil
end
- it 'returns nil when record cannot be found' do
- repository = UserRepository.new
- deleted = repository.delete('9999999')
+ it "returns nil when record cannot be found" do
+ repository = UserRepository.new(configuration: configuration)
+ deleted = repository.delete("9999999")
expect(deleted).to be_nil
end
end
- describe '#transaction' do
+ describe "#transaction" do
end
- describe 'custom finder' do
- it 'returns records' do
- repository = UserRepository.new
- user = repository.create(name: 'L')
- found = repository.by_name('L')
+ describe "custom finder" do
+ it "returns records" do
+ repository = UserRepository.new(configuration: configuration)
+ user = repository.create(name: "L")
+ found = repository.by_name("L")
expect(found.to_a).to include(user)
end
- it 'uses root relation' do
- repository = UserRepository.new
- user = repository.create(name: 'L')
- found = repository.by_name_with_root('L')
+ it "uses root relation" do
+ repository = UserRepository.new(configuration: configuration)
+ user = repository.create(name: "L")
+ found = repository.by_name_with_root("L")
expect(found.to_a).to include(user)
end
- it 'selects only a single column' do
- repository = UserRepository.new
+ it "selects only a single column" do
+ repository = UserRepository.new(configuration: configuration)
repository.clear
- repository.create([{ name: 'L', age: 35 }, { name: 'MG', age: 34 }])
+ repository.create([{ name: "L", age: 35 }, { name: "MG", age: 34 }])
found = repository.ids
expect(found.size).to be(2)
found.each do |user|
- expect(user).to be_a_kind_of(User)
+ expect(user).to be_a_kind_of(Project::Entities::User)
expect(user.id).to_not be(nil)
- expect(user.name).to be(nil)
- expect(user.age).to be(nil)
+ expect { user.name }.to raise_error Hanami::Model::MissingAttributeError
+ expect { user.age }.to raise_error Hanami::Model::MissingAttributeError
end
end
- it 'selects multiple columns' do
- repository = UserRepository.new
+ it "selects multiple columns" do
+ repository = UserRepository.new(configuration: configuration)
repository.clear
- repository.create([{ name: 'L', age: 35 }, { name: 'MG', age: 34 }])
+ repository.create([{ name: "L", age: 35 }, { name: "MG", age: 34 }])
found = repository.select_id_and_name
expect(found.size).to be(2)
found.each do |user|
- expect(user).to be_a_kind_of(User)
+ expect(user).to be_a(Project::Entities::User)
expect(user.id).to_not be(nil)
expect(user.name).to_not be(nil)
- expect(user.age).to be(nil)
+ expect { user.age }.to raise_error Hanami::Model::MissingAttributeError
end
end
end
with_platform(db: :postgresql) do
- describe 'PostgreSQL' do
- it 'finds record by primary key (UUID)' do
- repository = SourceFileRepository.new
- file = repository.create(name: 'path/to/file.rb', languages: ['ruby'], metadata: { coverage: 100.0 }, content: 'class Foo; end')
+ describe "PostgreSQL" do
+ it "finds record by primary key (UUID)" do
+ repository = SourceFileRepository.new(configuration: configuration)
+ file = repository.create(name: "path/to/file.rb", languages: ["ruby"], metadata: { coverage: 100.0 }, content: "class Foo; end")
found = repository.find(file.id)
- expect(file.languages).to eq(['ruby'])
+ expect(file.languages).to eq(["ruby"])
expect(file.metadata).to eq(coverage: 100.0)
expect(found).to eq(file)
end
- it 'returns nil for nil primary key (UUID)' do
- repository = SourceFileRepository.new
+ it "returns nil for nil primary key (UUID)" do
+ repository = SourceFileRepository.new(configuration: configuration)
found = repository.find(nil)
expect(found).to be_nil
@@ -626,29 +628,29 @@
#
# Sequel::DatabaseError: PG::InvalidTextRepresentation: ERROR: invalid input syntax for uuid: "9999999"
# LINE 1: ...", "updated_at" FROM "source_files" WHERE ("id" = '9999999')...
- it 'returns nil for missing record (UUID)'
+ it "returns nil for missing record (UUID)"
# it 'returns nil for missing record (UUID)' do
- # repository = SourceFileRepository.new
+ # repository = SourceFileRepository.new(configuration: configuration)
# found = repository.find('9999999')
# expect(found).to be_nil
# end
- describe 'JSON types' do
- it 'writes hashes' do
- hash = { first_name: 'John', age: 53, married: true, car: nil }
- repository = SourceFileRepository.new
- column_type = repository.create(metadata: hash, name: 'test', content: 'test', json_info: hash)
+ describe "JSON types" do
+ it "writes hashes" do
+ hash = { first_name: "John", age: 53, married: true, car: nil }
+ repository = SourceFileRepository.new(configuration: configuration)
+ column_type = repository.create(metadata: hash, name: "test", content: "test", json_info: hash)
found = repository.find(column_type.id)
expect(found.metadata).to eq(hash)
expect(found.json_info).to eq(hash)
end
- it 'writes arrays' do
- array = ['abc', 1, true, nil]
- repository = SourceFileRepository.new
- column_type = repository.create(metadata: array, name: 'test', content: 'test', json_info: array)
+ it "writes arrays" do
+ array = ["abc", 1, true, nil]
+ repository = SourceFileRepository.new(configuration: configuration)
+ column_type = repository.create(metadata: array, name: "test", content: "test", json_info: array)
found = repository.find(column_type.id)
expect(found.metadata).to eq(array)
@@ -657,50 +659,50 @@
end
describe "when timestamps aren't enabled" do
- it 'writes the proper PG types' do
- repository = ProductRepository.new
+ it "writes the proper PG types" do
+ repository = ProductRepository.new(configuration: configuration)
- product = repository.create(name: 'NeoVim', categories: ['software'])
+ product = repository.create(name: "NeoVim", categories: ["software"])
found = repository.find(product.id)
- expect(product.categories).to eq(['software'])
+ expect(product.categories).to eq(["software"])
expect(found).to eq(product)
end
- it 'succeeds even if timestamps is the only plugin' do
- repository = ProductRepository.new
+ it "succeeds even if timestamps is the only plugin" do
+ repository = ProductRepository.new(configuration: configuration)
product = repository
- .command(:create, repository.root, use: %i[timestamps])
- .call(name: 'NeoVim', categories: ['software'])
+ .command(:create, use: %i[timestamps])
+ .call(name: "NeoVim", categories: ["software"])
found = repository.find(product.id)
- expect(product.categories).to eq(['software'])
+ expect(product.categories).to eq(["software"])
expect(found.to_h).to eq(product.to_h)
end
end
end
- describe 'enum database type' do
- it 'allows to write data' do
- repository = ColorRepository.new
- color = repository.create(name: 'red')
+ describe "enum database type" do
+ it "allows to write data" do
+ repository = ColorRepository.new(configuration: configuration)
+ color = repository.create(name: "red")
- expect(color).to be_a_kind_of(Color)
- expect(color.name).to eq('red')
+ expect(color).to be_a_kind_of(Project::Entities::Color)
+ expect(color.name).to eq("red")
end
- it 'raises error if the value is not included in the enum' do
- repository = ColorRepository.new
+ it "raises error if the value is not included in the enum" do
+ repository = ColorRepository.new(configuration: configuration)
message = Platform.match do
engine(:ruby) { %(PG::InvalidTextRepresentation: ERROR: invalid input value for enum rainbow: "grey") }
engine(:jruby) { %(Java::OrgPostgresqlUtil::PSQLException: ERROR: invalid input value for enum rainbow: "grey") }
end
- expect { repository.create(name: 'grey') }.to raise_error do |error|
+ expect { repository.create(name: "grey") }.to raise_error do |error|
expect(error).to be_a(Hanami::Model::Error)
expect(error.message).to include(message)
end
diff --git a/spec/integration/hanami/model/repository/command_spec.rb b/spec/integration/hanami/model/repository/command_spec.rb
index 100863f5..8cf8df3c 100644
--- a/spec/integration/hanami/model/repository/command_spec.rb
+++ b/spec/integration/hanami/model/repository/command_spec.rb
@@ -1,25 +1,27 @@
-RSpec.describe 'Customized commands' do
- subject(:authors) { AuthorRepository.new }
+# frozen_string_literal: true
+
+RSpec.describe "Customized commands" do
+ subject(:authors) { AuthorRepository.new(configuration: configuration) }
let(:data) do
- [{ name: 'Arthur C. Clarke' }, { name: 'Phillip K. Dick' }]
+ [{ name: "Arthur C. Clarke" }, { name: "Phillip K. Dick" }]
end
- context 'the mapper' do
- it 'is enabled by default' do
+ context "the mapper" do
+ it "is enabled by default" do
result = authors.create_many(data)
expect(result).to be_an Array
expect(result).to all(be_an(Author))
end
- it 'can be explictly turned off' do
+ it "can be explictly turned off" do
result = authors.create_many(data, opts: { mapper: nil })
- expect(result).to all(be_an(ROM::Struct))
+ expect(result).to all(be_an(::Hash))
end
end
- context 'timestamps' do
- it 'are enabled by default' do
+ context "timestamps" do
+ it "are enabled by default" do
result = authors.create_many(data)
expect(result.first.created_at).to be_within(2).of(Time.now.utc)
end
diff --git a/spec/integration/hanami/model/repository/legacy_spec.rb b/spec/integration/hanami/model/repository/legacy_spec.rb
index d000800b..de44f106 100644
--- a/spec/integration/hanami/model/repository/legacy_spec.rb
+++ b/spec/integration/hanami/model/repository/legacy_spec.rb
@@ -1,123 +1,116 @@
-RSpec.describe 'Repository (legacy)' do
- describe '#find' do
- it 'finds record by primary key' do
- repository = OperatorRepository.new
- operator = repository.create(name: 'F')
+# frozen_string_literal: true
+
+RSpec.describe "Repository (legacy)" do
+ let(:repository) { OperatorRepository.new(configuration: configuration) }
+
+ describe "#find" do
+ it "finds record by primary key" do
+ operator = repository.create(name: "F")
found = repository.find(operator.id)
expect(operator).to eq(found)
end
- it 'returns nil for missing record' do
- repository = OperatorRepository.new
- found = repository.find('9999999')
+ it "returns nil for missing record" do
+ found = repository.find("9999999")
expect(found).to be_nil
end
end
- describe '#all' do
- it 'returns all the records' do
- repository = OperatorRepository.new
- operator = repository.create(name: 'F')
+ describe "#all" do
+ it "returns all the records" do
+ operator = repository.create(name: "F")
expect(repository.all).to be_an_instance_of(Array)
expect(repository.all).to include(operator)
end
end
- describe '#first' do
- it 'returns first record from table' do
- repository = OperatorRepository.new
+ describe "#first" do
+ it "returns first record from table" do
repository.clear
- operator = repository.create(name: 'Janis Joplin')
- repository.create(name: 'Jon')
+ operator = repository.create(name: "Janis Joplin")
+ repository.create(name: "Jon")
expect(repository.first).to eq(operator)
end
end
- describe '#last' do
- it 'returns last record from table' do
- repository = OperatorRepository.new
+ describe "#last" do
+ it "returns last record from table" do
repository.clear
- repository.create(name: 'Rob')
- operator = repository.create(name: 'Amy Winehouse')
+ repository.create(name: "Rob")
+ operator = repository.create(name: "Amy Winehouse")
expect(repository.last).to eq(operator)
end
end
- describe '#clear' do
- it 'clears all the records' do
- repository = OperatorRepository.new
- repository.create(name: 'F')
+ describe "#clear" do
+ it "clears all the records" do
+ repository.create(name: "F")
repository.clear
expect(repository.all).to be_empty
end
end
- describe '#execute' do
+ describe "#execute" do
end
- describe '#fetch' do
+ describe "#fetch" do
end
- describe '#create' do
- it 'creates record' do
- repository = OperatorRepository.new
- operator = repository.create(name: 'F')
+ describe "#create" do
+ it "creates record" do
+ operator = repository.create(name: "F")
- expect(operator).to be_an_instance_of(Operator)
+ expect(operator).to be_an(Project::Entities::Operator)
expect(operator.id).to_not be_nil
- expect(operator.name).to eq('F')
+ expect(operator.name).to eq("F")
end
end
- describe '#update' do
- it 'updates record' do
- repository = OperatorRepository.new
- operator = repository.create(name: 'F')
- updated = repository.update(operator.id, name: 'Flo')
+ describe "#update" do
+ it "updates record" do
+ operator = repository.create(name: "F")
+ updated = repository.update(operator.id, name: "Flo")
- expect(updated).to be_an_instance_of(Operator)
+ expect(updated).to be_an(Project::Entities::Operator)
expect(updated.id).to eq(operator.id)
- expect(updated.name).to eq('Flo')
+ expect(updated.name).to eq("Flo")
end
- it 'returns nil when record cannot be found' do
- repository = OperatorRepository.new
- updated = repository.update('9999999', name: 'Flo')
+ it "returns nil when record cannot be found" do
+ updated = repository.update("9999999", name: "Flo")
expect(updated).to be_nil
end
end
- describe '#delete' do
- it 'deletes record' do
- repository = OperatorRepository.new
- operator = repository.create(name: 'F')
+ describe "#delete" do
+ it "deletes record" do
+ operator = repository.create(name: "F")
deleted = repository.delete(operator.id)
- expect(deleted).to be_an_instance_of(Operator)
+ expect(deleted).to be_an(Project::Entities::Operator)
expect(deleted.id).to eq(operator.id)
- expect(deleted.name).to eq('F')
+ expect(deleted.name).to eq("F")
found = repository.find(operator.id)
expect(found).to be_nil
end
- it 'returns nil when record cannot be found' do
- repository = OperatorRepository.new
- deleted = repository.delete('9999999')
+ it "returns nil when record cannot be found" do
+ deleted = repository.delete("9999999")
expect(deleted).to be_nil
end
end
- describe '#transaction' do
+ describe "#transaction" do
end
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 0d62a4d6..b74a6c73 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -1,9 +1,11 @@
-$LOAD_PATH.unshift 'lib'
-require 'hanami/devtools/unit'
-require 'hanami/model'
+# frozen_string_literal: true
-require_relative './support/rspec'
-require_relative './support/test_io'
-require_relative './support/platform'
-require_relative './support/database'
-require_relative './support/fixtures'
+$LOAD_PATH.unshift "lib"
+require "hanami/devtools/unit"
+require "hanami/model"
+
+require_relative "./support/rspec"
+require_relative "./support/test_io"
+require_relative "./support/platform"
+require_relative "./support/database"
+require_relative "./support/fixtures"
diff --git a/spec/support/database.rb b/spec/support/database.rb
index f90b5e4f..7ada959f 100644
--- a/spec/support/database.rb
+++ b/spec/support/database.rb
@@ -1,8 +1,10 @@
+# frozen_string_literal: true
+
module Database
class Setup
- DEFAULT_ADAPTER = 'sqlite'.freeze
+ DEFAULT_ADAPTER = "sqlite"
- def initialize(adapter: ENV['DB'])
+ def initialize(adapter: ENV["DB"])
@strategy = Strategy.for(adapter || DEFAULT_ADAPTER)
end
@@ -12,9 +14,9 @@ def run
end
module Strategies
- require_relative './database/strategies/sqlite'
- require_relative './database/strategies/postgresql'
- require_relative './database/strategies/mysql'
+ require_relative "./database/strategies/sqlite"
+ require_relative "./database/strategies/postgresql"
+ require_relative "./database/strategies/mysql"
def self.strategies
constants.map do |const|
@@ -40,7 +42,7 @@ def strategies
end
def self.engine
- ENV['HANAMI_DATABASE_TYPE'].to_sym
+ ENV["HANAMI_DATABASE_TYPE"].to_sym
end
def self.engine?(name)
@@ -48,4 +50,22 @@ def self.engine?(name)
end
end
-Database::Setup.new.run
+# rubocop:disable Style/GlobalVars
+$config = Database::Setup.new.run
+
+module RSpec
+ module Support
+ module Context
+ def self.included(base)
+ base.class_eval do
+ let(:configuration) { $config }
+ end
+ end
+ end
+ end
+end
+# rubocop:enable Style/GlobalVars
+
+RSpec.configure do |config|
+ config.include(RSpec::Support::Context)
+end
diff --git a/spec/support/database/strategies/abstract.rb b/spec/support/database/strategies/abstract.rb
index ef6fac46..44d10b6d 100644
--- a/spec/support/database/strategies/abstract.rb
+++ b/spec/support/database/strategies/abstract.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Database
module Strategies
class Abstract
@@ -10,9 +12,11 @@ def run
load_dependencies
export_env
create_database
- configure
+ configuration = configure
after
sleep 1
+
+ configuration
end
protected
@@ -22,7 +26,7 @@ def before
end
def database_name
- 'hanami_model'
+ "hanami_model"
end
def load_dependencies
@@ -30,7 +34,7 @@ def load_dependencies
end
def export_env
- ENV['HANAMI_DATABASE_NAME'] = database_name
+ ENV["HANAMI_DATABASE_NAME"] = database_name
end
def create_database
@@ -38,11 +42,12 @@ def create_database
end
def configure
- returing = Hanami::Model.configure do
- adapter ENV['HANAMI_DATABASE_ADAPTER'].to_sym, ENV['HANAMI_DATABASE_URL']
+ returning = Hanami::Model.configure do
+ adapter ENV["HANAMI_DATABASE_ADAPTER"].to_sym, ENV["HANAMI_DATABASE_URL"]
end
- returing == Hanami::Model or raise 'Hanami::Model.configure should return Hanami::Model'
+ returning == Hanami::Model or raise "Hanami::Model.configure should return Hanami::Model"
+ returning.configuration
end
def after
diff --git a/spec/support/database/strategies/mysql.rb b/spec/support/database/strategies/mysql.rb
index 254a351f..adee51cc 100644
--- a/spec/support/database/strategies/mysql.rb
+++ b/spec/support/database/strategies/mysql.rb
@@ -1,4 +1,6 @@
-require_relative 'sql'
+# frozen_string_literal: true
+
+require_relative "sql"
module Database
module Strategies
@@ -7,27 +9,27 @@ module JrubyImplementation
protected
def load_dependencies
- require 'hanami/model/sql'
- require 'jdbc/mysql'
+ require "hanami/model/sql"
+ require "jdbc/mysql"
end
def export_env
super
- ENV['HANAMI_DATABASE_URL'] = "jdbc:mysql://#{host}/#{database_name}?#{credentials}"
+ ENV["HANAMI_DATABASE_URL"] = "jdbc:mysql://#{host}/#{database_name}?#{credentials}"
end
def host
- ENV['HANAMI_DATABASE_HOST'] || '127.0.0.1'
+ ENV["HANAMI_DATABASE_HOST"] || "127.0.0.1"
end
def credentials
Hash[
- 'user' => ENV['HANAMI_DATABASE_USERNAME'],
- 'password' => ENV['HANAMI_DATABASE_PASSWORD'],
- 'useSSL' => 'false'
+ "user" => ENV["HANAMI_DATABASE_USERNAME"],
+ "password" => ENV["HANAMI_DATABASE_PASSWORD"],
+ "useSSL" => "false"
].map do |key, value|
"#{key}=#{value}" unless Hanami::Utils::Blank.blank?(value)
- end.compact.join('&')
+ end.compact.join("&")
end
end
@@ -36,8 +38,8 @@ module TravisCiImplementation
def export_env
super
- ENV['HANAMI_DATABASE_USERNAME'] = 'travis'
- ENV['HANAMI_DATABASE_URL'] = "mysql2://#{credentials}@#{host}/#{database_name}"
+ ENV["HANAMI_DATABASE_USERNAME"] = "travis"
+ ENV["HANAMI_DATABASE_URL"] = "mysql2://#{credentials}@#{host}/#{database_name}"
end
def create_database
@@ -59,8 +61,8 @@ module CircleCiImplementation
def export_env
super
- ENV['HANAMI_DATABASE_USERNAME'] ||= 'root'
- ENV['HANAMI_DATABASE_URL'] = "mysql2://#{credentials}@#{host}/#{database_name}"
+ ENV["HANAMI_DATABASE_USERNAME"] ||= "root"
+ ENV["HANAMI_DATABASE_URL"] = "mysql2://#{credentials}@#{host}/#{database_name}"
end
def create_database
@@ -77,7 +79,7 @@ def run_command(command)
end
def self.eligible?(adapter)
- adapter.start_with?('mysql')
+ adapter.start_with?("mysql")
end
def initialize
@@ -94,16 +96,16 @@ def initialize
protected
def load_dependencies
- require 'hanami/model/sql'
- require 'mysql2'
+ require "hanami/model/sql"
+ require "mysql2"
end
def export_env
super
- ENV['HANAMI_DATABASE_TYPE'] = 'mysql'
- ENV['HANAMI_DATABASE_USERNAME'] ||= 'root'
- ENV['HANAMI_DATABASE_PASSWORD'] ||= ''
- ENV['HANAMI_DATABASE_URL'] = "mysql2://#{credentials}@#{host}/#{database_name}"
+ ENV["HANAMI_DATABASE_TYPE"] = "mysql"
+ ENV["HANAMI_DATABASE_USERNAME"] ||= "root"
+ ENV["HANAMI_DATABASE_PASSWORD"] ||= ""
+ ENV["HANAMI_DATABASE_URL"] = "mysql2://#{credentials}@#{host}/#{database_name}"
end
def create_database
diff --git a/spec/support/database/strategies/postgresql.rb b/spec/support/database/strategies/postgresql.rb
index cf76afb6..5fa5303f 100644
--- a/spec/support/database/strategies/postgresql.rb
+++ b/spec/support/database/strategies/postgresql.rb
@@ -1,4 +1,6 @@
-require_relative 'sql'
+# frozen_string_literal: true
+
+require_relative "sql"
module Database
module Strategies
@@ -7,15 +9,15 @@ module JrubyImplementation
protected
def load_dependencies
- require 'hanami/model/sql'
- require 'jdbc/postgres'
+ require "hanami/model/sql"
+ require "jdbc/postgres"
Jdbc::Postgres.load_driver
end
def export_env
super
- ENV['HANAMI_DATABASE_URL'] = "jdbc:postgresql://#{host_and_credentials}/#{database_name}"
+ ENV["HANAMI_DATABASE_URL"] = "jdbc:postgresql://#{host_and_credentials}/#{database_name}"
end
end
@@ -24,7 +26,7 @@ module TravisCiImplementation
def export_env
super
- ENV['HANAMI_DATABASE_USERNAME'] = 'postgres'
+ ENV["HANAMI_DATABASE_USERNAME"] = "postgres"
end
end
@@ -43,7 +45,7 @@ def create_database
end
def self.eligible?(adapter)
- adapter.start_with?('postgres')
+ adapter.start_with?("postgres")
end
def initialize
@@ -60,8 +62,8 @@ def initialize
protected
def load_dependencies
- require 'hanami/model/sql'
- require 'pg'
+ require "hanami/model/sql"
+ require "pg"
end
def create_database
@@ -76,9 +78,9 @@ def create_database
def export_env
super
- ENV['HANAMI_DATABASE_TYPE'] = 'postgresql'
- ENV['HANAMI_DATABASE_USERNAME'] ||= `whoami`.strip.freeze
- ENV['HANAMI_DATABASE_URL'] = "postgres://#{credentials}@#{host}/#{database_name}"
+ ENV["HANAMI_DATABASE_TYPE"] = "postgresql"
+ ENV["HANAMI_DATABASE_USERNAME"] ||= `whoami`.strip.freeze
+ ENV["HANAMI_DATABASE_URL"] = "postgres://#{credentials}@#{host}/#{database_name}"
end
private
diff --git a/spec/support/database/strategies/sql.rb b/spec/support/database/strategies/sql.rb
index 00d971c1..d8fa9311 100644
--- a/spec/support/database/strategies/sql.rb
+++ b/spec/support/database/strategies/sql.rb
@@ -1,7 +1,9 @@
-require_relative 'abstract'
-require 'hanami/utils/blank'
-require 'pathname'
-require 'stringio'
+# frozen_string_literal: true
+
+require_relative "abstract"
+require "hanami/utils/blank"
+require "pathname"
+require "stringio"
module Database
module Strategies
@@ -20,23 +22,24 @@ def before
def export_env
super
- ENV['HANAMI_DATABASE_ADAPTER'] = 'sql'
- ENV['HANAMI_DATABASE_LOGGER'] = logger.to_s
+ ENV["HANAMI_DATABASE_ADAPTER"] = "sql"
+ ENV["HANAMI_DATABASE_LOGGER"] = logger.to_s
end
def configure # rubocop:disable Metrics/AbcSize
Hanami::Model.configure do
- adapter ENV['HANAMI_DATABASE_ADAPTER'].to_sym, ENV['HANAMI_DATABASE_URL']
- logger ENV['HANAMI_DATABASE_LOGGER'], level: :debug
- migrations Dir.pwd + '/spec/support/fixtures/database_migrations'
- schema Dir.pwd + '/tmp/schema.sql'
+ adapter ENV["HANAMI_DATABASE_ADAPTER"].to_sym, ENV["HANAMI_DATABASE_URL"]
+ logger ENV["HANAMI_DATABASE_LOGGER"], level: :debug
+ migrations Dir.pwd + "/spec/support/fixtures/database_migrations"
+ schema Dir.pwd + "/tmp/schema.sql"
+ path Dir.pwd + "/spec/support/fixtures/project/"
- migrations_logger ENV['HANAMI_DATABASE_LOGGER']
+ migrations_logger ENV["HANAMI_DATABASE_LOGGER"]
gateway do |g|
g.connection.extension(:pg_enum) if Database.engine?(:postgresql)
end
- end
+ end.configuration
end
def after
@@ -47,19 +50,19 @@ def after
def migrate
TestIO.with_stdout do
- require 'hanami/model/migrator'
+ require "hanami/model/migrator"
Hanami::Model::Migrator.migrate
end
end
def credentials
- [ENV['HANAMI_DATABASE_USERNAME'], ENV['HANAMI_DATABASE_PASSWORD']].reject do |token|
+ [ENV["HANAMI_DATABASE_USERNAME"], ENV["HANAMI_DATABASE_PASSWORD"]].reject do |token|
Hanami::Utils::Blank.blank?(token)
- end.join(':')
+ end.join(":")
end
def host
- ENV['HANAMI_DATABASE_HOST'] || 'localhost'
+ ENV["HANAMI_DATABASE_HOST"] || "localhost"
end
def host_and_credentials
@@ -69,7 +72,7 @@ def host_and_credentials
end
def logger
- Pathname.new('tmp').join('hanami_model.log')
+ Pathname.new("tmp").join("hanami_model.log")
end
end
end
diff --git a/spec/support/database/strategies/sqlite.rb b/spec/support/database/strategies/sqlite.rb
index 01963731..958c3d00 100644
--- a/spec/support/database/strategies/sqlite.rb
+++ b/spec/support/database/strategies/sqlite.rb
@@ -1,5 +1,7 @@
-require_relative 'sql'
-require 'pathname'
+# frozen_string_literal: true
+
+require_relative "sql"
+require "pathname"
module Database
module Strategies
@@ -8,14 +10,14 @@ module JrubyImplementation
protected
def load_dependencies
- require 'hanami/model/sql'
- require 'jdbc/sqlite3'
+ require "hanami/model/sql"
+ require "jdbc/sqlite3"
Jdbc::SQLite3.load_driver
end
def export_env
super
- ENV['HANAMI_DATABASE_URL'] = "jdbc:sqlite://#{database_name}"
+ ENV["HANAMI_DATABASE_URL"] = "jdbc:sqlite://#{database_name}"
end
end
@@ -23,7 +25,7 @@ module CiImplementation
end
def self.eligible?(adapter)
- adapter.start_with?('sqlite')
+ adapter.start_with?("sqlite")
end
def initialize
@@ -34,12 +36,12 @@ def initialize
protected
def database_name
- Pathname.new(__dir__).join('..', '..', '..', '..', 'tmp', 'sqlite', "#{super}.sqlite3").to_s
+ Pathname.new(__dir__).join("..", "..", "..", "..", "tmp", "sqlite", "#{super}.sqlite3").to_s
end
def load_dependencies
- require 'hanami/model/sql'
- require 'sqlite3'
+ require "hanami/model/sql"
+ require "sqlite3"
end
def create_database
@@ -51,8 +53,8 @@ def create_database
def export_env
super
- ENV['HANAMI_DATABASE_TYPE'] = 'sqlite'
- ENV['HANAMI_DATABASE_URL'] = "sqlite://#{database_name}"
+ ENV["HANAMI_DATABASE_TYPE"] = "sqlite"
+ ENV["HANAMI_DATABASE_URL"] = "sqlite://#{database_name}"
end
end
end
diff --git a/spec/support/fixtures.rb b/spec/support/fixtures.rb
index 1b75c949..c011f9d2 100644
--- a/spec/support/fixtures.rb
+++ b/spec/support/fixtures.rb
@@ -1,374 +1,321 @@
+# frozen_string_literal: true
+
require "ostruct"
class BaseParams < OpenStruct
- def to_hash
- to_h
+ def merge(other)
+ other.merge(to_h)
end
end
-class User < Hanami::Entity
-end
+module Project
+ module Entities
+ class Operator < Hanami::Entity
+ def name
+ s_name
+ end
-class Avatar < Hanami::Entity
-end
+ def id
+ operator_id
+ end
+ end
-class Author < Hanami::Entity
-end
+ class AccessToken < Hanami::Entity
+ end
-class Book < Hanami::Entity
-end
+ class Author < Hanami::Entity
+ end
-class Category < Hanami::Entity
-end
+ class Avatar < Hanami::Entity
+ end
-class BookOntology < Hanami::Entity
-end
+ class Book < Hanami::Entity
+ end
-class Operator < Hanami::Entity
-end
+ class BookOntology < Hanami::Entity
+ end
-class AccessToken < Hanami::Entity
-end
+ class Category < Hanami::Entity
+ end
-class SourceFile < Hanami::Entity
-end
+ class Color < Hanami::Entity
+ end
-class Post < Hanami::Entity
-end
+ class Comment < Hanami::Entity
+ end
-class Comment < Hanami::Entity
-end
+ class Label < Hanami::Entity
+ end
-class Warehouse < Hanami::Entity
- attributes do
- attribute :id, Types::Int
- attribute :name, Types::String
- attribute :code, Types::String.constrained(format: /\Awh\-/)
- end
-end
+ class Post < Hanami::Entity
+ end
-class Account < Hanami::Entity
- attributes do
- attribute :id, Types::Strict::Int
- attribute :name, Types::String
- attribute :codes, Types::Collection(Types::Coercible::Int)
- attribute :owner, Types::Entity(User)
- attribute :users, Types::Collection(User)
- attribute :email, Types::String.constrained(format: /@/)
- attribute :created_at, Types::DateTime.constructor(->(dt) { ::DateTime.parse(dt.to_s) })
+ class User < Hanami::Entity
+ end
end
end
-class PageVisit < Hanami::Entity
- attributes do
- attribute :id, Types::Strict::Int
- attribute :start, Types::DateTime
- attribute :end, Types::DateTime
- attribute :visitor, Types::Hash
- attribute :page_info, Types::Hash.symbolized(
- name: Types::Coercible::String,
- scroll_depth: Types::Coercible::Float,
- meta: Types::Hash
- )
- end
+class AccessTokenRepository < Hanami::Repository[:tokens]
+ struct_namespace Project::Entities
end
-class Person < Hanami::Entity
- attributes :strict do
- attribute :id, Types::Strict::Int
- attribute :name, Types::Strict::String
- end
-end
-
-class Product < Hanami::Entity
-end
+class AuthorRepository < Hanami::Repository[:authors]
+ struct_namespace Project::Entities
-class Color < Hanami::Entity
-end
-
-class Label < Hanami::Entity
-end
+ def find_with_books(id)
+ root.combine(:books).by_pk(id).one
+ end
-class PostRepository < Hanami::Repository
- associations do
- belongs_to :user, as: :author
- has_many :comments
- has_many :users, through: :comments, as: :commenters
+ # There must be a better way to do this - MRP - 2020-04-25
+ def books_for(author)
+ books.join(root).where(root[:id] => author.id).to_a
end
- def find_with_commenters(id)
- aggregate(:commenters).where(id: id).map_to(Post).to_a
+ def books_count(author)
+ root.assoc(:books).where(root[:id] => author.id).count
end
- def commenters_for(post)
- assoc(:commenters, post).to_a
+ def on_sales_books_count(author)
+ root.assoc(:books).where(root[:id] => author.id, on_sale: true).count
end
- def find_with_author(id)
- aggregate(:author).where(id: id).map_to(Post).one
+ def add_book(author, data)
+ associated = root.associations[:books].associate(data, author)
+ command(:create, relation: books).call(associated)
end
- def feed_for(id)
- aggregate(:author, comments: :user).where(id: id).map_to(Post).one
+ def create_with_books(data)
+ command(:create, relation: root.combine(:books)).call(data)
end
- def author_for(post)
- assoc(:author, post).one
+ # There's no simple way to delete from the has_many association it seems,
+ # as composite scopes aren't changeable.
+ # One could argue that this is better done directly on the BookRepository
+ # and that we are only mirroring AR behaviour. - MRP - 2020-04-25
+ def delete_books(author)
+ books.where(author_id: author.id).delete
end
-end
-class CommentRepository < Hanami::Repository
- associations do
- belongs_to :post
- belongs_to :user
+ def delete_on_sales_books(author)
+ books.where(author_id: author.id, on_sale: true).delete
end
- def commenter_for(comment)
- assoc(:user, comment).one
+ def remove_book(_author, id)
+ command(:update, relation: books).by_pk(id).call(author_id: nil)
end
end
-class AvatarRepository < Hanami::Repository
- associations do
- belongs_to :user
- end
+class AvatarRepository < Hanami::Repository[:avatars]
+ struct_namespace Project::Entities
def by_user(id)
- avatars.where(user_id: id).to_a
+ root.where(user_id: id).to_a
end
end
-class UserRepository < Hanami::Repository
- associations do
- has_one :avatar
- has_many :posts, as: :threads
- has_many :comments
- end
-
- def find_with_threads(id)
- aggregate(:threads).where(id: id).map_to(User).one
- end
-
- def threads_for(user)
- assoc(:threads, user).to_a
- end
+class BookRepository < Hanami::Repository[:books]
+ struct_namespace Project::Entities
- def find_with_avatar(id)
- aggregate(:avatar).where(id: id).map_to(User).one
- end
-
- def create_with_avatar(data)
- assoc(:avatar).create(data)
- end
-
- def remove_avatar(user)
- assoc(:avatar, user).delete
- end
-
- def add_avatar(user, data)
- assoc(:avatar, user).add(data)
- end
-
- def update_avatar(user, data)
- assoc(:avatar, user).update(data)
- end
-
- def replace_avatar(user, data)
- assoc(:avatar, user).replace(data)
- end
-
- def avatar_for(user)
- assoc(:avatar, user).one
- end
-
- def by_name(name)
- users.where(name: name)
+ def author_for(book)
+ author.join(root).where(root[:id] => book.id).one
end
- def by_matching_name(name)
- users.where(users[:name].ilike(name)).map_to(User).to_a
+ def find_with_author(id)
+ root.combine(:author).by_pk(id).one
end
- def by_name_with_root(name)
- root.where(name: name).as(:entity)
+ def find_with_categories(id)
+ root.combine(:categories).by_pk(id).one
end
- def find_all_by_manual_query
- users.read("select * from users").to_a
+ def categories_for(book)
+ categories.join(root).where(root[:id] => book.id).to_a
end
- def ids
- users.select(:id).to_a
+ def add_category(book, *data)
+ associated = categories.associations[:books].associate(data, book)
+ command(:create, relation: book_ontologies).call(associated)
end
- def select_id_and_name
- users.select(:id, :name).to_a
+ def clear_categories(book)
+ book_ontologies.where(book_id: book.id).delete
end
end
-class AvatarRepository < Hanami::Repository
+class BookOntologyRepository < Hanami::Repository[:book_ontologies]
+ struct_namespace Project::Entities
end
-class AuthorRepository < Hanami::Repository
- associations do
- has_many :books
- end
+class CategoryRepository < Hanami::Repository[:categories]
+ struct_namespace Project::Entities
- def create_many(data, opts: {})
- command(create: :authors, result: :many, **opts).call(data)
- end
-
- def create_with_books(data)
- assoc(:books).create(data)
+ def books_for(category)
+ books.join(root).where(root[:id] => category.id).to_a
end
- def find_with_books(id)
- aggregate(:books).by_pk(id).map_to(Author).one
+ def on_sales_books_count(category)
+ root.assoc(:books).where(root[:id] => category.id, on_sale: true).count
end
- def books_for(author)
- assoc(:books, author)
+ def books_count(category)
+ books.join(root).where(root[:id] => category.id).count
end
- def add_book(author, data)
- assoc(:books, author).add(data)
+ def find_with_books(id)
+ root.combine(:books).by_pk(id).one
end
- def remove_book(author, id)
- assoc(:books, author).remove(id)
+ def add_books(category, *data)
+ # This is a bit weird. Is there any other way to do this?
+ associated = books.associations[:categories].associate(data, category)
+ command(:create, relation: book_ontologies).call(associated)
end
- def delete_books(author)
- assoc(:books, author).delete
+ def remove_book(category, book_id)
+ book_ontologies.where(category_id: category.id, book_id: book_id).delete
end
+end
- def delete_on_sales_books(author)
- assoc(:books, author).where(on_sale: true).delete
- end
+class ColorRepository < Hanami::Repository[:colors]
+ struct_namespace Project::Entities
+end
- def books_count(author)
- assoc(:books, author).count
- end
+class LabelRepository < Hanami::Repository[:labels]
+ struct_namespace Project::Entities
+end
- def on_sales_books_count(author)
- assoc(:books, author).where(on_sale: true).count
- end
+class CommentRepository < Hanami::Repository[:comments]
+ struct_namespace Project::Entities
+end
- def find_book(author, id)
- book_for(author, id).one
+class PostRepository < Hanami::Repository[:posts]
+ # def find_with_commenters(id)
+ # combine(:commenters).where(id: id).map_to(Post).to_a
+ # end
+ #
+ def commenters_for(post)
+ target = root.associations[:commenters].call
+ target.where(root[:id] => post.id).to_a
end
- def book_exists?(author, id)
- book_for(author, id).exists?
+ def find_with_author(id)
+ root.combine(:author).by_pk(id).one
end
- private
-
- def book_for(author, id)
- assoc(:books, author).where(id: id)
+ def feed_for(id)
+ root.combine(:author, comments: :user).by_pk(id).one
end
-end
-class BookOntologyRepository < Hanami::Repository
- associations do
- belongs_to :books
- belongs_to :categories
+ def author_for(post)
+ target = root.associations[:author].call
+ target.where(root[:id] => post.id).one
end
end
-class CategoryRepository < Hanami::Repository
- associations do
- has_many :books, through: :book_ontologies
- end
-
- def books_for(category)
- assoc(:books, category)
- end
-
- def on_sales_books_count(category)
- assoc(:books, category).where(on_sale: true).count
- end
+class UserRepository < Hanami::Repository[:users]
+ struct_namespace Project::Entities
- def books_count(category)
- assoc(:books, category).count
+ def by_name(name)
+ root.where(name: name)
end
- def find_with_books(id)
- aggregate(:books).where(id: id).map_to(Category).one
+ def by_matching_name(name)
+ root.where(users[:name].ilike(name)).to_a
end
- def add_books(category, *books)
- assoc(:books, category).add(*books)
+ def by_name_with_root(name)
+ root.where(name: name)
end
- def remove_book(category, book_id)
- assoc(:books, category).remove(book_id)
+ def find_all_by_manual_query
+ users.read("select * from users").map_to(Project::Entities::User).to_a
end
-end
-class BookRepository < Hanami::Repository
- associations do
- belongs_to :author
- has_many :categories, through: :book_ontologies
+ def ids
+ root.select(:id).to_a
end
- def add_category(book, category)
- assoc(:categories, book).add(category)
+ def select_id_and_name
+ root.select(:id, :name).to_a
end
- def clear_categories(book)
- assoc(:categories, book).delete
+ def threads_for(user)
+ posts.combine(:comments).join(root).where(root[:id] => user.id).to_a
end
- def categories_for(book)
- assoc(:categories, book).to_a
+ def find_with_avatar(id)
+ root.combine(:avatar).by_pk(id).one
end
- def find_with_categories(id)
- aggregate(:categories).where(id: id).map_to(Book).one
+ def create_with_avatar(data)
+ root.combine(:avatar).command(:create, use: COMMAND_PLUGINS).call(data)
end
- def find_with_author(id)
- aggregate(:author).where(id: id).map_to(Book).one
+ def remove_avatar(user)
+ avatars.where(user_id: user.id).delete
end
- def author_for(book)
- assoc(:author, book).one
+ def add_avatar(user, data)
+ # Should I use root.associations[:avatar].target?
+ # Is there a better way to do this?
+ associated = root.associations[:avatar].associate(data, user)
+ root.associations[:avatar].target.command(:create).call(associated)
end
-end
-
-class OperatorRepository < Hanami::Repository
- self.relation = :t_operator
- mapping do
- attribute :id, from: :operator_id
- attribute :name, from: :s_name
+ def update_avatar(user, data)
+ associated = root.associations[:avatar].associate(data, user)
+ command(:update, relation: avatars.where(user_id: user.id)).call(associated)
end
-end
-
-class AccessTokenRepository < Hanami::Repository
- self.relation = "tokens"
-end
-
-class SourceFileRepository < Hanami::Repository
-end
-class WarehouseRepository < Hanami::Repository
-end
-
-class ProductRepository < Hanami::Repository
-end
-
-class ColorRepository < Hanami::Repository
- schema do
- attribute :id, Hanami::Model::Sql::Types::Int
- attribute :name, Hanami::Model::Sql::Types::String
- attribute :created_at, Hanami::Model::Sql::Types::DateTime
- attribute :updated_at, Hanami::Model::Sql::Types::DateTime
+ def replace_avatar(user, data)
+ transaction do
+ remove_avatar(user)
+ add_avatar(user, data)
+ end
end
-end
-
-class LabelRepository < Hanami::Repository
-end
-Hanami::Model.load!
+ def avatar_for(user)
+ target = root.associations[:avatar].call
+ target.where(root[:id] => user.id).one
+ end
+end
+
+# FIXME: This becomes non trivial bringing the need to setup a transformer & mapper
+# We had this before because all the entities had their database schemas loaded onto them
+# Is there a way to achieve this functionality? -> legacy_spec
+class OperatorRepository < Hanami::Repository[:operators]
+ struct_namespace Project::Entities
+end
+
+# class User < Hanami::OldEntity
+# end
+#
+# class Account < Hanami::OldEntity
+# attribute :id, Types::Strict::Integer
+# attribute :name, Types::String
+# attribute :codes, Types::Collection(Types::Coercible::Integer)
+# attribute :owner, Types::Entity(User)
+# attribute :users, Types::Collection(User)
+# attribute :email, Types::String.constrained(format: /@/)
+# attribute :created_at, Types::DateTime.constructor(->(dt) { ::DateTime.parse(dt.to_s) })
+# end
+#
+#
+# class PageVisit < Hanami::OldEntity
+# attribute :id, Types::Strict::Integer
+# attribute :start, Types::DateTime
+# attribute :end, Types::DateTime
+# attribute :visitor, Types::Hash
+# attribute :page_info do
+# attribute :name, Types::Coercible::String
+# attribute :scroll_depth, Types::Coercible::Float
+# attribute :meta, Types::Hash
+# end
+# end
+#
+# class Person < Hanami::OldEntity[:strict]
+# attribute :id, Types::Strict::Integer
+# attribute :name, Types::Strict::String
+# end
+
+Hanami::Model.configuration.load!
diff --git a/spec/support/fixtures/database_migrations/20150612081248_column_types.rb b/spec/support/fixtures/database_migrations/20150612081248_column_types.rb
index 079a958b..bbce4f33 100644
--- a/spec/support/fixtures/database_migrations/20150612081248_column_types.rb
+++ b/spec/support/fixtures/database_migrations/20150612081248_column_types.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
change do
case Database.engine
@@ -5,12 +7,12 @@
create_table :column_types do
column :integer1, Integer
column :integer2, :integer
- column :integer3, 'integer'
+ column :integer3, "integer"
column :string1, String
column :string2, :string
- column :string3, 'string'
- column :string4, 'varchar(3)'
+ column :string3, "string"
+ column :string4, "varchar(3)"
column :string5, String, size: 50
column :string6, String, fixed: true
@@ -18,7 +20,7 @@
column :string8, String, text: true
column :file1, File
- column :file2, 'blob'
+ column :file2, "blob"
column :number1, Fixnum # rubocop:disable Lint/UnifiedInteger
column :number2, :Bignum
@@ -51,14 +53,14 @@
create_table :column_types do
column :integer1, Integer
column :integer2, :integer
- column :integer3, 'integer'
+ column :integer3, "integer"
column :string1, String
- column :string2, 'text'
- column :string3, 'character varying(1)'
- column :string4, 'varchar(2)'
- column :string5, 'character(3)'
- column :string6, 'char(4)'
+ column :string2, "text"
+ column :string3, "character varying(1)"
+ column :string4, "varchar(2)"
+ column :string5, "character(3)"
+ column :string6, "char(4)"
column :string7, String, size: 50
column :string8, String, fixed: true
@@ -66,7 +68,7 @@
column :string10, String, text: true
column :file1, File
- column :file2, 'bytea'
+ column :file2, "bytea"
column :number1, Fixnum # rubocop:disable Lint/UnifiedInteger
column :number2, :Bignum
@@ -85,37 +87,37 @@
column :boolean1, TrueClass
column :boolean2, FalseClass
- column :array1, 'integer[]'
- column :array2, 'integer[3]'
- column :array3, 'text[][]'
+ column :array1, "integer[]"
+ column :array2, "integer[3]"
+ column :array3, "text[][]"
- column :money1, 'money'
+ column :money1, "money"
- column :enum1, 'mood'
+ column :enum1, "mood"
- column :geometric1, 'point'
- column :geometric2, 'line'
- column :geometric3, 'circle', default: '<(15,15), 1>'
+ column :geometric1, "point"
+ column :geometric2, "line"
+ column :geometric3, "circle", default: "<(15,15), 1>"
- column :net1, 'cidr', default: '192.168/24'
+ column :net1, "cidr", default: "192.168/24"
- column :uuid1, 'uuid', default: Hanami::Model::Sql.function(:uuid_generate_v4)
+ column :uuid1, "uuid", default: Hanami::Model::Sql.function(:uuid_generate_v4)
- column :xml1, 'xml'
+ column :xml1, "xml"
- column :json1, 'json'
- column :json2, 'jsonb'
+ column :json1, "json"
+ column :json2, "jsonb"
- column :composite1, 'inventory_item', default: Hanami::Model::Sql.literal("ROW('fuzzy dice', 42, 1.99)")
+ column :composite1, "inventory_item", default: Hanami::Model::Sql.literal("ROW('fuzzy dice', 42, 1.99)")
end
when :mysql
create_table :column_types do
column :integer1, Integer
column :integer2, :integer
- column :integer3, 'integer'
+ column :integer3, "integer"
column :string1, String
- column :string2, 'varchar(3)'
+ column :string2, "varchar(3)"
column :string5, String, size: 50
column :string6, String, fixed: true
@@ -123,7 +125,7 @@
column :string8, String, text: true
column :file1, File
- column :file2, 'blob'
+ column :file2, "blob"
column :number1, Fixnum # rubocop:disable Lint/UnifiedInteger
column :number2, :Bignum
diff --git a/spec/support/fixtures/database_migrations/20150612084656_default_values.rb b/spec/support/fixtures/database_migrations/20150612084656_default_values.rb
index 308868ac..df040851 100644
--- a/spec/support/fixtures/database_migrations/20150612084656_default_values.rb
+++ b/spec/support/fixtures/database_migrations/20150612084656_default_values.rb
@@ -1,10 +1,12 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
change do
case Database.engine
when :sqlite
create_table :default_values do
column :a, Integer, default: 23
- column :b, String, default: 'Hanami'
+ column :b, String, default: "Hanami"
column :c, Fixnum, default: -1 # rubocop:disable Lint/UnifiedInteger
column :d, :Bignum, default: 0
column :e, Float, default: 3.14
@@ -19,13 +21,13 @@
when :postgresql
create_table :default_values do
column :a, Integer, default: 23
- column :b, String, default: 'Hanami'
+ column :b, String, default: "Hanami"
column :c, Fixnum, default: -1 # rubocop:disable Lint/UnifiedInteger
column :d, :Bignum, default: 0
column :e, Float, default: 3.14
column :f, BigDecimal, default: 1.0
column :g, Numeric, default: 943_943
- column :h, Date, default: 'now'
+ column :h, Date, default: "now"
column :i, DateTime, default: DateTime.now
column :j, Time, default: Time.now
column :k, TrueClass, default: true
@@ -34,7 +36,7 @@
when :mysql
create_table :default_values do
column :a, Integer, default: 23
- column :b, String, default: 'Hanami'
+ column :b, String, default: "Hanami"
column :c, Fixnum, default: -1 # rubocop:disable Lint/UnifiedInteger
column :d, :Bignum, default: 0
column :e, Float, default: 3.14
diff --git a/spec/support/fixtures/database_migrations/20150612093458_null_constraints.rb b/spec/support/fixtures/database_migrations/20150612093458_null_constraints.rb
index f6470f77..9e6a7cf7 100644
--- a/spec/support/fixtures/database_migrations/20150612093458_null_constraints.rb
+++ b/spec/support/fixtures/database_migrations/20150612093458_null_constraints.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
change do
create_table :null_constraints do
diff --git a/spec/support/fixtures/database_migrations/20150612093810_column_indexes.rb b/spec/support/fixtures/database_migrations/20150612093810_column_indexes.rb
index 461f672c..781754ae 100644
--- a/spec/support/fixtures/database_migrations/20150612093810_column_indexes.rb
+++ b/spec/support/fixtures/database_migrations/20150612093810_column_indexes.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
change do
create_table :column_indexes do
diff --git a/spec/support/fixtures/database_migrations/20150612094740_primary_keys.rb b/spec/support/fixtures/database_migrations/20150612094740_primary_keys.rb
index 7505df76..32a48024 100644
--- a/spec/support/fixtures/database_migrations/20150612094740_primary_keys.rb
+++ b/spec/support/fixtures/database_migrations/20150612094740_primary_keys.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
change do
create_table :primary_keys_1 do
diff --git a/spec/support/fixtures/database_migrations/20150612115204_foreign_keys.rb b/spec/support/fixtures/database_migrations/20150612115204_foreign_keys.rb
index 8583259a..4b011c2f 100644
--- a/spec/support/fixtures/database_migrations/20150612115204_foreign_keys.rb
+++ b/spec/support/fixtures/database_migrations/20150612115204_foreign_keys.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
change do
create_table :artists do
diff --git a/spec/support/fixtures/database_migrations/20150612122233_table_constraints.rb b/spec/support/fixtures/database_migrations/20150612122233_table_constraints.rb
index 3a148cc5..1571ca55 100644
--- a/spec/support/fixtures/database_migrations/20150612122233_table_constraints.rb
+++ b/spec/support/fixtures/database_migrations/20150612122233_table_constraints.rb
@@ -1,7 +1,9 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
change do
- case ENV['HANAMI_DATABASE_TYPE']
- when 'sqlite'
+ case ENV["HANAMI_DATABASE_TYPE"]
+ when "sqlite"
create_table :table_constraints do
column :age, Integer
constraint(:age_constraint) { age > 18 }
@@ -9,7 +11,7 @@
column :role, String
check %(role IN("contributor", "manager", "owner"))
end
- when 'postgresql'
+ when "postgresql"
create_table :table_constraints do
column :age, Integer
constraint(:age_constraint) { age > 18 }
@@ -17,7 +19,7 @@
column :role, String
check %(role IN('contributor', 'manager', 'owner'))
end
- when 'mysql'
+ when "mysql"
create_table :table_constraints do
column :age, Integer
constraint(:age_constraint) { age > 18 }
diff --git a/spec/support/fixtures/database_migrations/20150612124205_table_alterations.rb b/spec/support/fixtures/database_migrations/20150612124205_table_alterations.rb
index 5e19c750..c19cb9af 100644
--- a/spec/support/fixtures/database_migrations/20150612124205_table_alterations.rb
+++ b/spec/support/fixtures/database_migrations/20150612124205_table_alterations.rb
@@ -1,7 +1,9 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
change do
- case ENV['HANAMI_DATABASE_TYPE']
- when 'sqlite'
+ case ENV["HANAMI_DATABASE_TYPE"]
+ when "sqlite"
create_table :songs do
column :title, String
column :useless, String
@@ -19,7 +21,7 @@
set_column_type :useless, File
rename_column :title, :primary_title
- set_column_default :primary_title, 'Unknown title'
+ set_column_default :primary_title, "Unknown title"
# add_index :album_id
# drop_index :artist_id
@@ -34,7 +36,7 @@
drop_constraint :useless_min_length
drop_column :useless
end
- when 'postgresql'
+ when "postgresql"
create_table :songs do
column :title, String
column :useless, String
@@ -52,7 +54,7 @@
# set_column_type :useless, File
rename_column :title, :primary_title
- set_column_default :primary_title, 'Unknown title'
+ set_column_default :primary_title, "Unknown title"
# add_index :album_id
# drop_index :artist_id
diff --git a/spec/support/fixtures/database_migrations/20160830094800_create_users.rb b/spec/support/fixtures/database_migrations/20160830094800_create_users.rb
index 8ff31616..9eaccb32 100644
--- a/spec/support/fixtures/database_migrations/20160830094800_create_users.rb
+++ b/spec/support/fixtures/database_migrations/20160830094800_create_users.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
change do
drop_table? :users
diff --git a/spec/support/fixtures/database_migrations/20160830094851_create_authors.rb b/spec/support/fixtures/database_migrations/20160830094851_create_authors.rb
index 6395f63c..7be34224 100644
--- a/spec/support/fixtures/database_migrations/20160830094851_create_authors.rb
+++ b/spec/support/fixtures/database_migrations/20160830094851_create_authors.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
change do
drop_table? :authors
diff --git a/spec/support/fixtures/database_migrations/20160830094941_create_books.rb b/spec/support/fixtures/database_migrations/20160830094941_create_books.rb
index d14f9722..3ce90faa 100644
--- a/spec/support/fixtures/database_migrations/20160830094941_create_books.rb
+++ b/spec/support/fixtures/database_migrations/20160830094941_create_books.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
change do
drop_table? :books
diff --git a/spec/support/fixtures/database_migrations/20160830095033_create_t_operator.rb b/spec/support/fixtures/database_migrations/20160830095033_create_t_operator.rb
index b75167b2..c6ee29ff 100644
--- a/spec/support/fixtures/database_migrations/20160830095033_create_t_operator.rb
+++ b/spec/support/fixtures/database_migrations/20160830095033_create_t_operator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
change do
drop_table? :t_operator
diff --git a/spec/support/fixtures/database_migrations/20160905125728_create_source_files.rb b/spec/support/fixtures/database_migrations/20160905125728_create_source_files.rb
index 488a9fe2..93627441 100644
--- a/spec/support/fixtures/database_migrations/20160905125728_create_source_files.rb
+++ b/spec/support/fixtures/database_migrations/20160905125728_create_source_files.rb
@@ -1,13 +1,15 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
change do
case Database.engine
when :postgresql
create_table :source_files do
- column :id, 'uuid', primary_key: true, default: Hanami::Model::Sql.function(:uuid_generate_v4)
+ column :id, "uuid", primary_key: true, default: Hanami::Model::Sql.function(:uuid_generate_v4)
column :name, String, null: false
- column :languages, 'text[]'
- column :metadata, 'jsonb', null: false
- column :json_info, 'json'
+ column :languages, "text[]"
+ column :metadata, "jsonb", null: false
+ column :json_info, "json"
column :content, File, null: false
column :created_at, DateTime, null: false
column :updated_at, DateTime, null: false
diff --git a/spec/support/fixtures/database_migrations/20160909150704_create_avatars.rb b/spec/support/fixtures/database_migrations/20160909150704_create_avatars.rb
index 2a38a1c0..2e854266 100644
--- a/spec/support/fixtures/database_migrations/20160909150704_create_avatars.rb
+++ b/spec/support/fixtures/database_migrations/20160909150704_create_avatars.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
change do
drop_table? :avatars
diff --git a/spec/support/fixtures/database_migrations/20161104143844_create_warehouses.rb b/spec/support/fixtures/database_migrations/20161104143844_create_warehouses.rb
index 24253d41..bcea269d 100644
--- a/spec/support/fixtures/database_migrations/20161104143844_create_warehouses.rb
+++ b/spec/support/fixtures/database_migrations/20161104143844_create_warehouses.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
change do
drop_table? :warehouses
diff --git a/spec/support/fixtures/database_migrations/20161114094644_create_products.rb b/spec/support/fixtures/database_migrations/20161114094644_create_products.rb
index a185b255..05e988d7 100644
--- a/spec/support/fixtures/database_migrations/20161114094644_create_products.rb
+++ b/spec/support/fixtures/database_migrations/20161114094644_create_products.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
change do
case Database.engine
@@ -5,7 +7,7 @@
create_table :products do
primary_key :id
column :name, String
- column :categories, 'text[]'
+ column :categories, "text[]"
end
else
create_table :products do
diff --git a/spec/support/fixtures/database_migrations/20170103142428_create_colors.rb b/spec/support/fixtures/database_migrations/20170103142428_create_colors.rb
index e94fe4f0..2ecc04ef 100644
--- a/spec/support/fixtures/database_migrations/20170103142428_create_colors.rb
+++ b/spec/support/fixtures/database_migrations/20170103142428_create_colors.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
change do
case Database.engine
diff --git a/spec/support/fixtures/database_migrations/20170124081339_create_labels.rb b/spec/support/fixtures/database_migrations/20170124081339_create_labels.rb
index ca159853..bb47388c 100644
--- a/spec/support/fixtures/database_migrations/20170124081339_create_labels.rb
+++ b/spec/support/fixtures/database_migrations/20170124081339_create_labels.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
change do
create_table :labels do
diff --git a/spec/support/fixtures/database_migrations/20170517115243_create_tokens.rb b/spec/support/fixtures/database_migrations/20170517115243_create_tokens.rb
index 0bd14be0..aa0b9249 100644
--- a/spec/support/fixtures/database_migrations/20170517115243_create_tokens.rb
+++ b/spec/support/fixtures/database_migrations/20170517115243_create_tokens.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
change do
drop_table? :tokens
diff --git a/spec/support/fixtures/database_migrations/20170519172332_create_categories.rb b/spec/support/fixtures/database_migrations/20170519172332_create_categories.rb
index 89361731..69f4ab53 100644
--- a/spec/support/fixtures/database_migrations/20170519172332_create_categories.rb
+++ b/spec/support/fixtures/database_migrations/20170519172332_create_categories.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
change do
drop_table? :categories
diff --git a/spec/support/fixtures/database_migrations/20171002201227_create_posts_and_comments.rb b/spec/support/fixtures/database_migrations/20171002201227_create_posts_and_comments.rb
index 14e917c6..96864f2a 100644
--- a/spec/support/fixtures/database_migrations/20171002201227_create_posts_and_comments.rb
+++ b/spec/support/fixtures/database_migrations/20171002201227_create_posts_and_comments.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
change do
drop_table? :posts
diff --git a/spec/support/fixtures/migrations/20160831073534_create_reviews.rb b/spec/support/fixtures/migrations/20160831073534_create_reviews.rb
index a934c6d8..164350f1 100644
--- a/spec/support/fixtures/migrations/20160831073534_create_reviews.rb
+++ b/spec/support/fixtures/migrations/20160831073534_create_reviews.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
up do
create_table :reviews do
diff --git a/spec/support/fixtures/migrations/20160831090612_add_rating_to_reviews.rb b/spec/support/fixtures/migrations/20160831090612_add_rating_to_reviews.rb
index 6c65a540..e6029fc5 100644
--- a/spec/support/fixtures/migrations/20160831090612_add_rating_to_reviews.rb
+++ b/spec/support/fixtures/migrations/20160831090612_add_rating_to_reviews.rb
@@ -1,6 +1,8 @@
+# frozen_string_literal: true
+
Hanami::Model.migration do
up do
- add_column :reviews, :rating, 'integer', default: 0
+ add_column :reviews, :rating, "integer", default: 0
end
down do
diff --git a/spec/support/fixtures/project/relations/authors.rb b/spec/support/fixtures/project/relations/authors.rb
new file mode 100644
index 00000000..84ec7dbe
--- /dev/null
+++ b/spec/support/fixtures/project/relations/authors.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Project
+ module Relations
+ class Authors < Hanami::Relation[:sql]
+ schema(:authors, infer: true) do
+ associations do
+ has_many :books
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/fixtures/project/relations/avatars.rb b/spec/support/fixtures/project/relations/avatars.rb
new file mode 100644
index 00000000..6fcd1de6
--- /dev/null
+++ b/spec/support/fixtures/project/relations/avatars.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Project
+ module Relations
+ class Avatars < Hanami::Relation[:sql]
+ struct_namespace Project::Entities
+ auto_struct true
+
+ schema(:avatars, infer: true) do
+ associations do
+ belongs_to :users
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/fixtures/project/relations/book_ontologies.rb b/spec/support/fixtures/project/relations/book_ontologies.rb
new file mode 100644
index 00000000..73912105
--- /dev/null
+++ b/spec/support/fixtures/project/relations/book_ontologies.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Project
+ module Relations
+ class BookOntologies < Hanami::Relation[:sql]
+ schema(:book_ontologies, infer: true) do
+ associations do
+ belongs_to :books
+ belongs_to :categories
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/fixtures/project/relations/books.rb b/spec/support/fixtures/project/relations/books.rb
new file mode 100644
index 00000000..40ece0a3
--- /dev/null
+++ b/spec/support/fixtures/project/relations/books.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Project
+ module Relations
+ class Books < Hanami::Relation[:sql]
+ schema(:books, infer: true) do
+ associations do
+ belongs_to :author
+ has_many :book_ontologies
+ has_many :categories, through: :book_ontologies
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/fixtures/project/relations/categories.rb b/spec/support/fixtures/project/relations/categories.rb
new file mode 100644
index 00000000..1de4db6b
--- /dev/null
+++ b/spec/support/fixtures/project/relations/categories.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Project
+ module Relations
+ class Categories < Hanami::Relation[:sql]
+ schema(:categories, infer: true) do
+ associations do
+ has_many :book_ontologies
+ has_many :books, through: :book_ontologies
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/fixtures/project/relations/colors.rb b/spec/support/fixtures/project/relations/colors.rb
new file mode 100644
index 00000000..aac28ae0
--- /dev/null
+++ b/spec/support/fixtures/project/relations/colors.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Project
+ module Relations
+ class Colors < Hanami::Relation[:sql]
+ schema(:colors) do
+ attribute :id, Hanami::Model::Sql::Types::Integer
+ attribute :name, Hanami::Model::Sql::Types::String
+ attribute :created_at, Hanami::Model::Sql::Types::DateTime
+ attribute :updated_at, Hanami::Model::Sql::Types::DateTime
+ end
+ end
+ end
+end
diff --git a/spec/support/fixtures/project/relations/comments.rb b/spec/support/fixtures/project/relations/comments.rb
new file mode 100644
index 00000000..243d0a82
--- /dev/null
+++ b/spec/support/fixtures/project/relations/comments.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Project
+ module Relations
+ class Comments < Hanami::Relation[:sql]
+ auto_struct true
+ struct_namespace Project::Entities
+
+ schema(:comments, infer: true) do
+ associations do
+ belongs_to :user
+ belongs_to :post
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/fixtures/project/relations/labels.rb b/spec/support/fixtures/project/relations/labels.rb
new file mode 100644
index 00000000..58123c11
--- /dev/null
+++ b/spec/support/fixtures/project/relations/labels.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module Project
+ module Relations
+ class Labels < Hanami::Relation[:sql]
+ schema(:labels, infer: true)
+ end
+ end
+end
diff --git a/spec/support/fixtures/project/relations/operators.rb b/spec/support/fixtures/project/relations/operators.rb
new file mode 100644
index 00000000..8d739d3b
--- /dev/null
+++ b/spec/support/fixtures/project/relations/operators.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Project
+ module Relations
+ class Operators < Hanami::Relation[:sql]
+ schema(:t_operator, as: :operators) do
+ attribute :operator_id, Types::Integer
+ attribute :s_name, Types::String
+
+ primary_key :operator_id
+ end
+ end
+ end
+end
diff --git a/spec/support/fixtures/project/relations/posts.rb b/spec/support/fixtures/project/relations/posts.rb
new file mode 100644
index 00000000..1acffda2
--- /dev/null
+++ b/spec/support/fixtures/project/relations/posts.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Project
+ module Relations
+ class Posts < Hanami::Relation[:sql]
+ auto_struct true
+ struct_namespace Project::Entities
+
+ schema(:posts, infer: true) do
+ associations do
+ belongs_to :user, as: :author
+ has_many :comments
+ has_many :users, through: :comments, as: :commenters
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/fixtures/project/relations/tokens.rb b/spec/support/fixtures/project/relations/tokens.rb
new file mode 100644
index 00000000..14e1b0bf
--- /dev/null
+++ b/spec/support/fixtures/project/relations/tokens.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module Project
+ module Relations
+ class Tokens < Hanami::Relation[:sql]
+ schema(:tokens, infer: true)
+ end
+ end
+end
diff --git a/spec/support/fixtures/project/relations/users.rb b/spec/support/fixtures/project/relations/users.rb
new file mode 100644
index 00000000..5ab0d808
--- /dev/null
+++ b/spec/support/fixtures/project/relations/users.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Project
+ module Relations
+ class Users < Hanami::Relation[:sql]
+ schema(:users, infer: true) do
+ associations do
+ has_one :avatar
+ has_many :posts, as: :threads
+ has_many :comments
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/platform.rb b/spec/support/platform.rb
index d4c8035a..b0b29ffa 100644
--- a/spec/support/platform.rb
+++ b/spec/support/platform.rb
@@ -1,9 +1,11 @@
+# frozen_string_literal: true
+
module Platform
- require_relative 'platform/os'
- require_relative 'platform/ci'
- require_relative 'platform/engine'
- require_relative 'platform/db'
- require_relative 'platform/matcher'
+ require_relative "platform/os"
+ require_relative "platform/ci"
+ require_relative "platform/engine"
+ require_relative "platform/db"
+ require_relative "platform/matcher"
def self.ci?
!Ci.current.nil?
diff --git a/spec/support/platform/ci.rb b/spec/support/platform/ci.rb
index 83a66aa0..af5f87a4 100644
--- a/spec/support/platform/ci.rb
+++ b/spec/support/platform/ci.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Platform
module Ci
def self.ci?(name)
@@ -15,15 +17,15 @@ class << self
private
def travis?
- ENV['TRAVIS'] == 'true'
+ ENV["TRAVIS"] == "true"
end
def circle?
- ENV['CIRCLECI'] == 'true'
+ ENV["CIRCLECI"] == "true"
end
def drone?
- ENV['DRONE'] == 'true'
+ ENV["DRONE"] == "true"
end
end
end
diff --git a/spec/support/platform/db.rb b/spec/support/platform/db.rb
index a0c62b59..0e6bc200 100644
--- a/spec/support/platform/db.rb
+++ b/spec/support/platform/db.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Platform
module Db
def self.db?(name)
diff --git a/spec/support/platform/engine.rb b/spec/support/platform/engine.rb
index 8c6d83b4..1afa86a8 100644
--- a/spec/support/platform/engine.rb
+++ b/spec/support/platform/engine.rb
@@ -1,4 +1,6 @@
-require 'hanami/utils'
+# frozen_string_literal: true
+
+require "hanami/utils"
module Platform
module Engine
@@ -16,7 +18,7 @@ class << self
private
def ruby?
- RUBY_ENGINE == 'ruby'
+ RUBY_ENGINE == "ruby"
end
def jruby?
diff --git a/spec/support/platform/matcher.rb b/spec/support/platform/matcher.rb
index 8328ab04..11907107 100644
--- a/spec/support/platform/matcher.rb
+++ b/spec/support/platform/matcher.rb
@@ -1,10 +1,12 @@
-require 'hanami/utils/basic_object'
+# frozen_string_literal: true
+
+require "hanami/utils/basic_object"
module Platform
class Matcher
class Nope < Hanami::Utils::BasicObject
def or(other, &blk)
- blk.nil? ? other : blk.call
+ blk.nil? ? other : yield
end
# rubocop:disable Style/MethodMissingSuper
@@ -22,11 +24,13 @@ def self.match(&blk)
end
end
- def self.match?(os: Os.current, ci: Ci.current, engine: Engine.current, db: Db.current) # rubocop:disable Naming/UncommunicativeMethodParamName
+ # rubocop:disable Naming/MethodParameterName
+ def self.match?(os: Os.current, ci: Ci.current, engine: Engine.current, db: Db.current)
catch :match do
new.os(os).ci(ci).engine(engine).db(db) { true }.or(false)
end
end
+ # rubocop:enable Naming/MethodParameterName
def initialize
freeze
diff --git a/spec/support/platform/os.rb b/spec/support/platform/os.rb
index a617f506..014aff62 100644
--- a/spec/support/platform/os.rb
+++ b/spec/support/platform/os.rb
@@ -1,4 +1,6 @@
-require 'rbconfig'
+# frozen_string_literal: true
+
+require "rbconfig"
module Platform
module Os
@@ -7,7 +9,7 @@ def self.os?(name)
end
def self.current
- case RbConfig::CONFIG['host_os']
+ case RbConfig::CONFIG["host_os"]
when /linux/ then :linux
when /darwin/ then :macos
end
diff --git a/spec/support/rspec.rb b/spec/support/rspec.rb
index 8a71f70b..bcdd2b0d 100644
--- a/spec/support/rspec.rb
+++ b/spec/support/rspec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
RSpec.configure do |config|
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
@@ -14,7 +16,7 @@
config.warnings = true
- config.default_formatter = 'doc' if config.files_to_run.one?
+ config.default_formatter = "doc" if config.files_to_run.one?
config.profile_examples = 10
diff --git a/spec/support/test_io.rb b/spec/support/test_io.rb
index 173efb1e..a711f7d1 100644
--- a/spec/support/test_io.rb
+++ b/spec/support/test_io.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module TestIO
def self.with_stdout
stdout = $stdout
@@ -9,6 +11,6 @@ def self.with_stdout
end
def self.stream
- File.new(ENV['HANAMI_DATABASE_LOGGER'], "a+")
+ File.new(ENV["HANAMI_DATABASE_LOGGER"], "a+")
end
end
diff --git a/spec/unit/hanami/entity/automatic_schema_spec.rb b/spec/unit/hanami/entity/automatic_schema_spec.rb
index d174b9c6..5c721895 100644
--- a/spec/unit/hanami/entity/automatic_schema_spec.rb
+++ b/spec/unit/hanami/entity/automatic_schema_spec.rb
@@ -1,6 +1,8 @@
-RSpec.describe Hanami::Entity do
- describe 'automatic schema' do
- let(:described_class) { Author }
+# frozen_string_literal: true
+
+RSpec.describe Hanami::Entity, skip: true do
+ describe "automatic schema" do
+ let(:described_class) { Project::Entities::Author }
let(:input) do
Class.new do
@@ -10,43 +12,43 @@ def to_hash
end.new
end
- describe '#initialize' do
- it 'can be instantiated without attributes' do
+ describe "#initialize" do
+ it "can be instantiated without attributes" do
entity = described_class.new
expect(entity).to be_a_kind_of(described_class)
end
- it 'accepts a hash' do
- entity = described_class.new(id: 1, name: 'Luca', books: books = [Book.new], created_at: now = Time.now.utc)
+ it "accepts a hash" do
+ entity = described_class.new(id: 1, name: "Luca", books: books = [Book.new], created_at: now = Time.now.utc)
expect(entity.id).to eq(1)
- expect(entity.name).to eq('Luca')
+ expect(entity.name).to eq("Luca")
expect(entity.books).to eq(books)
expect(entity.created_at).to be_within(2).of(now)
end
- it 'accepts object that implements #to_hash' do
+ it "accepts object that implements #to_hash" do
entity = described_class.new(input)
expect(entity.id).to eq(1)
end
- it 'freezes the instance' do
+ it "freezes the instance" do
entity = described_class.new
expect(entity).to be_frozen
end
- it 'coerces values' do
+ it "coerces values" do
now = Time.now
entity = described_class.new(created_at: now.to_s)
expect(entity.created_at).to be_within(2).of(now)
end
- it 'coerces values for array of objects' do
- entity = described_class.new(books: books = [{ title: 'TDD' }, { title: 'Refactoring' }])
+ it "coerces values for array of objects" do
+ entity = described_class.new(books: books = [{ title: "TDD" }, { title: "Refactoring" }])
books.each_with_index do |book, i|
b = entity.books[i]
@@ -56,45 +58,39 @@ def to_hash
end
end
- it 'raises error if initialized with wrong array object' do
- object = Object.new
- expect { described_class.new(books: [object]) }.to raise_error do |error|
- expect(error).to be_a(TypeError)
- expect(error.message).to include('[#] (Array) has invalid type for :books')
- end
+ it "raises error if initialized with wrong array object" do
+ expect { described_class.new(books: [Object.new]) }.to raise_error(NoMethodError, /to_hash/)
end
end
- describe '#id' do
- it 'returns the value' do
- entity = described_class.new(id: 1)
-
+ describe "#id" do
+ it "returns the value" do
+ entity = described_class.new(id: 1, name: "Bob")
expect(entity.id).to eq(1)
end
- it 'returns nil if not present in attributes' do
+ it "returns nil if not present in attributes" do
entity = described_class.new
expect(entity.id).to be_nil
end
end
- describe 'accessors' do
- it 'exposes accessors from schema' do
- entity = described_class.new(name: 'Luca')
+ describe "accessors" do
+ it "exposes accessors from schema" do
+ entity = described_class.new(name: "Luca")
- expect(entity.name).to eq('Luca')
+ expect(entity.name).to eq("Luca")
end
- it 'raises error for unknown methods' do
+ it "raises error for unknown methods" do
entity = described_class.new
expect { entity.foo }
.to raise_error(NoMethodError, /undefined method `foo'/)
end
- it 'raises error when #attributes is invoked' do
+ it "raises error when #attributes is invoked" do
entity = described_class.new
expect { entity.attributes }
@@ -102,54 +98,54 @@ def to_hash
end
end
- describe '#to_h' do
- it 'serializes attributes into hash' do
- entity = described_class.new(id: 1, name: 'Luca')
+ describe "#to_h" do
+ it "serializes attributes into hash" do
+ entity = described_class.new(id: 1, name: "Luca")
- expect(entity.to_h).to eq(Hash[id: 1, name: 'Luca'])
+ expect(entity.to_h).to eq(Hash[id: 1, name: "Luca"])
end
- it 'must be an instance of ::Hash' do
+ it "must be an instance of ::Hash" do
entity = described_class.new
expect(entity.to_h).to be_an_instance_of(::Hash)
end
- it 'ignores unknown attributes' do
- entity = described_class.new(foo: 'bar')
+ it "ignores unknown attributes" do
+ entity = described_class.new(foo: "bar")
expect(entity.to_h).to eq(Hash[])
end
- it 'prevents information escape' do
- entity = described_class.new(books: books = [Book.new(id: 1), Book.new(id: 2)])
+ it "prevents information escape" do
+ entity = described_class.new(books: books = [Project::Entities::Book.new(id: 1), Project::Entities::Book.new(id: 2)])
entity.to_h[:books].reverse!
expect(entity.books).to eq(books)
end
- it 'is aliased as #to_hash' do
- entity = described_class.new(name: 'Luca')
+ it "is aliased as #to_hash" do
+ entity = described_class.new(name: "Luca")
expect(entity.to_hash).to eq(entity.to_h)
end
end
- describe '#respond_to?' do
- it 'returns ture for id' do
+ describe "#respond_to?" do
+ it "returns ture for id" do
entity = described_class.new
expect(entity).to respond_to(:id)
end
- it 'returns true for methods with the same name of attributes defined by schema' do
+ it "returns true for methods with the same name of attributes defined by schema" do
entity = described_class.new
expect(entity).to respond_to(:name)
end
- it 'returns false for methods not in the set of attributes defined by schema' do
- entity = described_class.new(foo: 'bar')
+ it "returns false for methods not in the set of attributes defined by schema" do
+ entity = described_class.new(foo: "bar")
expect(entity).to_not respond_to(:foo)
end
diff --git a/spec/unit/hanami/entity/manual_schema/base_spec.rb b/spec/unit/hanami/entity/manual_schema/base_spec.rb
index dccb99d0..5bf098f4 100644
--- a/spec/unit/hanami/entity/manual_schema/base_spec.rb
+++ b/spec/unit/hanami/entity/manual_schema/base_spec.rb
@@ -1,5 +1,7 @@
-RSpec.describe Hanami::Entity do
- describe 'manual schema (base)' do
+# frozen_string_literal: true
+
+RSpec.describe Hanami::Entity, skip: true do
+ describe "manual schema (base)" do
let(:described_class) { Account }
let(:input) do
@@ -10,38 +12,40 @@ def to_hash
end.new
end
- describe '#initialize' do
- it 'can be instantiated without attributes' do
+ describe "#initialize" do
+ it "can be instantiated without attributes" do
entity = described_class.new
expect(entity).to be_a_kind_of(described_class)
end
- it 'accepts a hash' do
- entity = described_class.new(id: 1, owner: owner = User.new(name: "MG"), users: users = [User.new], name: 'Acme Inc.', codes: [1, 2, 3], email: 'account@acme-inc.test', created_at: now = DateTime.now)
+ it "accepts a hash" do
+ entity = described_class.new(id: 1, owner: owner = User.new(name: "MG"), users: users = [User.new],
+ name: "Acme Inc.", codes: [1, 2, 3], email: "account@acme-inc.test",
+ created_at: now = DateTime.now)
expect(entity.id).to eq(1)
- expect(entity.name).to eq('Acme Inc.')
+ expect(entity.name).to eq("Acme Inc.")
expect(entity.owner).to eq(owner)
expect(entity.users).to eq(users)
expect(entity.codes).to eq([1, 2, 3])
- expect(entity.email).to eq('account@acme-inc.test')
+ expect(entity.email).to eq("account@acme-inc.test")
expect(entity.created_at).to be_within(1).of(now)
end
- it 'accepts object that implements #to_hash' do
+ it "accepts object that implements #to_hash" do
entity = described_class.new(input)
expect(entity.id).to eq(1)
end
- it 'freezes the instance' do
+ it "freezes the instance" do
entity = described_class.new
expect(entity).to be_frozen
end
- it 'coerces values' do
+ it "coerces values" do
now = DateTime.now
entity = described_class.new(created_at: now.to_s)
@@ -49,21 +53,21 @@ def to_hash
expect(entity.created_at).to be_within(1).of(now)
end
- it 'coerces values for array of primitives' do
+ it "coerces values for array of primitives" do
entity = described_class.new(codes: %w[4 5 6])
expect(entity.codes).to eq([4, 5, 6])
end
- it 'coerces values for single object' do
- entity = described_class.new(owner: owner = { name: 'L' })
+ it "coerces values for single object" do
+ entity = described_class.new(owner: owner = { name: "L" })
expect(entity.owner).to be_a_kind_of(User)
expect(entity.owner.name).to eq(owner.fetch(:name))
end
- it 'coerces values for array of objects' do
- entity = described_class.new(users: users = [{ name: 'L' }, { name: 'MG' }])
+ it "coerces values for array of objects" do
+ entity = described_class.new(users: users = [{ name: "L" }, { name: "MG" }])
users.each_with_index do |user, i|
u = entity.users[i]
@@ -73,85 +77,92 @@ def to_hash
end
end
- it 'raises error if initialized with wrong primitive' do
- expect { described_class.new(id: :foo) }
- .to raise_error(TypeError, ':foo (Symbol) has invalid type for :id violates constraints (type?(Integer, :foo) failed)')
+ it "raises error if initialized with wrong primitive" do
+ expect { described_class.new(id: :foo) }.to raise_error(Hanami::Model::Error) do |exception|
+ expect(exception.message).to include(":foo (Symbol) has invalid type for :id violates constraints (type?(Integer, :foo) failed)")
+ end
end
- it 'raises error if initialized with wrong array primitive' do
+ it "raises error if initialized with wrong array primitive" do
message = Platform.match do
engine(:jruby) { "no implicit conversion of Object into Integer" }
default { "can't convert Object into Integer" }
end
- expect { described_class.new(codes: [Object.new]) }.to raise_error(TypeError, message)
+ expect { described_class.new(codes: [Object.new]) }.to raise_error(Hanami::Model::Error) do |exception|
+ expect(exception.message).to match(message)
+ end
end
it "raises error if type constraint isn't honored" do
- expect { described_class.new(email: 'test') }
- .to raise_error(TypeError, '"test" (String) has invalid type for :email violates constraints (format?(/@/, "test") failed)')
+ expect { described_class.new(email: "test") }.to raise_error(Hanami::Model::Error) do |exception|
+ expect(exception.message).to include('"test" (String) has invalid type for :email violates constraints (format?(/@/, "test") failed)')
+ end
end
it "doesn't override manual defined schema" do
- expect { Warehouse.new(code: 'foo') }
- .to raise_error(TypeError, '"foo" (String) has invalid type for :code violates constraints (format?(/\Awh\-/, "foo") failed)')
+ expect { Warehouse.new(code: "foo") }.to raise_error(Hanami::Model::Error) do |exception|
+ expect(exception.message).to include('"foo" (String) has invalid type for :code violates constraints (format?(/\Awh\-/, "foo") failed)')
+ end
end
- it 'symbolizes nested hash keys according to schema' do
+ it "symbolizes nested hash keys according to schema" do
entity = PageVisit.new(
id: 42,
start: DateTime.now,
end: (Time.now + 53).to_datetime,
visitor: {
- 'user_agent' => 'w3m/0.5.3', 'language' => { 'en' => 0.9 }
+ "user_agent" => "w3m/0.5.3", "language" => { "en" => 0.9 }
},
page_info: {
- 'name' => 'landing page',
+ "name" => "landing page",
scroll_depth: 0.7,
- 'meta' => { 'version' => '0.8.3', updated_at: 1_492_769_467_000 }
+ "meta" => { "version" => "0.8.3", updated_at: 1_492_769_467_000 }
}
)
expect(entity.visitor).to eq(
- user_agent: 'w3m/0.5.3', language: { en: 0.9 }
+ user_agent: "w3m/0.5.3", language: { en: 0.9 }
)
expect(entity.page_info).to eq(
- name: 'landing page',
- scroll_depth: 0.7,
- meta: { version: '0.8.3', updated_at: 1_492_769_467_000 }
+ PageVisit::PageInfo.new(
+ name: "landing page",
+ scroll_depth: 0.7,
+ meta: { version: "0.8.3", updated_at: 1_492_769_467_000 }
+ )
)
end
end
- describe '#id' do
- it 'returns the value' do
+ describe "#id" do
+ it "returns the value" do
entity = described_class.new(id: 1)
expect(entity.id).to eq(1)
end
- it 'returns nil if not present in attributes' do
+ it "returns nil if not present in attributes" do
entity = described_class.new
expect(entity.id).to be_nil
end
end
- describe 'accessors' do
- it 'exposes accessors from schema' do
- entity = described_class.new(name: 'Acme Inc.')
+ describe "accessors" do
+ it "exposes accessors from schema" do
+ entity = described_class.new(name: "Acme Inc.")
- expect(entity.name).to eq('Acme Inc.')
+ expect(entity.name).to eq("Acme Inc.")
end
- it 'raises error for unknown methods' do
+ it "raises error for unknown methods" do
entity = described_class.new
expect { entity.foo }
.to raise_error(NoMethodError, /undefined method `foo'/)
end
- it 'raises error when #attributes is invoked' do
+ it "raises error when #attributes is invoked" do
entity = described_class.new
expect { entity.attributes }
@@ -159,54 +170,54 @@ def to_hash
end
end
- describe '#to_h' do
- it 'serializes attributes into hash' do
- entity = described_class.new(id: 1, name: 'Acme Inc.')
+ describe "#to_h" do
+ it "serializes attributes into hash" do
+ entity = described_class.new(id: 1, name: "Acme Inc.")
- expect(entity.to_h).to eq(Hash[id: 1, name: 'Acme Inc.'])
+ expect(entity.to_h).to eq(Hash[id: 1, name: "Acme Inc."])
end
- it 'must be an instance of ::Hash' do
+ it "must be an instance of ::Hash" do
entity = described_class.new
expect(entity.to_h).to be_an_instance_of(::Hash)
end
- it 'ignores unknown attributes' do
- entity = described_class.new(foo: 'bar')
+ it "ignores unknown attributes" do
+ entity = described_class.new(foo: "bar")
expect(entity.to_h).to eq(Hash[])
end
- it 'prevents information escape' do
+ it "prevents information escape" do
entity = described_class.new(users: users = [User.new(id: 1), User.new(id: 2)])
entity.to_h[:users].reverse!
expect(entity.users).to eq(users)
end
- it 'is aliased as #to_hash' do
- entity = described_class.new(name: 'Acme Inc.')
+ it "is aliased as #to_hash" do
+ entity = described_class.new(name: "Acme Inc.")
expect(entity.to_hash).to eq(entity.to_h)
end
end
- describe '#respond_to?' do
- it 'returns ture for id' do
+ describe "#respond_to?" do
+ it "returns ture for id" do
entity = described_class.new
expect(entity).to respond_to(:id)
end
- it 'returns true for methods with the same name of attributes defined by schema' do
+ it "returns true for methods with the same name of attributes defined by schema" do
entity = described_class.new
expect(entity).to respond_to(:name)
end
- it 'returns false for methods not in the set of attributes defined by schema' do
- entity = described_class.new(foo: 'bar')
+ it "returns false for methods not in the set of attributes defined by schema" do
+ entity = described_class.new(foo: "bar")
expect(entity).to_not respond_to(:foo)
end
diff --git a/spec/unit/hanami/entity/manual_schema/strict_spec.rb b/spec/unit/hanami/entity/manual_schema/strict_spec.rb
index be0c9f5f..ac9ba047 100644
--- a/spec/unit/hanami/entity/manual_schema/strict_spec.rb
+++ b/spec/unit/hanami/entity/manual_schema/strict_spec.rb
@@ -1,5 +1,7 @@
-RSpec.describe Hanami::Entity do
- describe 'manual schema (strict)' do
+# frozen_string_literal: true
+
+RSpec.describe Hanami::Entity, skip: true do
+ describe "manual schema (strict)" do
let(:described_class) { Person }
let(:input) do
@@ -10,21 +12,21 @@ def to_hash
end.new
end
- describe '#initialize' do
+ describe "#initialize" do
it "can't be instantiated without attributes" do
- expect { described_class.new }.to raise_error(ArgumentError, ":id is missing in Hash input")
+ expect { described_class.new }.to raise_error(Hanami::Model::Error, /:id is missing in Hash input/)
end
it "can't be instantiated with empty hash" do
- expect { described_class.new({}) }.to raise_error(ArgumentError, ":id is missing in Hash input")
+ expect { described_class.new({}) }.to raise_error(Hanami::Model::Error, /:id is missing in Hash input/)
end
it "can't be instantiated with partial data" do
- expect { described_class.new(id: 1) }.to raise_error(ArgumentError, ":name is missing in Hash input")
+ expect { described_class.new(id: 1) }.to raise_error(Hanami::Model::Error, /:name is missing in Hash input/)
end
it "can't be instantiated with unknown data" do
- expect { described_class.new(id: 1, name: "Luca", foo: "bar") }.to raise_error(ArgumentError, "unexpected keys [:foo] in Hash input")
+ expect { described_class.new(id: 1, name: "Luca", foo: "bar") }.to raise_error(Hanami::Model::Error, /unexpected keys \[:foo\] in Hash input/)
end
it "can be instantiated with full data" do
@@ -34,21 +36,23 @@ def to_hash
expect(entity.name).to eq("Luca")
end
- it 'accepts object that implements #to_hash' do
+ it "accepts object that implements #to_hash" do
entity = described_class.new(input)
expect(entity.id).to eq(2)
expect(entity.name).to eq("MG")
end
- it 'freezes the instance' do
+ it "freezes the instance" do
entity = described_class.new(id: 1, name: "Luca")
expect(entity).to be_frozen
end
it "fails if values aren't of the expected type" do
- expect { described_class.new(id: "1", name: "Luca") }.to raise_error(TypeError, %("1" (String) has invalid type for :id violates constraints (type?(Integer, "1") failed)))
+ expect { described_class.new(id: "1", name: "Luca") }.to raise_error(Hanami::Model::Error) do |exception|
+ expect(exception.message).to include(%("1" (String) has invalid type for :id violates constraints (type?(Integer, "1") failed)))
+ end
end
end
end
diff --git a/spec/unit/hanami/entity/manual_schema/types_spec.rb b/spec/unit/hanami/entity/manual_schema/types_spec.rb
index 37bb85a4..e63d20c4 100644
--- a/spec/unit/hanami/entity/manual_schema/types_spec.rb
+++ b/spec/unit/hanami/entity/manual_schema/types_spec.rb
@@ -1,19 +1,19 @@
-RSpec.describe Hanami::Entity do
- describe 'manual schema (types)' do
- [nil, :schema, :strict, :weak, :permissive, :strict_with_defaults, :symbolized].each do |type|
+# frozen_string_literal: true
+
+RSpec.describe Hanami::Entity, skip: true do
+ describe "manual schema (types)" do
+ %i[strict struct].each do |type|
it "allows to build schema with #{type.inspect}" do
- Class.new(described_class) do
- attributes(type) {}
- end
+ Class.new(described_class[type])
end
end
it "raises error for unknown type" do
- expect do
- Class.new(described_class) do
- attributes(:unknown) {}
- end
- end.to raise_error(Hanami::Model::Error, "Unknown schema type: `:unknown'")
+ [nil, :unknown].each do |type|
+ expect do
+ Class.new(described_class[type])
+ end.to raise_error(Hanami::Model::Error, "Unknown schema type: `#{type.inspect}'")
+ end
end
end
end
diff --git a/spec/unit/hanami/entity/schema/definition_spec.rb b/spec/unit/hanami/entity/schema/definition_spec.rb
deleted file mode 100644
index e25b4e3c..00000000
--- a/spec/unit/hanami/entity/schema/definition_spec.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-RSpec.describe Hanami::Entity::Schema::Definition do
- let(:described_class) { Hanami::Entity::Schema::Definition }
- let(:subject) do
- described_class.new do
- attribute :id, Hanami::Model::Types::Coercible::Int
- end
- end
-
- describe '#initialize' do
- it 'returns frozen instance' do
- subject = described_class.new {}
-
- expect(subject).to be_frozen
- end
-
- it "raises error if block isn't given" do
- expect { described_class.new }.to raise_error(LocalJumpError)
- end
- end
-
- describe '#call' do
- it 'returns empty hash when nil is given' do
- result = subject.call(nil)
-
- expect(result).to eq({})
- end
-
- it 'processes attributes' do
- result = subject.call(id: 1)
-
- expect(result).to eq(id: 1)
- end
-
- it 'ignores unknown attributes' do
- result = subject.call(foo: 'bar')
-
- expect(result).to eq({})
- end
-
- it 'raises error if the process fails' do
- message = Platform.match do
- engine(:jruby) { "no implicit conversion of Symbol into Integer" }
- default { "can't convert Symbol into Integer" }
- end
-
- expect { subject.call(id: :foo) }.to raise_error(TypeError, message)
- end
- end
-
- describe '#attribute?' do
- it 'returns true for known attributes' do
- expect(subject.attribute?(:id)).to eq(true)
- end
-
- it 'returns false for unknown attributes' do
- expect(subject.attribute?(:foo)).to eq(false)
- end
- end
-end
diff --git a/spec/unit/hanami/entity/schema/schemaless_spec.rb b/spec/unit/hanami/entity/schema/schemaless_spec.rb
deleted file mode 100644
index 9405f666..00000000
--- a/spec/unit/hanami/entity/schema/schemaless_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-RSpec.describe Hanami::Entity::Schema::Schemaless do
- let(:subject) { Hanami::Entity::Schema::Schemaless.new }
-
- describe '#initialize' do
- it 'returns frozen instance' do
- expect(subject).to be_frozen
- end
- end
-
- describe '#call' do
- it 'returns empty hash when nil is given' do
- result = subject.call(nil)
-
- expect(result).to eq({})
- end
-
- it 'returns duped hash' do
- input = { foo: 'bar' }
- result = subject.call(input)
-
- expect(result).to eq(input)
- expect(result.object_id).to_not eq(input.object_id)
- end
- end
-
- describe '#attribute?' do
- it 'always returns true' do
- expect(subject.attribute?(:foo)).to eq(true)
- end
- end
-end
diff --git a/spec/unit/hanami/entity/schema_spec.rb b/spec/unit/hanami/entity/schema_spec.rb
deleted file mode 100644
index 93426ed2..00000000
--- a/spec/unit/hanami/entity/schema_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-RSpec.describe Hanami::Entity::Schema do
- let(:described_class) { Hanami::Entity::Schema }
-
- describe 'without definition' do
- let(:subject) { described_class.new }
-
- describe '#call' do
- it 'processes attributes' do
- result = subject.call('foo' => 'bar')
-
- expect(result).to eq(foo: 'bar')
- end
- end
-
- describe '#attribute?' do
- it 'always returns true' do
- expect(subject.attribute?(:foo)).to eq true
- end
- end
- end
-
- describe 'with definition' do
- let(:subject) do
- described_class.new do
- attribute :id, Hanami::Model::Types::Coercible::Int
- end
- end
-
- describe '#call' do
- it 'processes attributes' do
- result = subject.call(id: '1')
-
- expect(result).to eq(id: 1)
- end
-
- it 'ignores unknown attributes' do
- result = subject.call(foo: 'bar')
-
- expect(result).to eq({})
- end
- end
-
- describe '#attribute?' do
- it 'returns true for known attributes' do
- expect(subject.attribute?(:id)).to eq true
- end
-
- it 'returns false for unknown attributes' do
- expect(subject.attribute?(:foo)).to eq false
- end
- end
- end
-end
diff --git a/spec/unit/hanami/entity/schemaless_spec.rb b/spec/unit/hanami/entity/schemaless_spec.rb
index a8cabe13..d888ee49 100644
--- a/spec/unit/hanami/entity/schemaless_spec.rb
+++ b/spec/unit/hanami/entity/schemaless_spec.rb
@@ -1,5 +1,7 @@
+# frozen_string_literal: true
+
RSpec.describe Hanami::Entity do
- describe 'schemaless' do
+ describe "schemaless" do
let(:described_class) do
Class.new(Hanami::Entity)
end
@@ -12,112 +14,112 @@ def to_hash
end.new
end
- describe '#initialize' do
- it 'can be instantiated without attributes' do
+ describe "#initialize" do
+ it "can be instantiated without attributes" do
entity = described_class.new
expect(entity).to be_a_kind_of(described_class)
end
- it 'accepts a hash' do
- entity = described_class.new(foo: 1, 'bar' => 2)
+ it "accepts a hash" do
+ entity = described_class.new(foo: 1, "bar" => 2)
expect(entity.foo).to eq(1)
expect(entity.bar).to eq(2)
end
- it 'accepts object that implements #to_hash' do
+ it "accepts object that implements #to_hash" do
entity = described_class.new(input)
expect(entity.a).to eq(1)
end
- it 'freezes the instance' do
+ it "freezes the instance" do
entity = described_class.new
expect(entity).to be_frozen
end
end
- describe '#id' do
- it 'returns the value' do
+ describe "#id" do
+ it "returns the value" do
entity = described_class.new(id: 1)
expect(entity.id).to eq(1)
end
- it 'returns nil if not present in attributes' do
+ it "returns nil if not present in attributes" do
entity = described_class.new
expect(entity.id).to be_nil
end
end
- describe 'accessors' do
- it 'exposes accessors for given keys' do
- entity = described_class.new(name: 'Luca')
+ describe "accessors" do
+ it "exposes accessors for given keys" do
+ entity = described_class.new(name: "Luca")
- expect(entity.name).to eq('Luca')
+ expect(entity.name).to eq("Luca")
end
- it 'returns nil for unknown methods' do
+ it "raises error for unknown methods" do
entity = described_class.new
- expect(entity.foo).to be_nil
+ expect { entity.foo }.to raise_error(Hanami::Model::MissingAttributeError)
end
- it 'returns nil for #attributes' do
+ it "returns empty hash for #attributes" do
entity = described_class.new
- expect(entity.attributes).to be_nil
+ expect(entity.attributes).to eq({})
end
end
- describe '#to_h' do
- it 'serializes attributes into hash' do
- entity = described_class.new(foo: 1, 'bar' => { 'baz' => 2 })
+ describe "#to_h" do
+ it "serializes attributes into hash" do
+ entity = described_class.new(foo: 1, "bar" => { "baz" => 2 })
- expect(entity.to_h).to eq(Hash[foo: 1, bar: { baz: 2 }])
+ expect(entity.to_h).to eq(::Hash[foo: 1, bar: { baz: 2 }])
end
- it 'must be an instance of ::Hash' do
+ it "must be an instance of ::Hash" do
entity = described_class.new
expect(entity.to_h).to be_an_instance_of(::Hash)
end
- it 'prevents information escape' do
+ it "prevents information escape" do
entity = described_class.new(a: [1, 2, 3])
entity.to_h[:a].reverse!
expect(entity.a).to eq([1, 2, 3])
end
- it 'is aliased as #to_hash' do
- entity = described_class.new(foo: 'bar')
+ it "is aliased as #to_hash" do
+ entity = described_class.new(foo: "bar")
expect(entity.to_h).to eq(entity.to_hash)
end
end
- describe '#respond_to?' do
- it 'returns ture for id' do
+ describe "#respond_to?" do
+ it "returns ture for id" do
entity = described_class.new
expect(entity).to respond_to(:id)
end
- it 'returns true for present keys' do
- entity = described_class.new(foo: 1, 'bar' => 2)
+ it "returns true for present keys" do
+ entity = described_class.new(foo: 1, "bar" => 2)
expect(entity).to respond_to(:foo)
expect(entity).to respond_to(:bar)
end
- it 'returns false for missing keys' do
+ it "returns false for missing keys" do
entity = described_class.new
- expect(entity).to respond_to(:baz)
+ expect(entity).to_not respond_to(:baz)
end
end
end
diff --git a/spec/unit/hanami/entity_spec.rb b/spec/unit/hanami/entity_spec.rb
index 36c48cc8..e425b3f2 100644
--- a/spec/unit/hanami/entity_spec.rb
+++ b/spec/unit/hanami/entity_spec.rb
@@ -1,40 +1,42 @@
-require 'ostruct'
+# frozen_string_literal: true
-RSpec.describe Hanami::Entity do
+require "ostruct"
+
+RSpec.describe Hanami::Entity, skip: true do
let(:described_class) do
- Class.new(Hanami::Entity)
+ Class.new(Hanami::Entity[:struct])
end
- describe 'equality' do
- it 'returns true if same class and same id' do
+ describe "equality" do
+ it "returns true if same class and same id" do
entity1 = described_class.new(id: 1)
entity2 = described_class.new(id: 1)
expect(entity1).to eq(entity2), "Expected #{entity1.inspect} to equal #{entity2.inspect}"
end
- it 'returns false if same class but different id' do
+ it "returns false if same class but different id" do
entity1 = described_class.new(id: 1)
entity2 = described_class.new(id: 1000)
expect(entity1).to_not eq(entity2), "Expected #{entity1.inspect} to NOT equal #{entity2.inspect}"
end
- it 'returns false if different class but same id' do
+ it "returns false if different class but same id" do
entity1 = described_class.new(id: 1)
entity2 = OpenStruct.new(id: 1)
expect(entity1).to_not eq(entity2), "Expected #{entity1.inspect} to NOT equal #{entity2.inspect}"
end
- it 'returns false if different class and different id' do
+ it "returns false if different class and different id" do
entity1 = described_class.new(id: 1)
entity2 = OpenStruct.new(id: 1000)
expect(entity1).to_not eq(entity2), "Expected #{entity1.inspect} to NOT equal #{entity2.inspect}"
end
- it 'returns true when both the ids are nil' do
+ it "returns true when both the ids are nil" do
entity1 = described_class.new
entity2 = described_class.new
@@ -42,31 +44,31 @@
end
end
- describe '#hash' do
- it 'returns predictable object hashing' do
+ describe "#hash" do
+ it "returns predictable object hashing" do
entity1 = described_class.new(id: 1)
entity2 = described_class.new(id: 1)
expect(entity1.hash).to eq(entity2.hash), "Expected #{entity1.hash} to equal #{entity2.hash}"
end
- it 'returns different object hash for same class but different id' do
+ it "returns different object hash for same class but different id" do
entity1 = described_class.new(id: 1)
entity2 = described_class.new(id: 1000)
expect(entity1.hash).to_not eq(entity2.hash), "Expected #{entity1.hash} to NOT equal #{entity2.hash}"
end
- it 'returns different object hash for different class but same id' do
+ it "returns different object hash for different class but same id" do
entity1 = described_class.new(id: 1)
- entity2 = Class.new(Hanami::Entity).new(id: 1)
+ entity2 = Class.new(Hanami::OldEntity).new(id: 1)
expect(entity1.hash).to_not eq(entity2.hash), "Expected #{entity1.hash} to NOT equal #{entity2.hash}"
end
- it 'returns different object hash for different class and different id' do
+ it "returns different object hash for different class and different id" do
entity1 = described_class.new(id: 1)
- entity2 = Class.new(Hanami::Entity).new(id: 2)
+ entity2 = Class.new(Hanami::OldEntity).new(id: 2)
expect(entity1.hash).to_not eq(entity2.hash), "Expected #{entity1.hash} to NOT equal #{entity2.hash}"
end
diff --git a/spec/unit/hanami/model/check_constraint_validation_error_spec.rb b/spec/unit/hanami/model/check_constraint_validation_error_spec.rb
index f1d4dfa6..5593e9c5 100644
--- a/spec/unit/hanami/model/check_constraint_validation_error_spec.rb
+++ b/spec/unit/hanami/model/check_constraint_validation_error_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
RSpec.describe Hanami::Model::CheckConstraintViolationError do
it "inherits from Hanami::Model::ConstraintViolationError" do
expect(described_class.ancestors).to include(Hanami::Model::ConstraintViolationError)
diff --git a/spec/unit/hanami/model/configuration_spec.rb b/spec/unit/hanami/model/configuration_spec.rb
index 8de0a34e..4d95b0f8 100644
--- a/spec/unit/hanami/model/configuration_spec.rb
+++ b/spec/unit/hanami/model/configuration_spec.rb
@@ -1,9 +1,11 @@
+# frozen_string_literal: true
+
RSpec.describe Hanami::Model::Configuration do
before do
- database_directory = Pathname.pwd.join('tmp', 'db')
- database_directory.join('migrations').mkpath
+ database_directory = Pathname.pwd.join("tmp", "db")
+ database_directory.join("migrations").mkpath
- FileUtils.touch database_directory.join('schema.sql')
+ FileUtils.touch database_directory.join("schema.sql")
end
let(:subject) { Hanami::Model::Configuration.new(configurator) }
@@ -14,79 +16,116 @@
Hanami::Model::Configurator.build do
adapter :sql, adapter_url
- migrations 'tmp/db/migrations'
- schema 'tmp/db/schema.sql'
+ migrations "tmp/db/migrations"
+ schema "tmp/db/schema.sql"
end
end
- let(:url) do
- db = 'tmp/db/bookshelf.sqlite'
-
- Platform.match do
- engine(:ruby) { "sqlite://#{db}" }
- engine(:jruby) { "jdbc:sqlite://#{db}" }
- end
- end
+ let(:url) { ENV["HANAMI_DATABASE_URL"] }
- describe '#url' do
- it 'equals to the configured url' do
+ describe "#url" do
+ it "equals to the configured url" do
expect(subject.url).to eq(url)
end
end
- describe '#connection' do
- it 'returns a raw connection aganist the database' do
+ describe "#connection" do
+ it "returns a raw connection aganist the database" do
connection = subject.connection
expect(connection).to be_a_kind_of(Sequel::Database)
expect(connection.url).to eq(url)
end
- context 'with blank url' do
+ context "with nil url" do
let(:url) { nil }
- it 'raises error' do
+ it "raises error" do
+ expect { subject.connection }.to raise_error(Hanami::Model::UnknownDatabaseAdapterError, "Unknown database adapter for URL: #{url.inspect}. Please check your database configuration (hint: ENV['DATABASE_URL']).")
+ end
+ end
+
+ context "with blank url" do
+ let(:url) { "" }
+
+ it "raises error" do
expect { subject.connection }.to raise_error(Hanami::Model::UnknownDatabaseAdapterError, "Unknown database adapter for URL: #{url.inspect}. Please check your database configuration (hint: ENV['DATABASE_URL']).")
end
end
end
- describe '#gateway' do
- it 'returns default ROM gateway' do
+ describe "#gateway" do
+ it "returns default ROM gateway" do
gateway = subject.gateway
expect(gateway).to be_a_kind_of(ROM::Gateway)
expect(gateway.connection).to eq(subject.connection)
end
- context 'with blank url' do
+ context "with nil url" do
let(:url) { nil }
- it 'raises error' do
+ it "raises error" do
+ expect { subject.connection }.to raise_error(Hanami::Model::UnknownDatabaseAdapterError, "Unknown database adapter for URL: #{url.inspect}. Please check your database configuration (hint: ENV['DATABASE_URL']).")
+ end
+ end
+
+ context "with blank url" do
+ let(:url) { "" }
+
+ it "raises error" do
expect { subject.connection }.to raise_error(Hanami::Model::UnknownDatabaseAdapterError, "Unknown database adapter for URL: #{url.inspect}. Please check your database configuration (hint: ENV['DATABASE_URL']).")
end
end
end
- describe '#root' do
- it 'returns current directory' do
+ describe "#root" do
+ it "returns current directory" do
expect(subject.root).to eq(Pathname.pwd)
end
end
- describe '#migrations' do
- it 'returns path to migrations' do
- expected = subject.root.join('tmp', 'db', 'migrations')
+ describe "#migrations" do
+ it "returns path to migrations" do
+ expected = subject.root.join("tmp", "db", "migrations")
expect(subject.migrations).to eq(expected)
end
end
- describe '#schema' do
- it 'returns path to database schema' do
- expected = subject.root.join('tmp', 'db', 'schema.sql')
+ describe "#schema" do
+ it "returns path to database schema" do
+ expected = subject.root.join("tmp", "db", "schema.sql")
expect(subject.schema).to eq(expected)
end
end
+
+ describe "#inflector" do
+ let(:inflector) { Dry::Inflector.new }
+
+ it "returns dry-inflector" do
+ expect(subject.inflector).to be_a_kind_of(Dry::Inflector)
+ end
+
+ it "allows to pass inflector to config" do
+ configurator.inflector(inflector)
+
+ expect(subject.inflector).to eq(inflector)
+ end
+
+ describe "configuration" do
+ let(:configurator) do
+ Hanami::Model::Configurator.build do
+ inflector do |rule|
+ rule.plural "virus", "viruses"
+ end
+ end
+ end
+
+ it "allows to configure inflector rules" do
+ expect(subject.inflector.pluralize("virus")).to eq("viruses")
+ end
+ end
+ end
end
diff --git a/spec/unit/hanami/model/constraint_violation_error_spec.rb b/spec/unit/hanami/model/constraint_violation_error_spec.rb
index cebfec4a..a3d4f46f 100644
--- a/spec/unit/hanami/model/constraint_violation_error_spec.rb
+++ b/spec/unit/hanami/model/constraint_violation_error_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
RSpec.describe Hanami::Model::ConstraintViolationError do
it "inherits from Hanami::Model::Error" do
expect(described_class.ancestors).to include(Hanami::Model::Error)
diff --git a/spec/unit/hanami/model/disconnect_spec.rb b/spec/unit/hanami/model/disconnect_spec.rb
index c74c1dda..81b4f0fd 100644
--- a/spec/unit/hanami/model/disconnect_spec.rb
+++ b/spec/unit/hanami/model/disconnect_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This test is tightly coupled to Sequel
#
# We should improve connection management via ROM
diff --git a/spec/unit/hanami/model/error_spec.rb b/spec/unit/hanami/model/error_spec.rb
index 4544359d..8bb5b813 100644
--- a/spec/unit/hanami/model/error_spec.rb
+++ b/spec/unit/hanami/model/error_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
RSpec.describe Hanami::Model::Error do
it "inherits from StandardError" do
expect(described_class.ancestors).to include(StandardError)
diff --git a/spec/unit/hanami/model/foreign_key_constraint_violation_error_spec.rb b/spec/unit/hanami/model/foreign_key_constraint_violation_error_spec.rb
index 3cd73013..4d76215c 100644
--- a/spec/unit/hanami/model/foreign_key_constraint_violation_error_spec.rb
+++ b/spec/unit/hanami/model/foreign_key_constraint_violation_error_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
RSpec.describe Hanami::Model::ForeignKeyConstraintViolationError do
it "inherits from Hanami::Model::ConstraintViolationError" do
expect(described_class.ancestors).to include(Hanami::Model::ConstraintViolationError)
diff --git a/spec/unit/hanami/model/load_spec.rb b/spec/unit/hanami/model/load_spec.rb
index 3cafdf5c..0fd46677 100644
--- a/spec/unit/hanami/model/load_spec.rb
+++ b/spec/unit/hanami/model/load_spec.rb
@@ -1,4 +1,6 @@
-RSpec.describe "Hanami::Model.load!" do
+# frozen_string_literal: true
+
+RSpec.describe "Hanami::Model.configuration.load!" do
let(:message) { "Cannot find corresponding type for form" }
before do
@@ -6,6 +8,6 @@
end
it "raises unknown database error when repository automapping spots an unknown type" do
- expect { Hanami::Model.load! }.to raise_error(Hanami::Model::UnknownDatabaseTypeError, message)
+ expect { Hanami::Model.configuration.load!(Hanami::Model.repositories) }.to raise_error(Hanami::Model::UnknownDatabaseTypeError, message)
end
end
diff --git a/spec/unit/hanami/model/mapped_relation_spec.rb b/spec/unit/hanami/model/mapped_relation_spec.rb
index ed159bdd..a1a876f8 100644
--- a/spec/unit/hanami/model/mapped_relation_spec.rb
+++ b/spec/unit/hanami/model/mapped_relation_spec.rb
@@ -1,6 +1,8 @@
+# frozen_string_literal: true
+
RSpec.describe Hanami::Model::MappedRelation do
subject { described_class.new(relation) }
- let(:relation) { UserRepository.new.users }
+ let(:relation) { UserRepository.new(configuration: configuration).users }
describe "#[]" do
it "returns attribute" do
diff --git a/spec/unit/hanami/model/migrator/adapter_spec.rb b/spec/unit/hanami/model/migrator/adapter_spec.rb
index e4fe9a91..13de55ca 100644
--- a/spec/unit/hanami/model/migrator/adapter_spec.rb
+++ b/spec/unit/hanami/model/migrator/adapter_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
RSpec.describe Hanami::Model::Migrator::Adapter do
extend PlatformHelpers
@@ -12,7 +14,7 @@
end
let(:configuration) { instance_double("Hanami::Model::Configuration") }
- let(:url) { ENV['HANAMI_DATABASE_URL'] }
+ let(:url) { ENV["HANAMI_DATABASE_URL"] }
with_platform(db: :sqlite) do
context "when sqlite" do
diff --git a/spec/unit/hanami/model/migrator/connection_spec.rb b/spec/unit/hanami/model/migrator/connection_spec.rb
index aaecf3a0..74c02819 100644
--- a/spec/unit/hanami/model/migrator/connection_spec.rb
+++ b/spec/unit/hanami/model/migrator/connection_spec.rb
@@ -1,110 +1,116 @@
+# frozen_string_literal: true
+
RSpec.describe Hanami::Model::Migrator::Connection do
extend PlatformHelpers
let(:connection) { Hanami::Model::Migrator::Connection.new(hanami_model_configuration) }
- describe 'when not a jdbc connection' do
- let(:hanami_model_configuration) { OpenStruct.new(url: url) }
+ describe "when not a jdbc connection" do
+ let(:hanami_model_configuration) { OpenStruct.new(url: url, migrations_logger: Hanami::Model::Migrator::Logger.new(StringIO.new)) }
let(:url) { "postgresql://postgres:s3cr3T@127.0.0.1:5432/database" }
- describe '#jdbc?' do
- it 'returns false' do
+ describe "#jdbc?" do
+ it "returns false" do
expect(connection.jdbc?).to eq(false)
end
end
- describe '#global_uri' do
- it 'returns connection URI without database' do
- expect(connection.global_uri.scan('database').empty?).to eq(true)
+ describe "#global_uri" do
+ it "returns connection URI without database" do
+ expect(connection.global_uri.scan("database").empty?).to eq(true)
end
end
- describe '#parsed_uri?' do
- it 'returns an URI instance' do
+ describe "#parsed_uri?" do
+ it "returns an URI instance" do
expect(connection.parsed_uri).to be_a_kind_of(URI)
end
end
- describe '#host' do
- describe 'when the host is only specified in the URI' do
+ describe "#host" do
+ it "returns configured host" do
+ expect(connection.host).to eq("127.0.0.1")
+ end
+
+ describe "when the host is only specified in the URI" do
let(:url) { "postgresql://127.0.0.1/database" }
- it 'returns configured host' do
- expect(connection.host).to eq('127.0.0.1')
+ it "returns configured host" do
+ expect(connection.host).to eq("127.0.0.1")
end
end
- describe 'when the host is only specified in the query' do
+ describe "when the host is only specified in the query" do
let(:url) { "postgresql:///database?host=0.0.0.0" }
- it 'returns the host specified in the query param' do
- expect(connection.host).to eql('0.0.0.0')
+ it "returns the host specified in the query param" do
+ expect(connection.host).to eql("0.0.0.0")
end
end
- describe 'when the host is specified as a socket' do
+ describe "when the host is specified as a socket" do
let(:url) { "postgresql:///database?host=/path/to/my/sock" }
- it 'returns the path to the socket specified in the query param' do
- expect(connection.host).to eql('/path/to/my/sock')
+ it "returns the path to the socket specified in the query param" do
+ expect(connection.host).to eql("/path/to/my/sock")
end
end
- describe 'when the host is specified in both the URI and query' do
+ describe "when the host is specified in both the URI and query" do
let(:url) { "postgresql://127.0.0.1/database?host=0.0.0.0" }
- it 'prefers the host from the URI' do
- expect(connection.host).to eql('127.0.0.1')
+ it "prefers the host from the URI" do
+ expect(connection.host).to eql("127.0.0.1")
end
end
end
- describe '#port' do
- it 'returns configured port' do
+ describe "#port" do
+ it "returns configured port" do
expect(connection.port).to eq(5432)
end
end
- describe '#database' do
- it 'returns configured database' do
- expect(connection.database).to eq('database')
+ describe "#database" do
+ it "returns configured database" do
+ expect(connection.database).to eq("database")
end
end
- describe '#user' do
- it 'returns configured user' do
- expect(connection.user).to eq('postgres')
+ describe "#user" do
+ it "returns configured user" do
+ expect(connection.user).to eq("postgres")
end
- describe 'when there is no user option' do
+ describe "when there is no user option" do
let(:hanami_model_configuration) do
- OpenStruct.new(url: 'postgresql://127.0.0.1:5432/database')
+ OpenStruct.new(url: "postgresql://127.0.0.1:5432/database")
end
- it 'returns nil' do
+ it "returns nil" do
expect(connection.user).to be_nil
end
end
end
- describe '#password' do
- it 'returns configured password' do
- expect(connection.password).to eq('s3cr3T')
+ describe "#password" do
+ it "returns configured password" do
+ expect(connection.password).to eq("s3cr3T")
end
- describe 'when there is no password option' do
+ describe "when there is no password option" do
let(:hanami_model_configuration) do
- OpenStruct.new(url: 'postgresql://127.0.0.1/database')
+ OpenStruct.new(url: "postgresql://127.0.0.1/database")
end
- it 'returns nil' do
+ it "returns nil" do
expect(connection.password).to be_nil
end
end
end
describe "#raw" do
- let(:url) { ENV['HANAMI_DATABASE_URL'] }
+ let(:url) { ENV["HANAMI_DATABASE_URL"] }
with_platform(db: :sqlite) do
context "when sqlite" do
@@ -147,107 +153,107 @@
end
# See https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING
- describe 'when connection components in uri params' do
+ describe "when connection components in uri params" do
let(:hanami_model_configuration) do
OpenStruct.new(
- url: 'postgresql:///mydb?host=localhost&port=6433&user=postgres&password=testpasswd'
+ url: "postgresql:///mydb?host=localhost&port=6433&user=postgres&password=testpasswd"
)
end
- it 'returns configured database' do
- expect(connection.database).to eq('mydb')
+ it "returns configured database" do
+ expect(connection.database).to eq("mydb")
end
- it 'returns configured user' do
- expect(connection.user).to eq('postgres')
+ it "returns configured user" do
+ expect(connection.user).to eq("postgres")
end
- it 'returns configured password' do
- expect(connection.password).to eq('testpasswd')
+ it "returns configured password" do
+ expect(connection.password).to eq("testpasswd")
end
- it 'returns configured host' do
- expect(connection.host).to eq('localhost')
+ it "returns configured host" do
+ expect(connection.host).to eq("localhost")
end
- it 'returns configured port' do
+ it "returns configured port" do
expect(connection.port).to eq(6433)
end
- describe 'with blank port' do
+ describe "with blank port" do
let(:hanami_model_configuration) do
OpenStruct.new(
- url: 'postgresql:///mydb?host=localhost&port=&user=postgres&password=testpasswd'
+ url: "postgresql:///mydb?host=localhost&port=&user=postgres&password=testpasswd"
)
end
- it 'raises an error' do
+ it "raises an error" do
expect(connection.port).to be_nil
end
end
end
end
- describe 'when jdbc connection' do
+ describe "when jdbc connection" do
let(:hanami_model_configuration) do
OpenStruct.new(
- url: 'jdbc:postgresql://127.0.0.1:5432/database?user=postgres&password=s3cr3T'
+ url: "jdbc:postgresql://127.0.0.1:5432/database?user=postgres&password=s3cr3T"
)
end
- describe '#jdbc?' do
- it 'returns true' do
+ describe "#jdbc?" do
+ it "returns true" do
expect(connection.jdbc?).to eq(true)
end
end
- describe '#host' do
- it 'returns configured host' do
- expect(connection.host).to eq('127.0.0.1')
+ describe "#host" do
+ it "returns configured host" do
+ expect(connection.host).to eq("127.0.0.1")
end
end
- describe '#port' do
- it 'returns configured port' do
+ describe "#port" do
+ it "returns configured port" do
expect(connection.port).to eq(5432)
end
end
- describe '#user' do
- it 'returns configured user' do
- expect(connection.user).to eq('postgres')
+ describe "#user" do
+ it "returns configured user" do
+ expect(connection.user).to eq("postgres")
end
- describe 'when there is no user option' do
+ describe "when there is no user option" do
let(:hanami_model_configuration) do
- OpenStruct.new(url: 'jdbc:postgresql://127.0.0.1/database')
+ OpenStruct.new(url: "jdbc:postgresql://127.0.0.1/database")
end
- it 'returns nil' do
+ it "returns nil" do
expect(connection.user).to be_nil
end
end
end
- describe '#password' do
- it 'returns configured password' do
- expect(connection.password).to eq('s3cr3T')
+ describe "#password" do
+ it "returns configured password" do
+ expect(connection.password).to eq("s3cr3T")
end
- describe 'when there is no password option' do
+ describe "when there is no password option" do
let(:hanami_model_configuration) do
- OpenStruct.new(url: 'jdbc:postgresql://127.0.0.1/database')
+ OpenStruct.new(url: "jdbc:postgresql://127.0.0.1/database")
end
- it 'returns nil' do
+ it "returns nil" do
expect(connection.password).to be_nil
end
end
end
- describe '#database' do
- it 'returns configured database' do
- expect(connection.database).to eq('database')
+ describe "#database" do
+ it "returns configured database" do
+ expect(connection.database).to eq("database")
end
end
end
diff --git a/spec/unit/hanami/model/migrator/mysql.rb b/spec/unit/hanami/model/migrator/mysql.rb
index de0d0f41..69f380c5 100644
--- a/spec/unit/hanami/model/migrator/mysql.rb
+++ b/spec/unit/hanami/model/migrator/mysql.rb
@@ -1,7 +1,9 @@
-require 'ostruct'
-require 'securerandom'
+# frozen_string_literal: true
-RSpec.shared_examples 'migrator_mysql' do
+require "ostruct"
+require "securerandom"
+
+RSpec.shared_examples "migrator_mysql" do
let(:migrator) do
Hanami::Model::Migrator.new(configuration: configuration)
end
@@ -9,9 +11,9 @@
let(:random) { SecureRandom.hex(4) }
# General variables
- let(:migrations) { Pathname.new(__dir__ + '/../../../../support/fixtures/migrations') }
+ let(:migrations) { Pathname.new(__dir__ + "/../../../../support/fixtures/migrations") }
let(:schema) { nil }
- let(:config) { OpenStruct.new(backend: :sql, url: url, _migrations: migrations, _schema: schema, migrations_logger: Hanami::Model::Migrator::Logger.new(ENV['HANAMI_DATABASE_LOGGER'])) }
+ let(:config) { OpenStruct.new(backend: :sql, url: url, _migrations: migrations, _schema: schema, migrations_logger: Hanami::Model::Migrator::Logger.new(ENV["HANAMI_DATABASE_LOGGER"])) }
let(:configuration) { Hanami::Model::Configuration.new(config) }
# Variables for `apply` and `prepare`
@@ -23,14 +25,14 @@
migrator.drop rescue nil # rubocop:disable Style/RescueModifier
end
- describe 'MySQL' do
+ describe "MySQL" do
let(:database) { "mysql_#{random}" }
let(:url) do
db = database
credentials = [
- ENV['HANAMI_DATABASE_USERNAME'],
- ENV['HANAMI_DATABASE_PASSWORD']
+ ENV["HANAMI_DATABASE_USERNAME"],
+ ENV["HANAMI_DATABASE_PASSWORD"]
].compact.join(":")
Platform.match do
@@ -39,8 +41,8 @@
end
end
- describe 'create' do
- it 'creates the database' do
+ describe "create" do
+ it "creates the database" do
migrator.create
connection = Sequel.connect(url)
@@ -56,23 +58,23 @@
end
end
- it 'raises error if database is busy' do
+ it "raises error if database is busy" do
migrator.create
Sequel.connect(url).tables
expect { migrator.create }.to raise_error do |error|
expect(error).to be_a(Hanami::Model::MigrationError)
- expect(error.message).to include('Database creation failed. If the database exists,')
- expect(error.message).to include('then its console may be open. See this issue for more details:')
- expect(error.message).to include('https://github.com/hanami/model/issues/250')
+ expect(error.message).to include("Database creation failed. If the database exists,")
+ expect(error.message).to include("then its console may be open. See this issue for more details:")
+ expect(error.message).to include("https://github.com/hanami/model/issues/250")
end
end
# See https://github.com/hanami/model/issues/381
- describe 'when database name contains a dash' do
+ describe "when database name contains a dash" do
let(:database) { "db-name-create_#{random}" }
- it 'creates the database' do
+ it "creates the database" do
migrator.create
connection = Sequel.connect(url)
@@ -81,12 +83,12 @@
end
end
- describe 'drop' do
+ describe "drop" do
before do
migrator.create
end
- it 'drops the database' do
+ it "drops the database" do
migrator.drop
expect { Sequel.connect(url).tables }.to raise_error(Sequel::DatabaseConnectionError)
end
@@ -108,10 +110,10 @@
end
# See https://github.com/hanami/model/issues/381
- describe 'when database name contains a dash' do
+ describe "when database name contains a dash" do
let(:database) { "db-name-drop_#{random}" }
- it 'drops the database' do
+ it "drops the database" do
migrator.drop
expect { Sequel.connect(url).tables }.to raise_error(Sequel::DatabaseConnectionError)
@@ -119,13 +121,13 @@
end
end
- describe 'migrate' do
+ describe "migrate" do
before do
migrator.create
end
- describe 'when no migrations' do
- let(:migrations) { Pathname.new(__dir__ + '/../../../../support/fixtures/empty_migrations') }
+ describe "when no migrations" do
+ let(:migrations) { Pathname.new(__dir__ + "/../../../../support/fixtures/empty_migrations") }
it "it doesn't alter database" do
migrator.migrate
@@ -135,8 +137,8 @@
end
end
- describe 'when migrations are present' do
- it 'migrates the database' do
+ describe "when migrations are present" do
+ it "migrates the database" do
migrator.migrate
connection = Sequel.connect(url)
@@ -150,7 +152,7 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to be_nil
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('int(11)')
+ expect(options.fetch(:db_type)).to eq("int(11)")
expect(options.fetch(:primary_key)).to eq(true)
expect(options.fetch(:auto_increment)).to eq(true)
@@ -160,21 +162,21 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to be_nil
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('varchar(255)')
+ expect(options.fetch(:db_type)).to eq("varchar(255)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[2] # rating (second migration)
expect(name).to eq(:rating)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('0')
+ expect(options.fetch(:default)).to eq("0")
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('int(11)')
+ expect(options.fetch(:db_type)).to eq("int(11)")
expect(options.fetch(:primary_key)).to eq(false)
end
end
- describe 'when migrations are ran twice' do
+ describe "when migrations are ran twice" do
before do
migrator.migrate
end
@@ -188,13 +190,13 @@
end
end
- describe 'migrate down' do
+ describe "migrate down" do
before do
migrator.migrate
end
- it 'migrates the database' do
- migrator.migrate(version: '20160831073534') # see spec/support/fixtures/migrations
+ it "migrates the database" do
+ migrator.migrate(version: "20160831073534") # see spec/support/fixtures/migrations
connection = Sequel.connect(url)
expect(connection.tables).to_not be_empty
@@ -207,7 +209,7 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to be_nil
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('int(11)')
+ expect(options.fetch(:db_type)).to eq("int(11)")
expect(options.fetch(:primary_key)).to eq(true)
expect(options.fetch(:auto_increment)).to eq(true)
@@ -217,7 +219,7 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to be_nil
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('varchar(255)')
+ expect(options.fetch(:db_type)).to eq("varchar(255)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[2] # rating (rolled back second migration)
@@ -227,13 +229,13 @@
end
end
- describe 'rollback' do
+ describe "rollback" do
before do
migrator.create
end
- describe 'when no migrations' do
- let(:migrations) { Pathname.new(__dir__ + '/../../../../support/fixtures/empty_migrations') }
+ describe "when no migrations" do
+ let(:migrations) { Pathname.new(__dir__ + "/../../../../support/fixtures/empty_migrations") }
it "it doesn't alter database" do
migrator.rollback
@@ -243,8 +245,8 @@
end
end
- describe 'when migrations are present' do
- it 'rollbacks one migration (default)' do
+ describe "when migrations are present" do
+ it "rollbacks one migration (default)" do
migrator.migrate
migrator.rollback
@@ -259,7 +261,7 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to be_nil
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('int(11)')
+ expect(options.fetch(:db_type)).to eq("int(11)")
expect(options.fetch(:primary_key)).to eq(true)
expect(options.fetch(:auto_increment)).to eq(true)
@@ -269,7 +271,7 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to be_nil
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('varchar(255)')
+ expect(options.fetch(:db_type)).to eq("varchar(255)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[2] # rating (second migration)
@@ -277,7 +279,7 @@
expect(options).to eq(nil)
end
- it 'rollbacks several migrations' do
+ it "rollbacks several migrations" do
migrator.migrate
migrator.rollback(steps: 2)
@@ -287,7 +289,7 @@
end
end
- describe 'apply' do
+ describe "apply" do
let(:migrations) { target_migrations }
let(:schema) { root.join("schema-#{random}.sql") }
@@ -300,15 +302,15 @@
clean_migrations
end
- it 'migrates to latest version' do
+ it "migrates to latest version" do
migrator.apply
connection = Sequel.connect(url)
migration = connection[:schema_migrations].to_a.last
- expect(migration.fetch(:filename)).to include('20160831090612') # see spec/support/fixtures/migrations
+ expect(migration.fetch(:filename)).to include("20160831090612") # see spec/support/fixtures/migrations
end
- it 'dumps database schema.sql' do
+ it "dumps database schema.sql" do
migrator.apply
actual = schema.read
@@ -336,7 +338,7 @@
expect(actual).to include %(UNLOCK TABLES;)
end
- it 'deletes all the migrations' do
+ it "deletes all the migrations" do
migrator.apply
expect(target_migrations.children).to be_empty
end
@@ -364,7 +366,7 @@
end
end
- describe 'prepare' do
+ describe "prepare" do
let(:migrations) { target_migrations }
let(:schema) { root.join("schema-#{random}.sql") }
@@ -378,13 +380,13 @@
clean_migrations
end
- it 'creates database, loads schema and migrate' do
+ it "creates database, loads schema and migrate" do
# Simulate already existing schema.sql, without existing database and pending migrations
connection = Sequel.connect(url)
Hanami::Model::Migrator::Adapter.for(configuration).dump
- migration = target_migrations.join('20160831095616_create_abuses.rb')
- File.open(migration, 'w+') do |f|
+ migration = target_migrations.join("20160831095616_create_abuses.rb")
+ File.open(migration, "w+") do |f|
f.write <<~RUBY
Hanami::Model.migration do
change do
@@ -417,7 +419,7 @@
expect(connection.tables).to include(:reviews)
end
- it 'drops the database and recreates it' do
+ it "drops the database and recreates it" do
migrator.prepare
connection = Sequel.connect(url)
@@ -426,24 +428,24 @@
end
end
- describe 'version' do
+ describe "version" do
before do
migrator.create
end
- describe 'when no migrations were ran' do
- it 'returns nil' do
+ describe "when no migrations were ran" do
+ it "returns nil" do
expect(migrator.version).to be_nil
end
end
- describe 'with migrations' do
+ describe "with migrations" do
before do
migrator.migrate
end
- it 'returns current database version' do
- expect(migrator.version).to eq('20160831090612') # see spec/support/fixtures/migrations)
+ it "returns current database version" do
+ expect(migrator.version).to eq("20160831090612") # see spec/support/fixtures/migrations)
end
end
end
diff --git a/spec/unit/hanami/model/migrator/postgresql.rb b/spec/unit/hanami/model/migrator/postgresql.rb
index 0a55499e..77a40e38 100644
--- a/spec/unit/hanami/model/migrator/postgresql.rb
+++ b/spec/unit/hanami/model/migrator/postgresql.rb
@@ -1,7 +1,9 @@
-require 'ostruct'
-require 'securerandom'
+# frozen_string_literal: true
-RSpec.shared_examples 'migrator_postgresql' do
+require "ostruct"
+require "securerandom"
+
+RSpec.shared_examples "migrator_postgresql" do
let(:migrator) do
Hanami::Model::Migrator.new(configuration: configuration)
end
@@ -9,9 +11,9 @@
let(:random) { SecureRandom.hex(4) }
# General variables
- let(:migrations) { Pathname.new(__dir__ + '/../../../../support/fixtures/migrations') }
+ let(:migrations) { Pathname.new(__dir__ + "/../../../../support/fixtures/migrations") }
let(:schema) { nil }
- let(:config) { OpenStruct.new(backend: :sql, url: url, _migrations: migrations, _schema: schema, migrations_logger: Hanami::Model::Migrator::Logger.new(ENV['HANAMI_DATABASE_LOGGER'])) }
+ let(:config) { OpenStruct.new(backend: :sql, url: url, _migrations: migrations, _schema: schema, migrations_logger: Hanami::Model::Migrator::Logger.new(ENV["HANAMI_DATABASE_LOGGER"])) }
let(:configuration) { Hanami::Model::Configuration.new(config) }
# Variables for `apply` and `prepare`
@@ -24,7 +26,7 @@
migrator.drop rescue nil # rubocop:disable Style/RescueModifier
end
- describe 'PostgreSQL' do
+ describe "PostgreSQL" do
let(:database) { random }
let(:url) do
db = database
@@ -35,34 +37,34 @@
end
end
- describe 'create' do
+ describe "create" do
before do
migrator.create
end
- it 'creates the database' do
+ it "creates the database" do
connection = Sequel.connect(url)
expect(connection.tables).to be_empty
end
- it 'raises error if database is busy' do
+ it "raises error if database is busy" do
Sequel.connect(url).tables
expect { migrator.create }.to raise_error do |error|
expect(error).to be_a(Hanami::Model::MigrationError)
- expect(error.message).to include('createdb: database creation failed. If the database exists,')
- expect(error.message).to include('then its console may be open. See this issue for more details:')
- expect(error.message).to include('https://github.com/hanami/model/issues/250')
+ expect(error.message).to include("createdb: database creation failed. If the database exists,")
+ expect(error.message).to include("then its console may be open. See this issue for more details:")
+ expect(error.message).to include("https://github.com/hanami/model/issues/250")
end
end
end
- describe 'drop' do
+ describe "drop" do
before do
migrator.create
end
- it 'drops the database' do
+ it "drops the database" do
migrator.drop
expect { Sequel.connect(url).tables }.to raise_error(Sequel::DatabaseConnectionError)
@@ -80,17 +82,17 @@
before do
# We accomplish having a command not be available by setting PATH
# to an empty string, which means *no commands* are available.
- @original_path = ENV['PATH']
- ENV['PATH'] = ''
+ @original_path = ENV["PATH"]
+ ENV["PATH"] = ""
end
after do
- ENV['PATH'] = @original_path
+ ENV["PATH"] = @original_path
end
- it 'raises MigrationError on missing `createdb`' do
+ it "raises MigrationError on missing `createdb`" do
message = Platform.match do
- os(:macos).engine(:jruby) { 'createdb' }
+ os(:macos).engine(:jruby) { "createdb" }
default { "Could not find executable in your PATH: `createdb`" }
end
@@ -100,9 +102,9 @@
end
end
- it 'raises MigrationError on missing `dropdb`' do
+ it "raises MigrationError on missing `dropdb`" do
message = Platform.match do
- os(:macos).engine(:jruby) { 'dropdb' }
+ os(:macos).engine(:jruby) { "dropdb" }
default { "Could not find executable in your PATH: `dropdb`" }
end
@@ -113,13 +115,13 @@
end
end
- describe 'migrate' do
+ describe "migrate" do
before do
migrator.create
end
- describe 'when no migrations' do
- let(:migrations) { Pathname.new(__dir__ + '/../../../../support/fixtures/empty_migrations') }
+ describe "when no migrations" do
+ let(:migrations) { Pathname.new(__dir__ + "/../../../../support/fixtures/empty_migrations") }
it "it doesn't alter database" do
migrator.migrate
@@ -129,8 +131,8 @@
end
end
- describe 'when migrations are present' do
- it 'migrates the database' do
+ describe "when migrations are present" do
+ it "migrates the database" do
migrator.migrate
connection = Sequel.connect(url)
@@ -142,9 +144,10 @@
expect(name).to eq(:id)
expect(options.fetch(:allow_null)).to eq(false)
- expect(options.fetch(:default)).to eq("nextval('reviews_id_seq'::regclass)")
+ # FIXME: determine how to assert it's a autoincrement
+ # expect(options.fetch(:default)).to eq("nextval('reviews_id_seq'::regclass)")
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(true)
expect(options.fetch(:auto_increment)).to eq(true)
@@ -154,21 +157,21 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to be_nil
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('text')
+ expect(options.fetch(:db_type)).to eq("text")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[2] # rating (second migration)
expect(name).to eq(:rating)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('0')
+ expect(options.fetch(:default)).to eq("0")
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(false)
end
end
- describe 'when migrations are ran twice' do
+ describe "when migrations are ran twice" do
before do
migrator.migrate
end
@@ -183,13 +186,13 @@
end
end
- describe 'migrate down' do
+ describe "migrate down" do
before do
migrator.migrate
end
- it 'migrates the database' do
- migrator.migrate(version: '20160831073534') # see spec/support/fixtures/migrations
+ it "migrates the database" do
+ migrator.migrate(version: "20160831073534") # see spec/support/fixtures/migrations
connection = Sequel.connect(url)
expect(connection.tables).to_not be_empty
@@ -200,9 +203,10 @@
expect(name).to eq(:id)
expect(options.fetch(:allow_null)).to eq(false)
- expect(options.fetch(:default)).to eq("nextval('reviews_id_seq'::regclass)")
+ # FIXME: determine how to assert it's a autoincrement
+ # expect(options.fetch(:default)).to eq("nextval('reviews_id_seq'::regclass)")
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(true)
expect(options.fetch(:auto_increment)).to eq(true)
@@ -212,7 +216,7 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to be_nil
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('text')
+ expect(options.fetch(:db_type)).to eq("text")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[2] # rating (rolled back second migration)
@@ -222,13 +226,13 @@
end
end
- describe 'rollback' do
+ describe "rollback" do
before do
migrator.create
end
- describe 'when no migrations' do
- let(:migrations) { Pathname.new(__dir__ + '/../../../../support/fixtures/empty_migrations') }
+ describe "when no migrations" do
+ let(:migrations) { Pathname.new(__dir__ + "/../../../../support/fixtures/empty_migrations") }
it "it doesn't alter database" do
migrator.rollback
@@ -238,8 +242,8 @@
end
end
- describe 'when migrations are present' do
- it 'rollbacks one migration (default)' do
+ describe "when migrations are present" do
+ it "rollbacks one migration (default)" do
migrator.migrate
migrator.rollback
@@ -252,9 +256,10 @@
expect(name).to eq(:id)
expect(options.fetch(:allow_null)).to eq(false)
- expect(options.fetch(:default)).to eq("nextval('reviews_id_seq'::regclass)")
+ # FIXME: determine how to assert it's a autoincrement
+ # expect(options.fetch(:default)).to eq("nextval('reviews_id_seq'::regclass)")
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(true)
expect(options.fetch(:auto_increment)).to eq(true)
@@ -264,7 +269,7 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to be_nil
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('text')
+ expect(options.fetch(:db_type)).to eq("text")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[2] # rating (second migration)
@@ -272,7 +277,7 @@
expect(options).to eq(nil)
end
- it 'rollbacks several migrations' do
+ it "rollbacks several migrations" do
migrator.migrate
migrator.rollback(steps: 2)
@@ -282,7 +287,7 @@
end
end
- describe 'apply' do
+ describe "apply" do
let(:migrations) { target_migrations }
let(:schema) { root.join("schema-postgresql-#{random}.sql") }
@@ -295,19 +300,19 @@
clean_migrations
end
- it 'migrates to latest version' do
+ it "migrates to latest version" do
migrator.apply
connection = Sequel.connect(url)
migration = connection[:schema_migrations].to_a.last
- expect(migration.fetch(:filename)).to include('20160831090612') # see spec/support/fixtures/migrations
+ expect(migration.fetch(:filename)).to include("20160831090612") # see spec/support/fixtures/migrations
end
- it 'dumps database schema.sql' do
+ xit "dumps database schema.sql" do
migrator.apply
actual = schema.read
- if actual =~ /public\.reviews/
+ if /public\.reviews/.match?(actual)
#
# POSTGRESQL 10
#
@@ -411,7 +416,7 @@
end
end
- it 'deletes all the migrations' do
+ it "deletes all the migrations" do
migrator.apply
expect(target_migrations.children).to be_empty
end
@@ -439,7 +444,7 @@
end
end
- describe 'prepare' do
+ describe "prepare" do
let(:migrations) { target_migrations }
let(:schema) { root.join("schema-postgresql-#{random}.sql") }
@@ -452,12 +457,12 @@
clean_migrations
end
- it 'creates database, loads schema and migrate' do
+ it "creates database, loads schema and migrate" do
# Simulate already existing schema.sql, without existing database and pending migrations
Hanami::Model::Migrator::Adapter.for(configuration).dump
- migration = target_migrations.join('20160831095616_create_abuses.rb')
- File.open(migration, 'w+') do |f|
+ migration = target_migrations.join("20160831095616_create_abuses.rb")
+ File.open(migration, "w+") do |f|
f.write <<-RUBY
Hanami::Model.migration do
change do
@@ -491,7 +496,7 @@
expect(connection.tables).to include(:reviews)
end
- it 'drops the database and recreates it' do
+ it "drops the database and recreates it" do
migrator.prepare
connection = Sequel.connect(url)
@@ -500,24 +505,24 @@
end
end
- describe 'version' do
+ describe "version" do
before do
migrator.create
end
- describe 'when no migrations were ran' do
- it 'returns nil' do
+ describe "when no migrations were ran" do
+ it "returns nil" do
expect(migrator.version).to be_nil
end
end
- describe 'with migrations' do
+ describe "with migrations" do
before do
migrator.migrate
end
- it 'returns current database version' do
- expect(migrator.version).to eq('20160831090612') # see spec/support/fixtures/migrations)
+ it "returns current database version" do
+ expect(migrator.version).to eq("20160831090612") # see spec/support/fixtures/migrations)
end
end
end
diff --git a/spec/unit/hanami/model/migrator/sqlite.rb b/spec/unit/hanami/model/migrator/sqlite.rb
index 1517df72..6b5babe4 100644
--- a/spec/unit/hanami/model/migrator/sqlite.rb
+++ b/spec/unit/hanami/model/migrator/sqlite.rb
@@ -1,7 +1,9 @@
-require 'ostruct'
-require 'securerandom'
+# frozen_string_literal: true
-RSpec.shared_examples 'migrator_sqlite' do
+require "ostruct"
+require "securerandom"
+
+RSpec.shared_examples "migrator_sqlite" do
let(:migrator) do
Hanami::Model::Migrator.new(configuration: configuration)
end
@@ -9,9 +11,9 @@
let(:random) { SecureRandom.hex }
# General variables
- let(:migrations) { Pathname.new(__dir__ + '/../../../../support/fixtures/migrations') }
+ let(:migrations) { Pathname.new(__dir__ + "/../../../../support/fixtures/migrations") }
let(:schema) { nil }
- let(:config) { OpenStruct.new(backend: :sql, url: url, _migrations: migrations, _schema: schema, migrations_logger: Hanami::Model::Migrator::Logger.new(ENV['HANAMI_DATABASE_LOGGER'])) }
+ let(:config) { OpenStruct.new(backend: :sql, url: url, _migrations: migrations, _schema: schema, migrations_logger: Hanami::Model::Migrator::Logger.new(ENV["HANAMI_DATABASE_LOGGER"])) }
let(:configuration) { Hanami::Model::Configuration.new(config) }
let(:url) do
db = database
@@ -31,21 +33,21 @@
migrator.drop rescue nil # rubocop:disable Style/RescueModifier
end
- describe 'SQLite filesystem' do
+ describe "SQLite filesystem" do
let(:database) do
Pathname.new("#{__dir__}/../../../../../tmp/create-#{random}.sqlite3").expand_path
end
- describe 'create' do
- it 'creates the database' do
+ describe "create" do
+ it "creates the database" do
migrator.create
expect(File.exist?(database)).to be_truthy, "Expected database #{database} to exist"
end
describe "when it doesn't have write permissions" do
- let(:database) { '/usr/bin/create.sqlite3' }
+ let(:database) { "/usr/bin/create.sqlite3" }
- it 'raises an error' do
+ it "raises an error" do
skip if Platform::Ci.ci?(:drone)
error = Platform.match do
@@ -54,30 +56,30 @@
end
message = Platform.match do
- os(:macos).engine(:jruby) { 'Unhandled IOException: java.io.IOException: unhandled errno: Operation not permitted' }
- default { 'Permission denied: /usr/bin/create.sqlite3' }
+ os(:macos).engine(:jruby) { "Unhandled IOException: java.io.IOException: unhandled errno: Operation not permitted" }
+ default { "Permission denied: /usr/bin/create.sqlite3" }
end
expect { migrator.create }.to raise_error(error, message)
end
end
- describe 'when the path is relative' do
- let(:database) { 'create.sqlite3' }
+ describe "when the path is relative" do
+ let(:database) { "create.sqlite3" }
- it 'creates the database' do
+ it "creates the database" do
migrator.create
expect(File.exist?(database)).to be_truthy, "Expected database #{database} to exist"
end
end
end
- describe 'drop' do
+ describe "drop" do
before do
migrator.create
end
- it 'drops the database' do
+ it "drops the database" do
migrator.drop
expect(File.exist?(database)).to be_falsey, "Expected database #{database} to NOT exist"
end
@@ -90,13 +92,13 @@
end
end
- describe 'migrate' do
+ describe "migrate" do
before do
migrator.create
end
- describe 'when no migrations' do
- let(:migrations) { Pathname.new(__dir__ + '/../../../../support/fixtures/empty_migrations') }
+ describe "when no migrations" do
+ let(:migrations) { Pathname.new(__dir__ + "/../../../../support/fixtures/empty_migrations") }
it "it doesn't alter database" do
migrator.migrate
@@ -106,8 +108,8 @@
end
end
- describe 'when migrations are present' do
- it 'migrates the database' do
+ describe "when migrations are present" do
+ it "migrates the database" do
migrator.migrate
connection = Sequel.connect(url)
@@ -121,7 +123,7 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to be_nil
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(true)
expect(options.fetch(:auto_increment)).to eq(true)
@@ -131,21 +133,21 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to be_nil
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('varchar(255)')
+ expect(options.fetch(:db_type)).to eq("varchar(255)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[2] # rating (second migration)
expect(name).to eq(:rating)
expect(options.fetch(:allow_null)).to eq(true)
- expect(options.fetch(:default)).to eq('0')
+ expect(options.fetch(:default)).to eq("0")
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(false)
end
end
- describe 'when migrations are ran twice' do
+ describe "when migrations are ran twice" do
before do
migrator.migrate
end
@@ -159,13 +161,13 @@
end
end
- describe 'migrate down' do
+ describe "migrate down" do
before do
migrator.migrate
end
- it 'migrates the database' do
- migrator.migrate(version: '20160831073534') # see spec/support/fixtures/migrations
+ it "migrates the database" do
+ migrator.migrate(version: "20160831073534") # see spec/support/fixtures/migrations
connection = Sequel.connect(url)
expect(connection.tables).to_not be_empty
@@ -178,7 +180,7 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to be_nil
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(true)
expect(options.fetch(:auto_increment)).to eq(true)
@@ -188,7 +190,7 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to be_nil
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('varchar(255)')
+ expect(options.fetch(:db_type)).to eq("varchar(255)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[2] # rating (rolled back second migration)
@@ -198,13 +200,13 @@
end
end
- describe 'rollback' do
+ describe "rollback" do
before do
migrator.create
end
- describe 'when no migrations' do
- let(:migrations) { Pathname.new(__dir__ + '/../../../../support/fixtures/empty_migrations') }
+ describe "when no migrations" do
+ let(:migrations) { Pathname.new(__dir__ + "/../../../../support/fixtures/empty_migrations") }
it "it doesn't alter database" do
migrator.rollback
@@ -214,8 +216,8 @@
end
end
- describe 'when migrations are present' do
- it 'rollbacks one migration (default)' do
+ describe "when migrations are present" do
+ it "rollbacks one migration (default)" do
migrator.migrate
migrator.rollback
@@ -230,7 +232,7 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to be_nil
expect(options.fetch(:type)).to eq(:integer)
- expect(options.fetch(:db_type)).to eq('integer')
+ expect(options.fetch(:db_type)).to eq("integer")
expect(options.fetch(:primary_key)).to eq(true)
expect(options.fetch(:auto_increment)).to eq(true)
@@ -240,7 +242,7 @@
expect(options.fetch(:allow_null)).to eq(false)
expect(options.fetch(:default)).to be_nil
expect(options.fetch(:type)).to eq(:string)
- expect(options.fetch(:db_type)).to eq('varchar(255)')
+ expect(options.fetch(:db_type)).to eq("varchar(255)")
expect(options.fetch(:primary_key)).to eq(false)
name, options = table[2] # rating (second migration)
@@ -248,7 +250,7 @@
expect(options).to eq(nil)
end
- it 'rollbacks several migrations' do
+ it "rollbacks several migrations" do
migrator.migrate
migrator.rollback(steps: 2)
@@ -258,7 +260,7 @@
end
end
- describe 'apply' do
+ describe "apply" do
let(:migrations) { target_migrations }
let(:schema) { root.join("schema-sqlite-#{random}.sql") }
@@ -270,15 +272,15 @@
clean_migrations
end
- it 'migrates to latest version' do
+ it "migrates to latest version" do
migrator.apply
connection = Sequel.connect(url)
migration = connection[:schema_migrations].to_a.last
- expect(migration.fetch(:filename)).to include('20160831090612') # see spec/support/fixtures/migrations
+ expect(migration.fetch(:filename)).to include("20160831090612") # see spec/support/fixtures/migrations
end
- it 'dumps database schema.sql' do
+ it "dumps database schema.sql" do
migrator.apply
actual = schema.read
@@ -288,7 +290,7 @@
expect(actual).to match(/INSERT INTO "?schema_migrations"? VALUES\('20160831090612_add_rating_to_reviews.rb'\);/)
end
- it 'deletes all the migrations' do
+ it "deletes all the migrations" do
migrator.apply
expect(target_migrations.children).to be_empty
end
@@ -323,7 +325,7 @@
end
end
- describe 'prepare' do
+ describe "prepare" do
let(:migrations) { target_migrations }
let(:schema) { root.join("schema-sqlite-#{random}.sql") }
@@ -335,13 +337,12 @@
clean_migrations
end
- it 'creates database, loads schema and migrate' do
+ it "creates database, loads schema and migrate" do
# Simulate already existing schema.sql, without existing database and pending migrations
- connection = Sequel.connect(url)
Hanami::Model::Migrator::Adapter.for(configuration).dump
- migration = target_migrations.join('20160831095616_create_abuses.rb')
- File.open(migration, 'w+') do |f|
+ migration = target_migrations.join("20160831095616_create_abuses.rb")
+ File.open(migration, "w+") do |f|
f.write <<~RUBY
Hanami::Model.migration do
change do
@@ -355,6 +356,7 @@
migrator.prepare
+ connection = Sequel.connect(url)
expect(connection.tables).to eq(%i[schema_migrations reviews abuses])
FileUtils.rm_f migration
@@ -369,7 +371,7 @@
expect(connection.tables).to eq(%i[schema_migrations reviews])
end
- it 'drops the database and recreate it' do
+ it "drops the database and recreate it" do
migrator.create
migrator.prepare
@@ -379,24 +381,24 @@
end
end
- describe 'version' do
+ describe "version" do
before do
migrator.create
end
- describe 'when no migrations were ran' do
- it 'returns nil' do
+ describe "when no migrations were ran" do
+ it "returns nil" do
expect(migrator.version).to be_nil
end
end
- describe 'with migrations' do
+ describe "with migrations" do
before do
migrator.migrate
end
- it 'returns current database version' do
- expect(migrator.version).to eq('20160831090612') # see spec/support/fixtures/migrations)
+ it "returns current database version" do
+ expect(migrator.version).to eq("20160831090612") # see spec/support/fixtures/migrations)
end
end
end
diff --git a/spec/unit/hanami/model/migrator_spec.rb b/spec/unit/hanami/model/migrator_spec.rb
index 0d4d3bd0..c425d87d 100644
--- a/spec/unit/hanami/model/migrator_spec.rb
+++ b/spec/unit/hanami/model/migrator_spec.rb
@@ -1,4 +1,6 @@
-require 'hanami/model/migrator'
+# frozen_string_literal: true
+
+require "hanami/model/migrator"
require_relative "./migrator/#{Database.engine}"
RSpec.describe Hanami::Model::Migrator do
diff --git a/spec/unit/hanami/model/not_null_constraint_violation_error_spec.rb b/spec/unit/hanami/model/not_null_constraint_violation_error_spec.rb
index 43dc9146..4871645c 100644
--- a/spec/unit/hanami/model/not_null_constraint_violation_error_spec.rb
+++ b/spec/unit/hanami/model/not_null_constraint_violation_error_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
RSpec.describe Hanami::Model::NotNullConstraintViolationError do
it "inherits from Hanami::Model::ConstraintViolationError" do
expect(described_class.ancestors).to include(Hanami::Model::ConstraintViolationError)
diff --git a/spec/unit/hanami/model/sql/console/mysql.rb b/spec/unit/hanami/model/sql/console/mysql.rb
index 1d8619a5..274d7308 100644
--- a/spec/unit/hanami/model/sql/console/mysql.rb
+++ b/spec/unit/hanami/model/sql/console/mysql.rb
@@ -1,13 +1,15 @@
-require 'hanami/model/sql/consoles/mysql'
+# frozen_string_literal: true
+
+require "hanami/model/sql/consoles/mysql"
RSpec.shared_examples "sql_console_mysql" do
- let(:console) { Hanami::Model::Sql::Consoles::Mysql.new(uri) }
+ let(:db_console) { Hanami::Model::Sql::Consoles::Mysql.new(uri) }
- describe '#connection_string' do
- let(:uri) { URI.parse('mysql://username:password@localhost:1234/foo_development') }
+ describe "#connection_string" do
+ let(:uri) { URI.parse("mysql://username:password@localhost:1234/foo_development") }
- it 'returns a connection string' do
- expect(console.connection_string).to eq('mysql -h localhost -D foo_development -P 1234 -u username -p password')
+ it "returns a connection string" do
+ expect(db_console.connection_string).to eq("mysql -h localhost -D foo_development -P 1234 -u username -p password")
end
end
end
diff --git a/spec/unit/hanami/model/sql/console/postgresql.rb b/spec/unit/hanami/model/sql/console/postgresql.rb
index 1fcd44b8..626bcfb2 100644
--- a/spec/unit/hanami/model/sql/console/postgresql.rb
+++ b/spec/unit/hanami/model/sql/console/postgresql.rb
@@ -1,42 +1,44 @@
-require 'hanami/model/sql/consoles/postgresql'
+# frozen_string_literal: true
+
+require "hanami/model/sql/consoles/postgresql"
RSpec.shared_examples "sql_console_postgresql" do
- let(:console) { Hanami::Model::Sql::Consoles::Postgresql.new(uri) }
+ let(:db_console) { Hanami::Model::Sql::Consoles::Postgresql.new(uri) }
- describe '#connection_string' do
- let(:uri) { URI.parse('postgres://username:password@localhost:1234/foo_development') }
+ describe "#connection_string" do
+ let(:uri) { URI.parse("postgres://username:password@localhost:1234/foo_development") }
- it 'returns a connection string' do
- expect(console.connection_string).to eq('psql -h localhost -d foo_development -p 1234 -U username')
+ it "returns a connection string" do
+ expect(db_console.connection_string).to eq("psql -h localhost -d foo_development -p 1234 -U username")
end
- it 'sets the PGPASSWORD environment variable' do
- console.connection_string
- expect(ENV['PGPASSWORD']).to eq('password')
- ENV.delete('PGPASSWORD')
+ it "sets the PGPASSWORD environment variable" do
+ db_console.connection_string
+ expect(ENV["PGPASSWORD"]).to eq("password")
+ ENV.delete("PGPASSWORD")
end
- context 'when the password contains percent encoded characters' do
- let(:uri) { URI.parse('postgres://username:p%40ss@localhost:1234/foo_development') }
+ context "when the password contains percent encoded characters" do
+ let(:uri) { URI.parse("postgres://username:p%40ss@localhost:1234/foo_development") }
- it 'sets the PGPASSWORD environment variable decoding special characters' do
- console.connection_string
- expect(ENV['PGPASSWORD']).to eq('p@ss')
- ENV.delete('PGPASSWORD')
+ it "sets the PGPASSWORD environment variable decoding special characters" do
+ db_console.connection_string
+ expect(ENV["PGPASSWORD"]).to eq("p@ss")
+ ENV.delete("PGPASSWORD")
end
end
- context 'when components of the hierarchical part of the URI can also be given as parameters' do
- let(:uri) { URI.parse('postgres:///foo_development?user=username&password=password&host=localhost&port=1234') }
+ context "when components of the hierarchical part of the URI can also be given as parameters" do
+ let(:uri) { URI.parse("postgres:///foo_development?user=username&password=password&host=localhost&port=1234") }
- it 'returns a connection string' do
- expect(console.connection_string).to eq('psql -h localhost -d foo_development -p 1234 -U username')
+ it "returns a connection string" do
+ expect(db_console.connection_string).to eq("psql -h localhost -d foo_development -p 1234 -U username")
end
- it 'sets the PGPASSWORD environment variable' do
- console.connection_string
- expect(ENV['PGPASSWORD']).to eq('password')
- ENV.delete('PGPASSWORD')
+ it "sets the PGPASSWORD environment variable" do
+ db_console.connection_string
+ expect(ENV["PGPASSWORD"]).to eq("password")
+ ENV.delete("PGPASSWORD")
end
end
end
diff --git a/spec/unit/hanami/model/sql/console/sqlite.rb b/spec/unit/hanami/model/sql/console/sqlite.rb
index 9827f686..c846be27 100644
--- a/spec/unit/hanami/model/sql/console/sqlite.rb
+++ b/spec/unit/hanami/model/sql/console/sqlite.rb
@@ -1,20 +1,22 @@
-require 'hanami/model/sql/consoles/sqlite'
+# frozen_string_literal: true
+
+require "hanami/model/sql/consoles/sqlite"
RSpec.shared_examples "sql_console_sqlite" do
- let(:console) { Hanami::Model::Sql::Consoles::Sqlite.new(uri) }
+ let(:db_console) { Hanami::Model::Sql::Consoles::Sqlite.new(uri) }
- describe '#connection_string' do
- describe 'with shell ok database uri' do
- let(:uri) { URI.parse('sqlite://foo/bar.db') }
- it 'returns a connection string for Sqlite3' do
- expect(console.connection_string).to eq('sqlite3 foo/bar.db')
+ describe "#connection_string" do
+ describe "with shell ok database uri" do
+ let(:uri) { URI.parse("sqlite://foo/bar.db") }
+ it "returns a connection string for Sqlite3" do
+ expect(db_console.connection_string).to eq("sqlite3 foo/bar.db")
end
end
- describe 'with non shell ok database uri' do
- let(:uri) { URI.parse('sqlite://foo/%20bar.db') }
- it 'returns an escaped connection string for Sqlite3' do
- expect(console.connection_string).to eq('sqlite3 foo/\\%20bar.db')
+ describe "with non shell ok database uri" do
+ let(:uri) { URI.parse("sqlite://foo/%20bar.db") }
+ it "returns an escaped connection string for Sqlite3" do
+ expect(db_console.connection_string).to eq('sqlite3 foo/\\%20bar.db')
end
end
end
diff --git a/spec/unit/hanami/model/sql/console_spec.rb b/spec/unit/hanami/model/sql/console_spec.rb
index f6f7de09..3a3920a7 100644
--- a/spec/unit/hanami/model/sql/console_spec.rb
+++ b/spec/unit/hanami/model/sql/console_spec.rb
@@ -1,34 +1,36 @@
-require 'hanami/model/sql/console'
+# frozen_string_literal: true
+
+require "hanami/model/sql/console"
RSpec.describe Hanami::Model::Sql::Console do
- describe 'deciding on which SQL console class to use, based on URI scheme' do
- let(:uri) { 'username:password@localhost:1234/foo_development' }
+ describe "deciding on which SQL console class to use, based on URI scheme" do
+ let(:uri) { "username:password@localhost:1234/foo_development" }
case Database.engine
when :sqlite
- it 'sqlite:// uri returns an instance of Console::Sqlite' do
- console = Hanami::Model::Sql::Console.new("sqlite://#{uri}").send(:console)
- expect(console).to be_a_kind_of(Hanami::Model::Sql::Consoles::Sqlite)
+ it "sqlite:// uri returns an instance of Console::Sqlite" do
+ db_console = Hanami::Model::Sql::Console.new("sqlite://#{uri}").send(:console)
+ expect(db_console).to be_a_kind_of(Hanami::Model::Sql::Consoles::Sqlite)
end
when :postgresql
- it 'postgres:// uri returns an instance of Console::Postgresql' do
- console = Hanami::Model::Sql::Console.new("postgres://#{uri}").send(:console)
- expect(console).to be_a_kind_of(Hanami::Model::Sql::Consoles::Postgresql)
+ it "postgres:// uri returns an instance of Console::Postgresql" do
+ db_console = Hanami::Model::Sql::Console.new("postgres://#{uri}").send(:console)
+ expect(db_console).to be_a_kind_of(Hanami::Model::Sql::Consoles::Postgresql)
end
- it 'postgresql:// uri returns an instance of Console::Postgresql' do
- console = Hanami::Model::Sql::Console.new("postgresql://#{uri}").send(:console)
- expect(console).to be_a_kind_of(Hanami::Model::Sql::Consoles::Postgresql)
+ it "postgresql:// uri returns an instance of Console::Postgresql" do
+ db_console = Hanami::Model::Sql::Console.new("postgresql://#{uri}").send(:console)
+ expect(db_console).to be_a_kind_of(Hanami::Model::Sql::Consoles::Postgresql)
end
when :mysql
- it 'mysql:// uri returns an instance of Console::Mysql' do
- console = Hanami::Model::Sql::Console.new("mysql://#{uri}").send(:console)
- expect(console).to be_a_kind_of(Hanami::Model::Sql::Consoles::Mysql)
+ it "mysql:// uri returns an instance of Console::Mysql" do
+ db_console = Hanami::Model::Sql::Console.new("mysql://#{uri}").send(:console)
+ expect(db_console).to be_a_kind_of(Hanami::Model::Sql::Consoles::Mysql)
end
- it 'mysql2:// uri returns an instance of Console::Mysql' do
- console = Hanami::Model::Sql::Console.new("mysql2://#{uri}").send(:console)
- expect(console).to be_a_kind_of(Hanami::Model::Sql::Consoles::Mysql)
+ it "mysql2:// uri returns an instance of Console::Mysql" do
+ db_console = Hanami::Model::Sql::Console.new("mysql2://#{uri}").send(:console)
+ expect(db_console).to be_a_kind_of(Hanami::Model::Sql::Consoles::Mysql)
end
end
end
diff --git a/spec/unit/hanami/model/sql/entity/schema/automatic_spec.rb b/spec/unit/hanami/model/sql/entity/schema/automatic_spec.rb
index 0501394b..f2b53909 100644
--- a/spec/unit/hanami/model/sql/entity/schema/automatic_spec.rb
+++ b/spec/unit/hanami/model/sql/entity/schema/automatic_spec.rb
@@ -1,21 +1,24 @@
-RSpec.describe Hanami::Model::Sql::Entity::Schema do
- describe 'automatic' do
- subject { Author.schema }
+# frozen_string_literal: true
- describe '#initialize' do
- it 'returns frozen instance' do
+RSpec.describe "Hanami::Model::Sql::Entity::Schema", skip: true do
+ describe "automatic" do
+ subject { entity.schema }
+ let(:entity) { Author }
+
+ describe "#initialize" do
+ it "returns frozen instance" do
expect(subject).to be_frozen
end
end
- describe '#call' do
- it 'returns empty hash when nil is given' do
+ describe "#call" do
+ it "returns empty hash when nil is given" do
result = subject.call(nil)
expect(result).to eq({})
end
- it 'processes attributes' do
+ it "processes attributes" do
now = Time.now
result = subject.call(id: 1, created_at: now.to_s)
@@ -23,20 +26,20 @@
expect(result.fetch(:created_at)).to be_within(2).of(now)
end
- it 'ignores unknown attributes' do
- result = subject.call(foo: 'bar')
+ it "ignores unknown attributes" do
+ result = subject.call(foo: "bar")
expect(result).to eq({})
end
end
- describe '#attribute?' do
- it 'returns true for known attributes' do
- expect(subject.attribute?(:id)).to eq(true)
+ describe "#has_attribute?" do
+ it "returns true for known attributes" do
+ expect(entity.has_attribute?(:id)).to eq(true)
end
- it 'returns false for unknown attributes' do
- expect(subject.attribute?(:foo)).to eq(false)
+ it "returns false for unknown attributes" do
+ expect(entity.has_attribute?(:foo)).to eq(false)
end
end
end
diff --git a/spec/unit/hanami/model/sql/entity/schema/mapping_spec.rb b/spec/unit/hanami/model/sql/entity/schema/mapping_spec.rb
index ccc42931..aea4f6cb 100644
--- a/spec/unit/hanami/model/sql/entity/schema/mapping_spec.rb
+++ b/spec/unit/hanami/model/sql/entity/schema/mapping_spec.rb
@@ -1,40 +1,43 @@
-RSpec.describe Hanami::Model::Sql::Entity::Schema do
- describe 'mapping' do
- subject { Operator.schema }
+# frozen_string_literal: true
- describe '#initialize' do
- it 'returns frozen instance' do
+RSpec.describe "Hanami::Model::Sql::Entity::Schema", skip: true do
+ describe "mapping" do
+ subject { entity.schema }
+ let(:entity) { Operator }
+
+ describe "#initialize" do
+ it "returns frozen instance" do
expect(subject).to be_frozen
end
end
- describe '#call' do
- it 'returns empty hash when nil is given' do
+ describe "#call" do
+ it "returns empty hash when nil is given" do
result = subject.call(nil)
expect(result).to eq({})
end
- it 'processes attributes' do
+ it "processes attributes" do
result = subject.call(id: 1, name: :foo)
- expect(result).to eq(id: 1, name: 'foo')
+ expect(result).to eq(id: 1, name: "foo")
end
- it 'ignores unknown attributes' do
- result = subject.call(foo: 'bar')
+ it "ignores unknown attributes" do
+ result = subject.call(foo: "bar")
expect(result).to eq({})
end
end
- describe '#attribute?' do
- it 'returns true for known attributes' do
- expect(subject.attribute?(:id)).to eq(true)
+ describe "#has_attribute?" do
+ it "returns true for known attributes" do
+ expect(entity.has_attribute?(:id)).to eq(true)
end
- it 'returns false for unknown attributes' do
- expect(subject.attribute?(:foo)).to eq(false)
+ it "returns false for unknown attributes" do
+ expect(entity.has_attribute?(:foo)).to eq(false)
end
end
end
diff --git a/spec/unit/hanami/model/sql/schema/array_spec.rb b/spec/unit/hanami/model/sql/schema/array_spec.rb
index 041b1744..c91682bb 100644
--- a/spec/unit/hanami/model/sql/schema/array_spec.rb
+++ b/spec/unit/hanami/model/sql/schema/array_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
RSpec.describe "Hanami::Model::Sql::Types::Schema::Array" do
let(:described_class) { Hanami::Model::Sql::Types::Schema::Array }
@@ -9,71 +11,71 @@ def to_ary
end.new
end
- it 'returns nil for nil' do
+ it "returns nil for nil" do
input = nil
expect(described_class[input]).to eq(input)
end
- it 'coerces object that respond to #to_ary' do
+ it "coerces object that respond to #to_ary" do
expect(described_class[input]).to eq(input.to_ary)
end
- it 'coerces string' do
- input = 'foo'
+ it "coerces string" do
+ input = "foo"
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Array(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Array(): #{input.inspect}")
end
- it 'raises error for symbol' do
+ it "raises error for symbol" do
input = :foo
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Array(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Array(): #{input.inspect}")
end
- it 'raises error for integer' do
+ it "raises error for integer" do
input = 11
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Array(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Array(): #{input.inspect}")
end
- it 'raises error for float' do
+ it "raises error for float" do
input = 3.14
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Array(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Array(): #{input.inspect}")
end
- it 'raises error for bigdecimal' do
+ it "raises error for bigdecimal" do
input = BigDecimal(3.14, 10)
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Array(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Array(): #{input.inspect}")
end
- it 'raises error for date' do
+ it "raises error for date" do
input = Date.today
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Array(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Array(): #{input.inspect}")
end
- it 'raises error for datetime' do
+ it "raises error for datetime" do
input = DateTime.new
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Array(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Array(): #{input.inspect}")
end
- it 'raises error for time' do
+ it "raises error for time" do
input = Time.now
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Array(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Array(): #{input.inspect}")
end
- it 'coerces array' do
+ it "coerces array" do
input = []
expect(described_class[input]).to eq(input)
end
- it 'raises error for hash' do
+ it "raises error for hash" do
input = {}
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Array(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Array(): #{input.inspect}")
end
end
diff --git a/spec/unit/hanami/model/sql/schema/bool_spec.rb b/spec/unit/hanami/model/sql/schema/bool_spec.rb
index 0313d9fa..a90ba16e 100644
--- a/spec/unit/hanami/model/sql/schema/bool_spec.rb
+++ b/spec/unit/hanami/model/sql/schema/bool_spec.rb
@@ -1,78 +1,80 @@
+# frozen_string_literal: true
+
RSpec.describe "Hanami::Model::Sql::Types::Schema::Bool" do
let(:described_class) { Hanami::Model::Sql::Types::Schema::Bool }
- it 'returns nil for nil' do
+ it "returns nil for nil" do
input = nil
expect(described_class[input]).to eq(input)
end
- it 'returns true for true' do
+ it "returns true for true" do
input = true
expect(described_class[input]).to eq(input)
end
- it 'returns false for false' do
+ it "returns false for false" do
input = true
expect(described_class[input]).to eq(input)
end
- it 'raises error for string' do
- input = 'foo'
+ it "raises error for string" do
+ input = "foo"
expect { described_class[input] }
- .to raise_error(TypeError, "#{input.inspect} violates constraints (type?(FalseClass, #{input.inspect}) failed)")
+ .to raise_error(Dry::Types::ConstraintError, "#{input.inspect} violates constraints (type?(FalseClass, #{input.inspect}) failed)")
end
- it 'raises error for symbol' do
+ it "raises error for symbol" do
input = :foo
expect { described_class[input] }
- .to raise_error(TypeError, "#{input.inspect} violates constraints (type?(FalseClass, #{input.inspect}) failed)")
+ .to raise_error(Dry::Types::ConstraintError, "#{input.inspect} violates constraints (type?(FalseClass, #{input.inspect}) failed)")
end
- it 'raises error for integer' do
+ it "raises error for integer" do
input = 11
expect { described_class[input] }
- .to raise_error(TypeError, "#{input.inspect} violates constraints (type?(FalseClass, #{input.inspect}) failed)")
+ .to raise_error(Dry::Types::ConstraintError, "#{input.inspect} violates constraints (type?(FalseClass, #{input.inspect}) failed)")
end
- it 'raises error for float' do
+ it "raises error for float" do
input = 3.14
expect { described_class[input] }
- .to raise_error(TypeError, "#{input.inspect} violates constraints (type?(FalseClass, #{input.inspect}) failed)")
+ .to raise_error(Dry::Types::ConstraintError, "#{input.inspect} violates constraints (type?(FalseClass, #{input.inspect}) failed)")
end
- it 'raises error for bigdecimal' do
+ it "raises error for bigdecimal" do
input = BigDecimal(3.14, 10)
expect { described_class[input] }
- .to raise_error(TypeError, "#{input.inspect} violates constraints (type?(FalseClass, #{input.inspect}) failed)")
+ .to raise_error(Dry::Types::ConstraintError, "#{input.inspect} violates constraints (type?(FalseClass, #{input.inspect}) failed)")
end
- it 'raises error for date' do
+ it "raises error for date" do
input = Date.today
expect { described_class[input] }
- .to raise_error(TypeError, "#{input.inspect} violates constraints (type?(FalseClass, #{input.inspect}) failed)")
+ .to raise_error(Dry::Types::ConstraintError, "#{input.inspect} violates constraints (type?(FalseClass, #{input.inspect}) failed)")
end
- it 'raises error for datetime' do
+ it "raises error for datetime" do
input = DateTime.new
expect { described_class[input] }
- .to raise_error(TypeError, "#{input.inspect} violates constraints (type?(FalseClass, #{input.inspect}) failed)")
+ .to raise_error(Dry::Types::ConstraintError, "#{input.inspect} violates constraints (type?(FalseClass, #{input.inspect}) failed)")
end
- it 'raises error for time' do
+ it "raises error for time" do
input = Time.now
expect { described_class[input] }
- .to raise_error(TypeError, "#{input.inspect} violates constraints (type?(FalseClass, #{input.inspect}) failed)")
+ .to raise_error(Dry::Types::ConstraintError, "#{input.inspect} violates constraints (type?(FalseClass, #{input.inspect}) failed)")
end
- it 'raises error for array' do
+ it "raises error for array" do
input = []
expect { described_class[input] }
- .to raise_error(TypeError, "#{input.inspect} violates constraints (type?(FalseClass, #{input.inspect}) failed)")
+ .to raise_error(Dry::Types::ConstraintError, "#{input.inspect} violates constraints (type?(FalseClass, #{input.inspect}) failed)")
end
- it 'raises error for hash' do
+ it "raises error for hash" do
input = {}
expect { described_class[input] }
- .to raise_error(TypeError, "#{input.inspect} violates constraints (type?(FalseClass, #{input.inspect}) failed)")
+ .to raise_error(Dry::Types::ConstraintError, "#{input.inspect} violates constraints (type?(FalseClass, #{input.inspect}) failed)")
end
end
diff --git a/spec/unit/hanami/model/sql/schema/date_spec.rb b/spec/unit/hanami/model/sql/schema/date_spec.rb
index d96095a9..730da655 100644
--- a/spec/unit/hanami/model/sql/schema/date_spec.rb
+++ b/spec/unit/hanami/model/sql/schema/date_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
RSpec.describe "Hanami::Model::Sql::Types::Schema::Date" do
let(:described_class) { Hanami::Model::Sql::Types::Schema::Date }
@@ -9,87 +11,87 @@ def to_date
end.new
end
- it 'returns nil for nil' do
+ it "returns nil for nil" do
input = nil
expect(described_class[input]).to eq(input)
end
- it 'coerces object that respond to #to_date' do
+ it "coerces object that respond to #to_date" do
expect(described_class[input]).to eq(input.to_date)
end
- it 'coerces string' do
+ it "coerces string" do
date = Date.today
input = date.to_s
expect(described_class[input]).to eq(date)
end
- it 'coerces Hanami string' do
+ it "coerces Hanami string" do
input = Hanami::Utils::String.new(Date.today)
expect(described_class[input]).to eq(Date.parse(input))
end
- it 'raises error for meaningless string' do
- input = 'foo'
+ it "raises error for meaningless string" do
+ input = "foo"
expect { described_class[input] }
- .to raise_error(ArgumentError, 'invalid date')
+ .to raise_error(Dry::Types::CoercionError, "invalid date")
end
- it 'raises error for symbol' do
+ it "raises error for symbol" do
input = :foo
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Date(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Date(): #{input.inspect}")
end
- it 'raises error for integer' do
+ it "raises error for integer" do
input = 11
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Date(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Date(): #{input.inspect}")
end
- it 'raises error for float' do
+ it "raises error for float" do
input = 3.14
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Date(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Date(): #{input.inspect}")
end
- it 'raises error for bigdecimal' do
+ it "raises error for bigdecimal" do
input = BigDecimal(3.14, 10)
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Date(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Date(): #{input.inspect}")
end
- it 'coerces date' do
+ it "coerces date" do
input = Date.today
date = input
expect(described_class[input]).to eq(date)
end
- it 'coerces datetime' do
+ it "coerces datetime" do
input = DateTime.new
date = input.to_date
expect(described_class[input]).to eq(date)
end
- it 'coerces time' do
+ it "coerces time" do
input = Time.now
date = input.to_date
expect(described_class[input]).to eq(date)
end
- it 'raises error for array' do
+ it "raises error for array" do
input = []
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Date(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Date(): #{input.inspect}")
end
- it 'raises error for hash' do
+ it "raises error for hash" do
input = {}
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Date(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Date(): #{input.inspect}")
end
end
diff --git a/spec/unit/hanami/model/sql/schema/date_time_spec.rb b/spec/unit/hanami/model/sql/schema/date_time_spec.rb
index b2b2c06f..0662071a 100644
--- a/spec/unit/hanami/model/sql/schema/date_time_spec.rb
+++ b/spec/unit/hanami/model/sql/schema/date_time_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
RSpec.describe "Hanami::Model::Sql::Types::Schema::DateTime" do
let(:described_class) { Hanami::Model::Sql::Types::Schema::DateTime }
@@ -9,87 +11,87 @@ def to_datetime
end.new
end
- it 'returns nil for nil' do
+ it "returns nil for nil" do
input = nil
expect(described_class[input]).to eq(input)
end
- it 'coerces object that respond to #to_datetime' do
+ it "coerces object that respond to #to_datetime" do
expect(described_class[input]).to eq(input.to_datetime)
end
- it 'coerces string' do
+ it "coerces string" do
date = DateTime.new
input = date.to_s
expect(described_class[input]).to eq(date)
end
- it 'coerces Hanami string' do
+ it "coerces Hanami string" do
input = Hanami::Utils::String.new(DateTime.new)
expect(described_class[input]).to eq(DateTime.parse(input))
end
- it 'raises error for meaningless string' do
- input = 'foo'
+ it "raises error for meaningless string" do
+ input = "foo"
expect { described_class[input] }
- .to raise_error(ArgumentError, 'invalid date')
+ .to raise_error(Dry::Types::CoercionError, "invalid date")
end
- it 'raises error for symbol' do
+ it "raises error for symbol" do
input = :foo
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for DateTime(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for DateTime(): #{input.inspect}")
end
- it 'raises error for integer' do
+ it "raises error for integer" do
input = 11
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for DateTime(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for DateTime(): #{input.inspect}")
end
- it 'raises error for float' do
+ it "raises error for float" do
input = 3.14
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for DateTime(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for DateTime(): #{input.inspect}")
end
- it 'raises error for bigdecimal' do
+ it "raises error for bigdecimal" do
input = BigDecimal(3.14, 10)
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for DateTime(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for DateTime(): #{input.inspect}")
end
- it 'coerces date' do
+ it "coerces date" do
input = Date.today
date_time = input.to_datetime
expect(described_class[input]).to eq(date_time)
end
- it 'coerces datetime' do
+ it "coerces datetime" do
input = DateTime.new
date_time = input
expect(described_class[input]).to eq(date_time)
end
- it 'coerces time' do
+ it "coerces time" do
input = Time.now
date_time = input.to_datetime
expect(described_class[input]).to be_within(2).of(date_time)
end
- it 'raises error for array' do
+ it "raises error for array" do
input = []
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for DateTime(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for DateTime(): #{input.inspect}")
end
- it 'raises error for hash' do
+ it "raises error for hash" do
input = {}
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for DateTime(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for DateTime(): #{input.inspect}")
end
end
diff --git a/spec/unit/hanami/model/sql/schema/decimal_spec.rb b/spec/unit/hanami/model/sql/schema/decimal_spec.rb
index 648498e0..8ec8c43f 100644
--- a/spec/unit/hanami/model/sql/schema/decimal_spec.rb
+++ b/spec/unit/hanami/model/sql/schema/decimal_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
RSpec.describe "Hanami::Model::Sql::Types::Schema::Decimal" do
let(:described_class) { Hanami::Model::Sql::Types::Schema::Decimal }
@@ -9,83 +11,83 @@ def to_d
end.new
end
- it 'returns nil for nil' do
+ it "returns nil for nil" do
input = nil
expect(described_class[input]).to eq(input)
end
- it 'coerces object that respond to #to_d' do
+ it "coerces object that respond to #to_d" do
expect(described_class[input]).to eq(input.to_d)
end
- it 'coerces string representing int' do
- input = '1'
+ it "coerces string representing int" do
+ input = "1"
expect(described_class[input]).to eq(input.to_d)
end
- it 'coerces Hanami string representing int' do
- input = Hanami::Utils::String.new('1')
+ it "coerces Hanami string representing int" do
+ input = Hanami::Utils::String.new("1")
expect(described_class[input]).to eq(input.to_d)
end
- it 'coerces string representing float' do
- input = '3.14'
+ it "coerces string representing float" do
+ input = "3.14"
expect(described_class[input]).to eq(input.to_d)
end
- it 'coerces Hanami string representing float' do
- input = Hanami::Utils::String.new('3.14')
+ it "coerces Hanami string representing float" do
+ input = Hanami::Utils::String.new("3.14")
expect(described_class[input]).to eq(input.to_d)
end
- it 'raises error for symbol' do
+ it "raises error for symbol" do
input = :house_11
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for BigDecimal(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for BigDecimal(): #{input.inspect}")
end
- it 'coerces integer' do
+ it "coerces integer" do
input = 23
expect(described_class[input]).to eq(input.to_d)
end
- it 'coerces float' do
+ it "coerces float" do
input = 3.14
expect(described_class[input]).to eq(input.to_d)
end
- it 'coerces bigdecimal' do
+ it "coerces bigdecimal" do
input = BigDecimal(3.14, 10)
expect(described_class[input]).to eq(input.to_d)
end
- it 'raises error for date' do
+ it "raises error for date" do
input = Date.today
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for BigDecimal(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for BigDecimal(): #{input.inspect}")
end
- it 'raises error for datetime' do
+ it "raises error for datetime" do
input = DateTime.new
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for BigDecimal(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for BigDecimal(): #{input.inspect}")
end
- it 'raises error for time' do
+ it "raises error for time" do
input = Time.now
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for BigDecimal(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for BigDecimal(): #{input.inspect}")
end
- it 'raises error for array' do
+ it "raises error for array" do
input = []
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for BigDecimal(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for BigDecimal(): #{input.inspect}")
end
- it 'raises error for hash' do
+ it "raises error for hash" do
input = {}
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for BigDecimal(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for BigDecimal(): #{input.inspect}")
end
end
diff --git a/spec/unit/hanami/model/sql/schema/float_spec.rb b/spec/unit/hanami/model/sql/schema/float_spec.rb
index a45d5ae2..60aad050 100644
--- a/spec/unit/hanami/model/sql/schema/float_spec.rb
+++ b/spec/unit/hanami/model/sql/schema/float_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
RSpec.describe "Hanami::Model::Sql::Types::Schema::Float" do
let(:described_class) { Hanami::Model::Sql::Types::Schema::Float }
@@ -9,89 +11,89 @@ def to_f
end.new
end
- it 'returns nil for nil' do
+ it "returns nil for nil" do
input = nil
expect(described_class[input]).to eq(input)
end
- it 'coerces object that respond to #to_f' do
+ it "coerces object that respond to #to_f" do
expect(described_class[input]).to eq(input.to_f)
end
- it 'coerces string representing int' do
- input = '1'
+ it "coerces string representing int" do
+ input = "1"
expect(described_class[input]).to eq(input.to_f)
end
- it 'coerces Hanami string representing int' do
- input = Hanami::Utils::String.new('1')
+ it "coerces Hanami string representing int" do
+ input = Hanami::Utils::String.new("1")
expect(described_class[input]).to eq(input.to_f)
end
- it 'coerces string representing float' do
- input = '3.14'
+ it "coerces string representing float" do
+ input = "3.14"
expect(described_class[input]).to eq(input.to_f)
end
- it 'coerces Hanami string representing float' do
- input = Hanami::Utils::String.new('3.14')
+ it "coerces Hanami string representing float" do
+ input = Hanami::Utils::String.new("3.14")
expect(described_class[input]).to eq(input.to_f)
end
- it 'raises error for meaningless string' do
- input = 'foo'
+ it "raises error for meaningless string" do
+ input = "foo"
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Float(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Float(): #{input.inspect}")
end
- it 'raises error for symbol' do
+ it "raises error for symbol" do
input = :house_11
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Float(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Float(): #{input.inspect}")
end
- it 'coerces integer' do
+ it "coerces integer" do
input = 23
expect(described_class[input]).to eq(input.to_f)
end
- it 'coerces float' do
+ it "coerces float" do
input = 3.14
expect(described_class[input]).to eq(input.to_f)
end
- it 'coerces bigdecimal' do
+ it "coerces bigdecimal" do
input = BigDecimal(3.14, 10)
expect(described_class[input]).to eq(input.to_f)
end
- it 'raises error for date' do
+ it "raises error for date" do
input = Date.today
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Float(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Float(): #{input.inspect}")
end
- it 'raises error for datetime' do
+ it "raises error for datetime" do
input = DateTime.new
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Float(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Float(): #{input.inspect}")
end
- it 'raises error for time' do
+ it "raises error for time" do
input = Time.now
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Float(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Float(): #{input.inspect}")
end
- it 'raises error for array' do
+ it "raises error for array" do
input = []
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Float(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Float(): #{input.inspect}")
end
- it 'raises error for hash' do
+ it "raises error for hash" do
input = {}
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Float(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Float(): #{input.inspect}")
end
end
diff --git a/spec/unit/hanami/model/sql/schema/hash_spec.rb b/spec/unit/hanami/model/sql/schema/hash_spec.rb
index 2640f2fb..eb75986c 100644
--- a/spec/unit/hanami/model/sql/schema/hash_spec.rb
+++ b/spec/unit/hanami/model/sql/schema/hash_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
RSpec.describe "Hanami::Model::Sql::Types::Schema::Hash" do
let(:described_class) { Hanami::Model::Sql::Types::Schema::Hash }
@@ -9,70 +11,70 @@ def to_hash
end.new
end
- it 'returns nil for nil' do
+ it "returns nil for nil" do
input = nil
expect(described_class[input]).to eq(input)
end
- it 'coerces object that respond to #to_hash' do
+ it "coerces object that respond to #to_hash" do
expect(described_class[input]).to eq(input.to_hash)
end
- it 'coerces string' do
- input = 'foo'
+ it "coerces string" do
+ input = "foo"
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Hash(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Hash(): #{input.inspect}")
end
- it 'raises error for symbol' do
+ it "raises error for symbol" do
input = :foo
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Hash(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Hash(): #{input.inspect}")
end
- it 'raises error for integer' do
+ it "raises error for integer" do
input = 11
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Hash(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Hash(): #{input.inspect}")
end
- it 'raises error for float' do
+ it "raises error for float" do
input = 3.14
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Hash(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Hash(): #{input.inspect}")
end
- it 'raises error for bigdecimal' do
+ it "raises error for bigdecimal" do
input = BigDecimal(3.14, 10)
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Hash(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Hash(): #{input.inspect}")
end
- it 'raises error for date' do
+ it "raises error for date" do
input = Date.today
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Hash(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Hash(): #{input.inspect}")
end
- it 'raises error for datetime' do
+ it "raises error for datetime" do
input = DateTime.new
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Hash(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Hash(): #{input.inspect}")
end
- it 'raises error for time' do
+ it "raises error for time" do
input = Time.now
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Hash(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Hash(): #{input.inspect}")
end
- it 'raises error for array' do
+ it "raises error for array" do
input = []
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Hash(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Hash(): #{input.inspect}")
end
- it 'coerces hash' do
+ it "coerces hash" do
input = {}
expect(described_class[input]).to eq(input)
end
diff --git a/spec/unit/hanami/model/sql/schema/int_spec.rb b/spec/unit/hanami/model/sql/schema/int_spec.rb
deleted file mode 100644
index 752d52f7..00000000
--- a/spec/unit/hanami/model/sql/schema/int_spec.rb
+++ /dev/null
@@ -1,87 +0,0 @@
-RSpec.describe "Hanami::Model::Sql::Types::Schema::Int" do
- let(:described_class) { Hanami::Model::Sql::Types::Schema::Int }
-
- let(:input) do
- Class.new do
- def to_int
- 23
- end
- end.new
- end
-
- it 'returns nil for nil' do
- input = nil
- expect(described_class[input]).to eq(input)
- end
-
- it 'coerces object that respond to #to_int' do
- expect(described_class[input]).to eq(input.to_int)
- end
-
- it 'coerces string representing int' do
- input = '1'
- expect(described_class[input]).to eq(input.to_i)
- end
-
- it 'coerces Hanami string representing int' do
- input = Hanami::Utils::String.new('1')
- expect(described_class[input]).to eq(input.to_i)
- end
-
- it 'raises error for meaningless string' do
- input = 'foo'
- expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Integer(): #{input.inspect}")
- end
-
- it 'raises error for symbol' do
- input = :house_11
- expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Integer(): #{input.inspect}")
- end
-
- it 'coerces integer' do
- input = 23
- expect(described_class[input]).to eq(input)
- end
-
- it 'coerces float' do
- input = 3.14
- expect(described_class[input]).to eq(input.to_i)
- end
-
- it 'coerces bigdecimal' do
- input = BigDecimal(3.14, 10)
- expect(described_class[input]).to eq(input.to_i)
- end
-
- it 'raises error for date' do
- input = Date.today
- expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Integer(): #{input.inspect}")
- end
-
- it 'raises error for datetime' do
- input = DateTime.new
- expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Integer(): #{input.inspect}")
- end
-
- it 'raises error for time' do
- input = Time.now
- expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Integer(): #{input.inspect}")
- end
-
- it 'raises error for array' do
- input = []
- expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Integer(): #{input.inspect}")
- end
-
- it 'raises error for hash' do
- input = {}
- expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Integer(): #{input.inspect}")
- end
-end
diff --git a/spec/unit/hanami/model/sql/schema/integer_spec.rb b/spec/unit/hanami/model/sql/schema/integer_spec.rb
new file mode 100644
index 00000000..87302630
--- /dev/null
+++ b/spec/unit/hanami/model/sql/schema/integer_spec.rb
@@ -0,0 +1,89 @@
+# frozen_string_literal: true
+
+RSpec.describe "Hanami::Model::Sql::Types::Schema::Integer" do
+ let(:described_class) { Hanami::Model::Sql::Types::Schema::Integer }
+
+ let(:input) do
+ Class.new do
+ def to_int
+ 23
+ end
+ end.new
+ end
+
+ it "returns nil for nil" do
+ input = nil
+ expect(described_class[input]).to eq(input)
+ end
+
+ it "coerces object that respond to #to_int" do
+ expect(described_class[input]).to eq(input.to_int)
+ end
+
+ it "coerces string representing int" do
+ input = "1"
+ expect(described_class[input]).to eq(input.to_i)
+ end
+
+ it "coerces Hanami string representing int" do
+ input = Hanami::Utils::String.new("1")
+ expect(described_class[input]).to eq(input.to_i)
+ end
+
+ it "raises error for meaningless string" do
+ input = "foo"
+ expect { described_class[input] }
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Integer(): #{input.inspect}")
+ end
+
+ it "raises error for symbol" do
+ input = :house_11
+ expect { described_class[input] }
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Integer(): #{input.inspect}")
+ end
+
+ it "coerces integer" do
+ input = 23
+ expect(described_class[input]).to eq(input)
+ end
+
+ it "coerces float" do
+ input = 3.14
+ expect(described_class[input]).to eq(input.to_i)
+ end
+
+ it "coerces bigdecimal" do
+ input = BigDecimal(3.14, 10)
+ expect(described_class[input]).to eq(input.to_i)
+ end
+
+ it "raises error for date" do
+ input = Date.today
+ expect { described_class[input] }
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Integer(): #{input.inspect}")
+ end
+
+ it "raises error for datetime" do
+ input = DateTime.new
+ expect { described_class[input] }
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Integer(): #{input.inspect}")
+ end
+
+ it "raises error for time" do
+ input = Time.now
+ expect { described_class[input] }
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Integer(): #{input.inspect}")
+ end
+
+ it "raises error for array" do
+ input = []
+ expect { described_class[input] }
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Integer(): #{input.inspect}")
+ end
+
+ it "raises error for hash" do
+ input = {}
+ expect { described_class[input] }
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Integer(): #{input.inspect}")
+ end
+end
diff --git a/spec/unit/hanami/model/sql/schema/string_spec.rb b/spec/unit/hanami/model/sql/schema/string_spec.rb
index c7be7943..6fc06063 100644
--- a/spec/unit/hanami/model/sql/schema/string_spec.rb
+++ b/spec/unit/hanami/model/sql/schema/string_spec.rb
@@ -1,57 +1,59 @@
+# frozen_string_literal: true
+
RSpec.describe "Hanami::Model::Sql::Types::Schema::String" do
let(:described_class) { Hanami::Model::Sql::Types::Schema::String }
- it 'returns nil for nil' do
+ it "returns nil for nil" do
input = nil
expect(described_class[input]).to eq(input)
end
- it 'coerces string' do
- input = 'foo'
+ it "coerces string" do
+ input = "foo"
expect(described_class[input]).to eq(input.to_s)
end
- it 'coerces symbol' do
+ it "coerces symbol" do
input = :foo
expect(described_class[input]).to eq(input.to_s)
end
- it 'coerces integer' do
+ it "coerces integer" do
input = 23
expect(described_class[input]).to eq(input.to_s)
end
- it 'coerces float' do
+ it "coerces float" do
input = 3.14
expect(described_class[input]).to eq(input.to_s)
end
- it 'coerces bigdecimal' do
+ it "coerces bigdecimal" do
input = BigDecimal(3.14, 10)
expect(described_class[input]).to eq(input.to_s)
end
- it 'coerces date' do
+ it "coerces date" do
input = Date.today
expect(described_class[input]).to eq(input.to_s)
end
- it 'coerces datetime' do
+ it "coerces datetime" do
input = DateTime.new
expect(described_class[input]).to eq(input.to_s)
end
- it 'coerces time' do
+ it "coerces time" do
input = Time.now
expect(described_class[input]).to eq(input.to_s)
end
- it 'coerces array' do
+ it "coerces array" do
input = []
expect(described_class[input]).to eq(input.to_s)
end
- it 'coerces hash' do
+ it "coerces hash" do
input = {}
expect(described_class[input]).to eq(input.to_s)
end
diff --git a/spec/unit/hanami/model/sql/schema/time_spec.rb b/spec/unit/hanami/model/sql/schema/time_spec.rb
index 7fcf8d5a..e2eaffee 100644
--- a/spec/unit/hanami/model/sql/schema/time_spec.rb
+++ b/spec/unit/hanami/model/sql/schema/time_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
RSpec.describe "Hanami::Model::Sql::Types::Schema::Time" do
let(:described_class) { Hanami::Model::Sql::Types::Schema::Time }
@@ -9,88 +11,88 @@ def to_time
end.new
end
- it 'returns nil for nil' do
+ it "returns nil for nil" do
input = nil
expect(described_class[input]).to eq(input)
end
- it 'coerces object that respond to #to_time' do
+ it "coerces object that respond to #to_time" do
expect(described_class[input]).to be_within(2).of(input.to_time)
end
- it 'coerces string' do
+ it "coerces string" do
time = Time.now
input = time.to_s
expect(described_class[input]).to be_within(2).of(time)
end
- it 'coerces Hanami string' do
+ it "coerces Hanami string" do
input = Hanami::Utils::String.new(Time.now)
expect(described_class[input]).to be_within(2).of(Time.parse(input))
end
- it 'raises error for meaningless string' do
- input = 'foo'
+ it "raises error for meaningless string" do
+ input = "foo"
expect { described_class[input] }
- .to raise_error(ArgumentError, "no time information in #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "no time information in #{input.inspect}")
end
- it 'raises error for symbol' do
+ it "raises error for symbol" do
input = :foo
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Time(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Time(): #{input.inspect}")
end
- it 'coerces integer' do
+ it "coerces integer" do
input = 11
time = Time.at(input)
expect(described_class[input]).to be_within(2).of(time)
end
- it 'raises error for float' do
+ it "raises error for float" do
input = 3.14
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Time(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Time(): #{input.inspect}")
end
- it 'raises error for bigdecimal' do
+ it "raises error for bigdecimal" do
input = BigDecimal(3.14, 10)
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Time(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Time(): #{input.inspect}")
end
- it 'coerces date' do
+ it "coerces date" do
input = Date.today
time = input.to_time
expect(described_class[input]).to be_within(2).of(time)
end
- it 'coerces datetime' do
+ it "coerces datetime" do
input = DateTime.new
time = input.to_time
expect(described_class[input]).to be_within(2).of(time)
end
- it 'coerces time' do
+ it "coerces time" do
input = Time.now
time = input
expect(described_class[input]).to be_within(2).of(time)
end
- it 'raises error for array' do
+ it "raises error for array" do
input = []
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Time(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Time(): #{input.inspect}")
end
- it 'raises error for hash' do
+ it "raises error for hash" do
input = {}
expect { described_class[input] }
- .to raise_error(ArgumentError, "invalid value for Time(): #{input.inspect}")
+ .to raise_error(Dry::Types::CoercionError, "invalid value for Time(): #{input.inspect}")
end
end
diff --git a/spec/unit/hanami/model/sql_spec.rb b/spec/unit/hanami/model/sql_spec.rb
index 591f2561..3ee7416f 100644
--- a/spec/unit/hanami/model/sql_spec.rb
+++ b/spec/unit/hanami/model/sql_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
RSpec.describe Hanami::Model::Sql do
describe ".migration" do
it "returns a new migration" do
diff --git a/spec/unit/hanami/model/unique_constraint_violation_error_spec.rb b/spec/unit/hanami/model/unique_constraint_violation_error_spec.rb
index f3184f9d..08aa43f0 100644
--- a/spec/unit/hanami/model/unique_constraint_violation_error_spec.rb
+++ b/spec/unit/hanami/model/unique_constraint_violation_error_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
RSpec.describe Hanami::Model::UniqueConstraintViolationError do
it "inherits from Hanami::Model::ConstraintViolationError" do
expect(described_class.ancestors).to include(Hanami::Model::ConstraintViolationError)
diff --git a/spec/unit/hanami/model/version_spec.rb b/spec/unit/hanami/model/version_spec.rb
index 1172b6f7..b8b6cad2 100644
--- a/spec/unit/hanami/model/version_spec.rb
+++ b/spec/unit/hanami/model/version_spec.rb
@@ -1,5 +1,7 @@
+# frozen_string_literal: true
+
RSpec.describe "Hanami::Model::VERSION" do
it "exposes version" do
- expect(Hanami::Model::VERSION).to eq("1.3.2")
+ expect(Hanami::Model::VERSION).to eq("2.0.0.alpha1")
end
end