rom-sql 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +16 -12
- data/CHANGELOG.md +23 -0
- data/Gemfile +11 -3
- data/README.md +1 -7
- data/lib/rom/sql.rb +4 -7
- data/lib/rom/sql/association.rb +1 -1
- data/lib/rom/sql/association/one_to_many.rb +44 -1
- data/lib/rom/sql/association/one_to_one.rb +1 -38
- data/lib/rom/sql/commands.rb +0 -3
- data/lib/rom/sql/commands/error_wrapper.rb +1 -1
- data/lib/rom/sql/errors.rb +4 -1
- data/lib/rom/sql/extensions.rb +19 -0
- data/lib/rom/sql/{support → extensions}/active_support_notifications.rb +0 -0
- data/lib/rom/sql/extensions/postgres.rb +3 -0
- data/lib/rom/sql/{commands/postgres.rb → extensions/postgres/commands.rb} +38 -0
- data/lib/rom/sql/extensions/postgres/inferrer.rb +64 -0
- data/lib/rom/sql/extensions/postgres/types.rb +65 -0
- data/lib/rom/sql/{support → extensions}/rails_log_subscriber.rb +0 -0
- data/lib/rom/sql/gateway.rb +15 -4
- data/lib/rom/sql/relation.rb +6 -2
- data/lib/rom/sql/relation/reading.rb +18 -0
- data/lib/rom/sql/schema/dsl.rb +7 -4
- data/lib/rom/sql/schema/inferrer.rb +44 -31
- data/lib/rom/sql/types.rb +5 -1
- data/lib/rom/sql/version.rb +1 -1
- data/rom-sql.gemspec +14 -13
- data/spec/extensions/postgres/inferrer_spec.rb +40 -0
- data/spec/extensions/postgres/integration_spec.rb +38 -0
- data/spec/extensions/postgres/types_spec.rb +115 -0
- data/spec/integration/association/many_to_many_spec.rb +2 -1
- data/spec/integration/association/one_to_one_spec.rb +6 -4
- data/spec/integration/combine_spec.rb +1 -1
- data/spec/integration/commands/create_spec.rb +46 -21
- data/spec/integration/commands/delete_spec.rb +13 -38
- data/spec/integration/commands/update_spec.rb +19 -41
- data/spec/integration/commands/upsert_spec.rb +1 -1
- data/spec/integration/gateway_spec.rb +5 -9
- data/spec/integration/migration_spec.rb +6 -7
- data/spec/integration/read_spec.rb +30 -38
- data/spec/integration/schema_inference_spec.rb +211 -49
- data/spec/integration/setup_spec.rb +5 -5
- data/spec/integration/support/active_support_notifications_spec.rb +4 -3
- data/spec/integration/support/rails_log_subscriber_spec.rb +5 -4
- data/spec/shared/database_setup.rb +21 -6
- data/spec/spec_helper.rb +44 -35
- data/spec/unit/association/one_to_many_spec.rb +20 -0
- data/spec/unit/association/one_to_one_spec.rb +23 -2
- data/spec/unit/association_errors_spec.rb +1 -1
- data/spec/unit/gateway_spec.rb +9 -8
- data/spec/unit/logger_spec.rb +1 -1
- data/spec/unit/migration_tasks_spec.rb +3 -3
- data/spec/unit/migrator_spec.rb +3 -2
- data/spec/unit/plugin/assoc_macros/combined_associations_spec.rb +1 -1
- data/spec/unit/plugin/assoc_macros/many_to_many_spec.rb +1 -1
- data/spec/unit/plugin/assoc_macros/many_to_one_spec.rb +1 -1
- data/spec/unit/plugin/assoc_macros/one_to_many_spec.rb +1 -1
- data/spec/unit/relation/associations_spec.rb +27 -0
- data/spec/unit/relation/avg_spec.rb +11 -0
- data/spec/unit/relation/by_pk_spec.rb +15 -0
- data/spec/unit/relation/dataset_spec.rb +48 -0
- data/spec/unit/relation/distinct_spec.rb +14 -0
- data/spec/unit/relation/exclude_spec.rb +13 -0
- data/spec/unit/relation/fetch_spec.rb +21 -0
- data/spec/unit/relation/having_spec.rb +20 -0
- data/spec/unit/relation/inner_join_spec.rb +22 -0
- data/spec/unit/relation/inspect_spec.rb +11 -0
- data/spec/unit/relation/invert_spec.rb +12 -0
- data/spec/unit/relation/left_join_spec.rb +16 -0
- data/spec/unit/relation/map_spec.rb +16 -0
- data/spec/unit/relation/max_spec.rb +11 -0
- data/spec/unit/relation/min_spec.rb +11 -0
- data/spec/unit/relation/pluck_spec.rb +11 -0
- data/spec/unit/relation/prefix_spec.rb +27 -0
- data/spec/unit/relation/primary_key_spec.rb +27 -0
- data/spec/unit/relation/project_spec.rb +22 -0
- data/spec/unit/relation/qualified_columns_spec.rb +27 -0
- data/spec/unit/relation/rename_spec.rb +21 -0
- data/spec/unit/relation/sum_spec.rb +11 -0
- data/spec/unit/relation/union_spec.rb +19 -0
- data/spec/unit/relation/unique_predicate_spec.rb +18 -0
- data/spec/unit/schema_spec.rb +1 -1
- data/spec/unit/types_spec.rb +4 -21
- metadata +79 -11
- data/lib/rom/sql/commands_ext/postgres.rb +0 -45
- data/lib/rom/sql/types/pg.rb +0 -26
- data/spec/unit/relation_spec.rb +0 -272
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'dry-types'
|
2
|
+
require 'sequel'
|
3
|
+
|
4
|
+
Sequel.extension(*%i(pg_array pg_array_ops pg_json pg_json_ops))
|
5
|
+
|
6
|
+
module ROM
|
7
|
+
module SQL
|
8
|
+
module Types
|
9
|
+
module PG
|
10
|
+
# UUID
|
11
|
+
|
12
|
+
UUID = Types::String
|
13
|
+
|
14
|
+
# Array
|
15
|
+
|
16
|
+
Array = Dry::Types::Definition
|
17
|
+
.new(Sequel::Postgres::PGArray)
|
18
|
+
|
19
|
+
def self.Array(db_type)
|
20
|
+
Array.constructor(-> (v) { Sequel.pg_array(v, db_type) }).meta(type: db_type)
|
21
|
+
end
|
22
|
+
|
23
|
+
# JSON
|
24
|
+
|
25
|
+
JSONArray = Dry::Types::Definition
|
26
|
+
.new(Sequel::Postgres::JSONArray)
|
27
|
+
.constructor(Sequel.method(:pg_json))
|
28
|
+
|
29
|
+
JSONHash = Dry::Types::Definition
|
30
|
+
.new(Sequel::Postgres::JSONHash)
|
31
|
+
.constructor(Sequel.method(:pg_json))
|
32
|
+
|
33
|
+
JSONOp = Dry::Types::Definition
|
34
|
+
.new(Sequel::Postgres::JSONOp)
|
35
|
+
.constructor(Sequel.method(:pg_json))
|
36
|
+
|
37
|
+
JSON = JSONArray | JSONHash | JSONOp
|
38
|
+
|
39
|
+
# JSONB
|
40
|
+
|
41
|
+
JSONBArray = Dry::Types::Definition
|
42
|
+
.new(Sequel::Postgres::JSONBArray)
|
43
|
+
.constructor(Sequel.method(:pg_jsonb))
|
44
|
+
|
45
|
+
JSONBHash = Dry::Types::Definition
|
46
|
+
.new(Sequel::Postgres::JSONBHash)
|
47
|
+
.constructor(Sequel.method(:pg_jsonb))
|
48
|
+
|
49
|
+
JSONBOp = Dry::Types::Definition
|
50
|
+
.new(Sequel::Postgres::JSONBOp)
|
51
|
+
.constructor(Sequel.method(:pg_jsonb))
|
52
|
+
|
53
|
+
JSONB = JSONBArray | JSONBHash | JSONBOp
|
54
|
+
|
55
|
+
Bytea = Dry::Types::Definition
|
56
|
+
.new(Sequel::SQL::Blob)
|
57
|
+
.constructor(Sequel::SQL::Blob.method(:new))
|
58
|
+
|
59
|
+
# MONEY
|
60
|
+
|
61
|
+
Money = Types::Decimal
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
File without changes
|
data/lib/rom/sql/gateway.rb
CHANGED
@@ -23,6 +23,10 @@ module ROM
|
|
23
23
|
attr_accessor :instance
|
24
24
|
end
|
25
25
|
|
26
|
+
CONNECTION_EXTENSIONS = {
|
27
|
+
postgres: %i(pg_array pg_json)
|
28
|
+
}.freeze
|
29
|
+
|
26
30
|
# Return optionally configured logger
|
27
31
|
#
|
28
32
|
# @return [Object] logger
|
@@ -56,7 +60,7 @@ module ROM
|
|
56
60
|
conn_options = options.reject { |k, _| repo_options.include?(k) }
|
57
61
|
|
58
62
|
@connection = connect(uri, conn_options)
|
59
|
-
|
63
|
+
load_extensions(Array(options[:extensions]))
|
60
64
|
|
61
65
|
super(uri, options.reject { |k, _| conn_options.keys.include?(k) })
|
62
66
|
|
@@ -177,11 +181,18 @@ module ROM
|
|
177
181
|
end
|
178
182
|
end
|
179
183
|
|
180
|
-
#
|
184
|
+
# Load database-specific extensions
|
181
185
|
#
|
182
186
|
# @api private
|
183
|
-
def
|
184
|
-
connection.
|
187
|
+
def load_extensions(exts)
|
188
|
+
db_type = connection.database_type.to_sym
|
189
|
+
|
190
|
+
if ROM::SQL.available_extension?(db_type)
|
191
|
+
ROM::SQL.load_extensions(db_type)
|
192
|
+
end
|
193
|
+
|
194
|
+
extensions = (CONNECTION_EXTENSIONS.fetch(db_type) { [] } + exts).uniq
|
195
|
+
connection.extension(*extensions)
|
185
196
|
end
|
186
197
|
end
|
187
198
|
end
|
data/lib/rom/sql/relation.rb
CHANGED
@@ -42,14 +42,18 @@ module ROM
|
|
42
42
|
|
43
43
|
klass.class_eval do
|
44
44
|
schema_dsl SQL::Schema::DSL
|
45
|
-
schema_inferrer
|
45
|
+
schema_inferrer -> (dataset, gateway) do
|
46
|
+
inferrer_for_db = ROM::SQL::Schema::Inferrer.get(gateway.connection.database_type.to_sym)
|
47
|
+
inferrer_for_db.new.call(dataset, gateway)
|
48
|
+
end
|
46
49
|
|
47
50
|
dataset do
|
48
51
|
table = opts[:from].first
|
49
52
|
|
50
53
|
if db.table_exists?(table)
|
51
54
|
pk_header = klass.primary_key_header(db, table)
|
52
|
-
|
55
|
+
col_names = klass.schema ? klass.schema.attributes.keys : columns
|
56
|
+
select(*col_names).order(*pk_header.qualified)
|
53
57
|
else
|
54
58
|
self
|
55
59
|
end
|
@@ -305,6 +305,24 @@ module ROM
|
|
305
305
|
__new__(dataset.__send__(__method__, *args, &block))
|
306
306
|
end
|
307
307
|
|
308
|
+
# Restrict a relation to match grouping criteria
|
309
|
+
#
|
310
|
+
# @example
|
311
|
+
# users.with_task_count.having( task_count: 2 )
|
312
|
+
#
|
313
|
+
# users.with_task_count.having { task_count > 3 }
|
314
|
+
#
|
315
|
+
# @param [Hash] *args An optional hash with conditions for HAVING clause
|
316
|
+
#
|
317
|
+
# @return [Relation]
|
318
|
+
#
|
319
|
+
# @see http://sequel.jeremyevans.net/rdoc/files/doc/dataset_filtering_rdoc.html
|
320
|
+
#
|
321
|
+
# @api public
|
322
|
+
def having(*args, &block)
|
323
|
+
__new__(dataset.__send__(__method__, *args, &block))
|
324
|
+
end
|
325
|
+
|
308
326
|
# Inverts the current WHERE and HAVING clauses. If there is neither a
|
309
327
|
# WHERE or HAVING clause, adds a WHERE clause that is always false.
|
310
328
|
#
|
data/lib/rom/sql/schema/dsl.rb
CHANGED
@@ -16,10 +16,13 @@ module ROM
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def opts
|
19
|
-
opts = {}
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
opts = { inferrer: inferrer }
|
20
|
+
|
21
|
+
if associations_dsl
|
22
|
+
{ **opts, associations: associations_dsl.call }
|
23
|
+
else
|
24
|
+
opts
|
25
|
+
end
|
23
26
|
end
|
24
27
|
end
|
25
28
|
end
|
@@ -1,27 +1,39 @@
|
|
1
1
|
module ROM
|
2
2
|
module SQL
|
3
3
|
class Schema < ROM::Schema
|
4
|
+
# @api private
|
4
5
|
class Inferrer
|
5
6
|
extend ClassMacros
|
6
7
|
|
7
|
-
defines :
|
8
|
+
defines :ruby_type_mapping, :numeric_pk_type, :db_type, :db_registry
|
8
9
|
|
9
|
-
|
10
|
-
integer: Types::
|
11
|
-
string: Types::
|
12
|
-
date: Types::
|
13
|
-
datetime: Types::
|
14
|
-
boolean: Types::
|
15
|
-
decimal: Types::
|
16
|
-
|
10
|
+
ruby_type_mapping(
|
11
|
+
integer: Types::Int,
|
12
|
+
string: Types::String,
|
13
|
+
date: Types::Date,
|
14
|
+
datetime: Types::Time,
|
15
|
+
boolean: Types::Bool,
|
16
|
+
decimal: Types::Decimal,
|
17
|
+
float: Types::Float,
|
18
|
+
blob: Types::Blob
|
17
19
|
).freeze
|
18
20
|
|
19
|
-
|
21
|
+
numeric_pk_type Types::Serial
|
20
22
|
|
21
|
-
|
23
|
+
db_registry Hash.new(self)
|
22
24
|
|
23
|
-
def
|
24
|
-
|
25
|
+
def self.inherited(klass)
|
26
|
+
super
|
27
|
+
|
28
|
+
Inferrer.db_registry[klass.db_type] = klass unless klass.name.nil?
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.[](type)
|
32
|
+
Class.new(self) { db_type(type) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.get(type)
|
36
|
+
db_registry[type]
|
25
37
|
end
|
26
38
|
|
27
39
|
# @api private
|
@@ -29,33 +41,35 @@ module ROM
|
|
29
41
|
columns = gateway.connection.schema(dataset)
|
30
42
|
fks = fks_for(gateway, dataset)
|
31
43
|
|
32
|
-
columns.
|
33
|
-
|
44
|
+
columns.each_with_object({}) do |(name, definition), attrs|
|
45
|
+
type = build_type(definition.merge(foreign_key: fks[name]))
|
46
|
+
attrs[name] = type.meta(name: name)
|
34
47
|
end
|
35
|
-
|
36
|
-
pks = columns
|
37
|
-
.map { |(name, definition)| name if definition.fetch(:primary_key) }
|
38
|
-
.compact
|
39
|
-
|
40
|
-
dsl.primary_key(*pks) if pks.any?
|
41
|
-
|
42
|
-
dsl.attributes
|
43
48
|
end
|
44
49
|
|
45
50
|
private
|
46
51
|
|
47
|
-
|
48
|
-
def build_type(primary_key: , type: , allow_null: , foreign_key: , **rest)
|
52
|
+
def build_type(primary_key:, db_type:, type:, allow_null:, foreign_key:, **rest)
|
49
53
|
if primary_key
|
50
|
-
|
54
|
+
map_pk_type(type, db_type)
|
51
55
|
else
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
+
mapped_type = map_type(type, db_type)
|
57
|
+
mapped_type = mapped_type.optional if allow_null
|
58
|
+
mapped_type = mapped_type.meta(foreign_key: true, relation: foreign_key) if foreign_key
|
59
|
+
mapped_type
|
56
60
|
end
|
57
61
|
end
|
58
62
|
|
63
|
+
def map_pk_type(_ruby_type, _db_type)
|
64
|
+
self.class.numeric_pk_type.meta(primary_key: true)
|
65
|
+
end
|
66
|
+
|
67
|
+
def map_type(ruby_type, db_type)
|
68
|
+
self.class.ruby_type_mapping.fetch(ruby_type) {
|
69
|
+
raise UnknownDBTypeError, "Cannot find corresponding type for #{ruby_type || db_type}"
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
59
73
|
# @api private
|
60
74
|
def fks_for(gateway, dataset)
|
61
75
|
gateway.connection.foreign_key_list(dataset).each_with_object({}) do |definition, fks|
|
@@ -65,7 +79,6 @@ module ROM
|
|
65
79
|
end
|
66
80
|
end
|
67
81
|
|
68
|
-
# @api private
|
69
82
|
def build_fk(columns: , table: , **rest)
|
70
83
|
if columns.size == 1
|
71
84
|
[columns[0], table]
|
data/lib/rom/sql/types.rb
CHANGED
@@ -5,7 +5,11 @@ module ROM
|
|
5
5
|
module Types
|
6
6
|
include ROM::Types
|
7
7
|
|
8
|
-
Serial =
|
8
|
+
Serial = Int.constrained(gt: 0).meta(primary_key: true)
|
9
|
+
|
10
|
+
Blob = Dry::Types::Definition
|
11
|
+
.new(Sequel::SQL::Blob)
|
12
|
+
.constructor(Sequel::SQL::Blob.method(:new))
|
9
13
|
end
|
10
14
|
end
|
11
15
|
end
|
data/lib/rom/sql/version.rb
CHANGED
data/rom-sql.gemspec
CHANGED
@@ -4,26 +4,27 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'rom/sql/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'rom-sql'
|
8
8
|
spec.version = ROM::SQL::VERSION.dup
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
9
|
+
spec.authors = ['Piotr Solnica']
|
10
|
+
spec.email = ['piotr.solnica@gmail.com']
|
11
11
|
spec.summary = 'SQL databases support for ROM'
|
12
12
|
spec.description = spec.summary
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
13
|
+
spec.homepage = 'http://rom-rb.org'
|
14
|
+
spec.license = 'MIT'
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0")
|
17
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = [
|
19
|
+
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.add_runtime_dependency
|
22
|
-
spec.add_runtime_dependency
|
23
|
-
spec.add_runtime_dependency
|
24
|
-
spec.add_runtime_dependency
|
25
|
-
spec.add_runtime_dependency
|
21
|
+
spec.add_runtime_dependency 'sequel', '~> 4.25'
|
22
|
+
spec.add_runtime_dependency 'dry-equalizer', '~> 0.2'
|
23
|
+
spec.add_runtime_dependency 'dry-types', '~> 0.9'
|
24
|
+
spec.add_runtime_dependency 'dry-core', '~> 0.2'
|
25
|
+
spec.add_runtime_dependency 'rom', '~> 2.0'
|
26
|
+
spec.add_runtime_dependency 'rom-support', '~> 2.0'
|
26
27
|
|
27
|
-
spec.add_development_dependency
|
28
|
-
spec.add_development_dependency
|
28
|
+
spec.add_development_dependency 'bundler'
|
29
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
29
30
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
RSpec.describe 'ROM::SQL::Schema::PostgresInferrer', :postgres do
|
2
|
+
include_context 'database setup'
|
3
|
+
|
4
|
+
before do
|
5
|
+
conn.drop_table?(:test_inferrence)
|
6
|
+
|
7
|
+
conn.create_table :test_inferrence do
|
8
|
+
primary_key :id, :uuid
|
9
|
+
Json :json_data
|
10
|
+
Jsonb :jsonb_data
|
11
|
+
Decimal :money, null: false
|
12
|
+
column :tags, "text[]"
|
13
|
+
column :tag_ids, "bigint[]"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:dataset) { :test_inferrence }
|
18
|
+
|
19
|
+
let(:schema) { container.relations[dataset].schema }
|
20
|
+
|
21
|
+
context 'inferring db-specific attributes' do
|
22
|
+
before do
|
23
|
+
dataset = self.dataset
|
24
|
+
conf.relation(dataset) do
|
25
|
+
schema(dataset, infer: true)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'can infer attributes for dataset' do
|
30
|
+
expect(schema.attributes).to eql(
|
31
|
+
id: ROM::SQL::Types::PG::UUID.meta(name: :id, primary_key: true),
|
32
|
+
json_data: ROM::SQL::Types::PG::JSON.optional.meta(name: :json_data),
|
33
|
+
jsonb_data: ROM::SQL::Types::PG::JSONB.optional.meta(name: :jsonb_data),
|
34
|
+
money: ROM::SQL::Types::Decimal.meta(name: :money),
|
35
|
+
tags: ROM::SQL::Types::PG::Array('text').optional.meta(name: :tags),
|
36
|
+
tag_ids: ROM::SQL::Types::PG::Array('biging').optional.meta(name: :tag_ids)
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
RSpec.describe 'PostgreSQL extension', :postgres do
|
2
|
+
include_context 'database setup'
|
3
|
+
|
4
|
+
before do
|
5
|
+
conn.drop_table?(:pg_people)
|
6
|
+
conn.drop_table?(:people)
|
7
|
+
|
8
|
+
conn.create_table :pg_people do
|
9
|
+
primary_key :id
|
10
|
+
String :name
|
11
|
+
column :tags, "text[]"
|
12
|
+
end
|
13
|
+
|
14
|
+
conf.relation(:people) do
|
15
|
+
schema(:pg_people, infer: true)
|
16
|
+
end
|
17
|
+
|
18
|
+
conf.commands(:people) do
|
19
|
+
define(:create)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:people_relation) { relations[:people] }
|
24
|
+
|
25
|
+
describe 'using arrays' do
|
26
|
+
let(:people) { commands[:people] }
|
27
|
+
|
28
|
+
it 'inserts array values' do
|
29
|
+
people.create.call(name: 'John Doe', tags: ['foo'])
|
30
|
+
expect(people_relation.to_a).to eq([id: 1, name: 'John Doe', tags: ['foo']])
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'inserts empty arrays' do
|
34
|
+
people.create.call(name: 'John Doe', tags: [])
|
35
|
+
expect(people_relation.to_a).to eq([id: 1, name: 'John Doe', tags: []])
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
RSpec.describe 'ROM::SQL::Types' do
|
2
|
+
describe 'ROM::SQL::Types::PG::JSON' do
|
3
|
+
it 'coerces to pg json hash' do
|
4
|
+
input = { foo: 'bar' }
|
5
|
+
|
6
|
+
expect(ROM::SQL::Types::PG::JSON[input]).to eql(Sequel.pg_json(input))
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'coerces to pg json array' do
|
10
|
+
input = [1, 2, 3]
|
11
|
+
output = ROM::SQL::Types::PG::JSON[input]
|
12
|
+
|
13
|
+
expect(output).to be_instance_of(Sequel::Postgres::JSONArray)
|
14
|
+
expect(output.to_a).to eql(input)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'ROM::SQL::Types::PG::Bytea' do
|
19
|
+
it 'coerces strings to Sequel::SQL::Blob' do
|
20
|
+
input = 'sutin'
|
21
|
+
output = ROM::SQL::Types::PG::Bytea[input]
|
22
|
+
|
23
|
+
expect(output).to be_instance_of(Sequel::SQL::Blob)
|
24
|
+
expect(output).to eql('sutin')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe ROM::SQL::Types::PG::UUID do
|
29
|
+
it 'coerces strings to UUID' do
|
30
|
+
input = SecureRandom.uuid
|
31
|
+
output = described_class[input]
|
32
|
+
|
33
|
+
expect(output).to be_instance_of(String)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe ROM::SQL::Types::PG::Array do
|
38
|
+
it 'coerces to pg array' do
|
39
|
+
input = [1, 2, 3]
|
40
|
+
output = ROM::SQL::Types::PG::Array('integer')[input]
|
41
|
+
|
42
|
+
expect(output).to be_instance_of(Sequel::Postgres::PGArray)
|
43
|
+
expect(output.to_a).to eql(input)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'accepts any other type of objects' do
|
47
|
+
input = [nil, 1, 'sutin', :sutin, 1.0, {}].sample
|
48
|
+
output = ROM::SQL::Types::PG::Array('integer')[input]
|
49
|
+
|
50
|
+
expect(output).to be_instance_of(Sequel::Postgres::ArrayOp)
|
51
|
+
expect(output.value).to eql(input)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe ROM::SQL::Types::PG::JSON do
|
56
|
+
it 'coerces to pg json hash' do
|
57
|
+
input = { foo: 'bar' }
|
58
|
+
output = described_class[input]
|
59
|
+
|
60
|
+
expect(output).to be_instance_of(Sequel::Postgres::JSONHash)
|
61
|
+
expect(output).to eql(Sequel.pg_json(input))
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'coerces to pg json array' do
|
65
|
+
input = [1, 2, 3]
|
66
|
+
output = described_class[input]
|
67
|
+
|
68
|
+
expect(output).to be_instance_of(Sequel::Postgres::JSONArray)
|
69
|
+
expect(output.to_a).to eql(input)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'accepts any other type of objects' do
|
73
|
+
input = [nil, 1, 'sutin', :sutin, 1.0].sample
|
74
|
+
output = described_class[input]
|
75
|
+
|
76
|
+
expect(output).to be_instance_of(Sequel::Postgres::JSONOp)
|
77
|
+
expect(output.value).to eql(input)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe ROM::SQL::Types::PG::JSONB do
|
82
|
+
it 'coerces to pg jsonb hash' do
|
83
|
+
input = { foo: 'bar' }
|
84
|
+
output = described_class[input]
|
85
|
+
|
86
|
+
expect(output).to be_instance_of(Sequel::Postgres::JSONBHash)
|
87
|
+
expect(output).to eql(Sequel.pg_jsonb(input))
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'coerces to pg jsonb array' do
|
91
|
+
input = [1, 2, 3]
|
92
|
+
output = described_class[input]
|
93
|
+
|
94
|
+
expect(output).to be_instance_of(Sequel::Postgres::JSONBArray)
|
95
|
+
expect(output.to_a).to eql(input)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'accepts any other type of objects' do
|
99
|
+
input = [nil, 1, 'sutin', :sutin, 1.0].sample
|
100
|
+
output = described_class[input]
|
101
|
+
|
102
|
+
expect(output).to be_instance_of(Sequel::Postgres::JSONBOp)
|
103
|
+
expect(output.value).to eql(input)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe ROM::SQL::Types::PG::Money do
|
108
|
+
it 'coerces to pg Money' do
|
109
|
+
input = BigDecimal.new(1.0, 2)
|
110
|
+
output = described_class[input]
|
111
|
+
|
112
|
+
expect(output).to be_instance_of(BigDecimal)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|