rom-sql 0.9.1 → 1.0.0.beta1
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 +1 -1
- data/CHANGELOG.md +32 -0
- data/Gemfile +4 -1
- data/lib/rom/plugins/relation/sql/auto_wrap.rb +1 -3
- data/lib/rom/sql/association.rb +33 -14
- data/lib/rom/sql/association/many_to_many.rb +17 -10
- data/lib/rom/sql/association/many_to_one.rb +29 -13
- data/lib/rom/sql/association/name.rb +12 -4
- data/lib/rom/sql/association/one_to_many.rb +21 -10
- data/lib/rom/sql/commands/create.rb +0 -1
- data/lib/rom/sql/commands/update.rb +1 -49
- data/lib/rom/sql/dsl.rb +29 -0
- data/lib/rom/sql/expression.rb +26 -0
- data/lib/rom/sql/function.rb +23 -0
- data/lib/rom/sql/gateway.rb +24 -9
- data/lib/rom/sql/migration.rb +6 -7
- data/lib/rom/sql/migration/migrator.rb +7 -8
- data/lib/rom/sql/order_dsl.rb +20 -0
- data/lib/rom/sql/plugin/associates.rb +58 -45
- data/lib/rom/sql/plugin/pagination.rb +8 -11
- data/lib/rom/sql/plugins.rb +0 -2
- data/lib/rom/sql/projection_dsl.rb +41 -0
- data/lib/rom/sql/qualified_attribute.rb +2 -2
- data/lib/rom/sql/relation.rb +35 -67
- data/lib/rom/sql/relation/reading.rb +77 -25
- data/lib/rom/sql/restriction_dsl.rb +24 -0
- data/lib/rom/sql/schema.rb +73 -7
- data/lib/rom/sql/schema/associations_dsl.rb +4 -3
- data/lib/rom/sql/schema/dsl.rb +5 -2
- data/lib/rom/sql/schema/inferrer.rb +21 -11
- data/lib/rom/sql/transaction.rb +19 -0
- data/lib/rom/sql/type.rb +76 -0
- data/lib/rom/sql/version.rb +1 -1
- data/rom-sql.gemspec +3 -4
- data/spec/extensions/postgres/inferrer_spec.rb +19 -9
- data/spec/integration/association/many_to_many/custom_fks_spec.rb +73 -0
- data/spec/integration/association/many_to_many/from_view_spec.rb +81 -0
- data/spec/integration/association/many_to_many_spec.rb +2 -2
- data/spec/integration/association/many_to_one/custom_fks_spec.rb +59 -0
- data/spec/integration/association/many_to_one/from_view_spec.rb +74 -0
- data/spec/integration/association/many_to_one/self_ref_spec.rb +51 -0
- data/spec/integration/association/many_to_one_spec.rb +4 -2
- data/spec/integration/association/one_to_many/custom_fks_spec.rb +48 -0
- data/spec/integration/association/one_to_many/from_view_spec.rb +57 -0
- data/spec/integration/association/one_to_many/self_ref_spec.rb +52 -0
- data/spec/integration/association/one_to_many_spec.rb +1 -1
- data/spec/integration/association/one_to_one_spec.rb +1 -1
- data/spec/integration/association/one_to_one_through_spec.rb +2 -2
- data/spec/integration/commands/create_spec.rb +11 -27
- data/spec/integration/commands/update_spec.rb +54 -109
- data/spec/integration/gateway_spec.rb +31 -17
- data/spec/integration/plugins/associates_spec.rb +27 -0
- data/spec/integration/plugins/auto_wrap_spec.rb +8 -8
- data/spec/integration/schema/call_spec.rb +24 -0
- data/spec/integration/schema/prefix_spec.rb +18 -0
- data/spec/integration/schema/qualified_spec.rb +18 -0
- data/spec/integration/schema/rename_spec.rb +23 -0
- data/spec/integration/schema/view_spec.rb +29 -0
- data/spec/integration/schema_inference_spec.rb +31 -14
- data/spec/spec_helper.rb +2 -2
- data/spec/support/helpers.rb +7 -0
- data/spec/unit/gateway_spec.rb +5 -4
- data/spec/unit/projection_dsl_spec.rb +54 -0
- data/spec/unit/relation/dataset_spec.rb +3 -3
- data/spec/unit/relation/distinct_spec.rb +8 -7
- data/spec/unit/relation/exclude_spec.rb +2 -4
- data/spec/unit/relation/having_spec.rb +6 -4
- data/spec/unit/relation/inner_join_spec.rb +47 -2
- data/spec/unit/relation/invert_spec.rb +2 -3
- data/spec/unit/relation/left_join_spec.rb +44 -3
- data/spec/unit/relation/order_spec.rb +40 -0
- data/spec/unit/relation/prefix_spec.rb +2 -0
- data/spec/unit/relation/project_spec.rb +3 -1
- data/spec/unit/relation/qualified_columns_spec.rb +2 -0
- data/spec/unit/relation/rename_spec.rb +2 -0
- data/spec/unit/relation/right_join_spec.rb +59 -0
- data/spec/unit/relation/select_append_spec.rb +21 -0
- data/spec/unit/relation/select_spec.rb +41 -0
- data/spec/unit/relation/where_spec.rb +28 -0
- data/spec/unit/restriction_dsl_spec.rb +34 -0
- metadata +62 -40
- data/lib/rom/plugins/relation/sql/base_view.rb +0 -31
- data/lib/rom/sql/header.rb +0 -61
- data/lib/rom/sql/plugin/assoc_macros.rb +0 -133
- data/lib/rom/sql/plugin/assoc_macros/class_interface.rb +0 -128
- data/spec/integration/read_spec.rb +0 -111
- data/spec/unit/association_errors_spec.rb +0 -19
- data/spec/unit/plugin/assoc_macros/combined_associations_spec.rb +0 -73
- data/spec/unit/plugin/assoc_macros/many_to_many_spec.rb +0 -53
- data/spec/unit/plugin/assoc_macros/many_to_one_spec.rb +0 -61
- data/spec/unit/plugin/assoc_macros/one_to_many_spec.rb +0 -78
- data/spec/unit/plugin/base_view_spec.rb +0 -18
data/lib/rom/sql/schema.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'rom/schema'
|
2
|
-
require 'rom/
|
2
|
+
require 'rom/sql/order_dsl'
|
3
|
+
require 'rom/sql/projection_dsl'
|
4
|
+
require 'rom/sql/restriction_dsl'
|
3
5
|
|
4
6
|
module ROM
|
5
7
|
module SQL
|
@@ -13,19 +15,83 @@ module ROM
|
|
13
15
|
# @return [Array<Symbol>] A list of all pk names
|
14
16
|
attr_reader :primary_key_names
|
15
17
|
|
18
|
+
# @api private
|
16
19
|
def initialize(*)
|
17
20
|
super
|
18
|
-
|
19
|
-
|
21
|
+
initialize_primary_key_names
|
22
|
+
end
|
23
|
+
|
24
|
+
# @api public
|
25
|
+
def restriction(&block)
|
26
|
+
RestrictionDSL.new(self).call(&block)
|
27
|
+
end
|
28
|
+
|
29
|
+
# @api public
|
30
|
+
def order(&block)
|
31
|
+
OrderDSL.new(self).call(&block)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Return a new schema with attributes marked as qualified
|
35
|
+
#
|
36
|
+
# @return [Schema]
|
37
|
+
#
|
38
|
+
# @api public
|
39
|
+
def qualified
|
40
|
+
new(map(&:qualified))
|
41
|
+
end
|
42
|
+
|
43
|
+
# @api public
|
44
|
+
def project(*names, &block)
|
45
|
+
if block
|
46
|
+
super(*(names + ProjectionDSL.new(self).(&block)))
|
47
|
+
else
|
48
|
+
super
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# @api private
|
53
|
+
def project_pk
|
54
|
+
project(*primary_key_names)
|
55
|
+
end
|
56
|
+
|
57
|
+
# @api private
|
58
|
+
def project_fk(mapping)
|
59
|
+
new(rename(mapping).map(&:foreign_key))
|
60
|
+
end
|
61
|
+
|
62
|
+
# @api public
|
63
|
+
def join(other)
|
64
|
+
merge(other.joined)
|
65
|
+
end
|
66
|
+
|
67
|
+
# @api public
|
68
|
+
def joined
|
69
|
+
new(map(&:joined))
|
70
|
+
end
|
71
|
+
|
72
|
+
# Create a new relation based on the schema definition
|
73
|
+
#
|
74
|
+
# @param [Relation] relation The source relation
|
75
|
+
#
|
76
|
+
# @return [Relation]
|
77
|
+
#
|
78
|
+
# @api public
|
79
|
+
def call(relation)
|
80
|
+
relation.new(relation.dataset.select(*self), schema: self)
|
20
81
|
end
|
21
82
|
|
22
83
|
# @api private
|
23
84
|
def finalize!(*)
|
24
85
|
super do
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
86
|
+
initialize_primary_key_names
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# @api private
|
91
|
+
def initialize_primary_key_names
|
92
|
+
if primary_key.size > 0
|
93
|
+
@primary_key_name = primary_key[0].meta[:name]
|
94
|
+
@primary_key_names = primary_key.map { |type| type.meta[:name] }
|
29
95
|
end
|
30
96
|
end
|
31
97
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'dry/core/inflector'
|
1
2
|
require 'rom/sql/association'
|
2
3
|
|
3
4
|
module ROM
|
@@ -42,11 +43,11 @@ module ROM
|
|
42
43
|
end
|
43
44
|
|
44
45
|
def belongs_to(name, options = {})
|
45
|
-
many_to_one(dataset_name(name),
|
46
|
+
many_to_one(dataset_name(name), {as: name}.merge(options))
|
46
47
|
end
|
47
48
|
|
48
49
|
def has_one(name, options = {})
|
49
|
-
one_to_one(dataset_name(name),
|
50
|
+
one_to_one(dataset_name(name), {as: name}.merge(options))
|
50
51
|
end
|
51
52
|
|
52
53
|
def call
|
@@ -60,7 +61,7 @@ module ROM
|
|
60
61
|
end
|
61
62
|
|
62
63
|
def dataset_name(name)
|
63
|
-
Inflector.pluralize(name).to_sym
|
64
|
+
::Dry::Core::Inflector.pluralize(name).to_sym
|
64
65
|
end
|
65
66
|
end
|
66
67
|
end
|
data/lib/rom/sql/schema/dsl.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'rom/sql/type'
|
1
2
|
require 'rom/sql/schema/inferrer'
|
2
3
|
require 'rom/sql/schema/associations_dsl'
|
3
4
|
|
@@ -8,11 +9,13 @@ module ROM
|
|
8
9
|
attr_reader :associations_dsl
|
9
10
|
|
10
11
|
def associations(&block)
|
11
|
-
@associations_dsl = AssociationsDSL.new(
|
12
|
+
@associations_dsl = AssociationsDSL.new(relation, &block)
|
12
13
|
end
|
13
14
|
|
14
15
|
def call
|
15
|
-
SQL::Schema.
|
16
|
+
SQL::Schema.define(
|
17
|
+
relation, opts.merge(attributes: attributes.values, type_class: SQL::Type)
|
18
|
+
)
|
16
19
|
end
|
17
20
|
|
18
21
|
def opts
|
@@ -1,9 +1,11 @@
|
|
1
|
+
require 'dry/core/class_attributes'
|
2
|
+
|
1
3
|
module ROM
|
2
4
|
module SQL
|
3
5
|
class Schema < ROM::Schema
|
4
6
|
# @api private
|
5
7
|
class Inferrer
|
6
|
-
extend
|
8
|
+
extend Dry::Core::ClassAttributes
|
7
9
|
|
8
10
|
defines :ruby_type_mapping, :numeric_pk_type, :db_type, :db_registry
|
9
11
|
|
@@ -37,14 +39,21 @@ module ROM
|
|
37
39
|
end
|
38
40
|
|
39
41
|
# @api private
|
40
|
-
def call(
|
42
|
+
def call(source, gateway)
|
43
|
+
dataset = source.dataset
|
44
|
+
|
41
45
|
columns = gateway.connection.schema(dataset)
|
42
46
|
fks = fks_for(gateway, dataset)
|
43
47
|
|
44
|
-
columns.
|
48
|
+
inferred = columns.map do |(name, definition)|
|
45
49
|
type = build_type(definition.merge(foreign_key: fks[name]))
|
46
|
-
|
47
|
-
|
50
|
+
|
51
|
+
if type
|
52
|
+
type.meta(name: name, source: source)
|
53
|
+
end
|
54
|
+
end.compact
|
55
|
+
|
56
|
+
[inferred, columns.map(&:first) - inferred.map { |attr| attr.meta[:name] }]
|
48
57
|
end
|
49
58
|
|
50
59
|
private
|
@@ -54,9 +63,12 @@ module ROM
|
|
54
63
|
map_pk_type(type, db_type)
|
55
64
|
else
|
56
65
|
mapped_type = map_type(type, db_type, rest)
|
57
|
-
|
58
|
-
|
59
|
-
|
66
|
+
|
67
|
+
if mapped_type
|
68
|
+
mapped_type = mapped_type.optional if allow_null
|
69
|
+
mapped_type = mapped_type.meta(foreign_key: true, target: foreign_key) if foreign_key
|
70
|
+
mapped_type
|
71
|
+
end
|
60
72
|
end
|
61
73
|
end
|
62
74
|
|
@@ -65,9 +77,7 @@ module ROM
|
|
65
77
|
end
|
66
78
|
|
67
79
|
def map_type(ruby_type, db_type, **_kw)
|
68
|
-
self.class.ruby_type_mapping
|
69
|
-
raise UnknownDBTypeError, "Cannot find corresponding type for #{ruby_type || db_type}"
|
70
|
-
}
|
80
|
+
self.class.ruby_type_mapping[ruby_type]
|
71
81
|
end
|
72
82
|
|
73
83
|
# @api private
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ROM
|
2
|
+
module SQL
|
3
|
+
# @api private
|
4
|
+
class Transaction < ::ROM::Transaction
|
5
|
+
attr_reader :connection
|
6
|
+
private :connection
|
7
|
+
|
8
|
+
def initialize(connection)
|
9
|
+
@connection = connection
|
10
|
+
end
|
11
|
+
|
12
|
+
def run(opts = EMPTY_HASH)
|
13
|
+
connection.transaction(opts) { yield(self) }
|
14
|
+
rescue ::ROM::Transaction::Rollback
|
15
|
+
# noop
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/rom/sql/type.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'rom/schema/type'
|
2
|
+
|
3
|
+
module ROM
|
4
|
+
module SQL
|
5
|
+
class Type < ROM::Schema::Type
|
6
|
+
# Return a new type marked as a FK
|
7
|
+
#
|
8
|
+
# @return [SQL::Type]
|
9
|
+
#
|
10
|
+
# @api public
|
11
|
+
def foreign_key
|
12
|
+
meta(foreign_key: true)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Return a new type marked as qualified
|
16
|
+
#
|
17
|
+
# @return [SQL::Type]
|
18
|
+
#
|
19
|
+
# @api public
|
20
|
+
def qualified
|
21
|
+
meta(qualified: true)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Return a new type marked as joined
|
25
|
+
#
|
26
|
+
# @return [SQL::Type]
|
27
|
+
#
|
28
|
+
# @api public
|
29
|
+
def joined
|
30
|
+
meta(joined: true)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Return if an attribute was used in a join
|
34
|
+
#
|
35
|
+
# @return [Boolean]
|
36
|
+
#
|
37
|
+
# @api public
|
38
|
+
def joined?
|
39
|
+
meta[:joined].equal?(true)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Return if an attribute type is qualified
|
43
|
+
#
|
44
|
+
# @return [Boolean]
|
45
|
+
#
|
46
|
+
# @api public
|
47
|
+
def qualified?
|
48
|
+
meta[:qualified].equal?(true)
|
49
|
+
end
|
50
|
+
|
51
|
+
# @api public
|
52
|
+
def to_sym
|
53
|
+
@_to_sym ||=
|
54
|
+
if qualified? && aliased?
|
55
|
+
:"#{source.dataset}__#{name}___#{meta[:alias]}"
|
56
|
+
elsif qualified?
|
57
|
+
:"#{source.dataset}__#{name}"
|
58
|
+
elsif aliased?
|
59
|
+
:"#{name}___#{meta[:alias]}"
|
60
|
+
else
|
61
|
+
name
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# @api private
|
66
|
+
def sql_literal(ds)
|
67
|
+
sql_expr.sql_literal(ds)
|
68
|
+
end
|
69
|
+
|
70
|
+
# @api private
|
71
|
+
def sql_expr
|
72
|
+
Sequel.expr(to_sym)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/lib/rom/sql/version.rb
CHANGED
data/rom-sql.gemspec
CHANGED
@@ -18,12 +18,11 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.add_runtime_dependency 'sequel', '~> 4.
|
21
|
+
spec.add_runtime_dependency 'sequel', '~> 4.42'
|
22
22
|
spec.add_runtime_dependency 'dry-equalizer', '~> 0.2'
|
23
23
|
spec.add_runtime_dependency 'dry-types', '~> 0.9'
|
24
|
-
spec.add_runtime_dependency 'dry-core', '~> 0.2'
|
25
|
-
spec.add_runtime_dependency 'rom', '~>
|
26
|
-
spec.add_runtime_dependency 'rom-support', '~> 2.0'
|
24
|
+
spec.add_runtime_dependency 'dry-core', '~> 0.2', '>= 0.2.3'
|
25
|
+
spec.add_runtime_dependency 'rom', '~> 3.0.0.beta'
|
27
26
|
|
28
27
|
spec.add_development_dependency 'bundler'
|
29
28
|
spec.add_development_dependency 'rake', '~> 10.0'
|
@@ -18,10 +18,15 @@ RSpec.describe 'ROM::SQL::Schema::PostgresInferrer', :postgres do
|
|
18
18
|
Decimal :money, null: false
|
19
19
|
column :tags, "text[]"
|
20
20
|
column :tag_ids, "bigint[]"
|
21
|
+
column :ip, "inet"
|
21
22
|
rainbow :color
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
26
|
+
after do
|
27
|
+
conn.drop_table?(:test_inferrence)
|
28
|
+
end
|
29
|
+
|
25
30
|
let(:dataset) { :test_inferrence }
|
26
31
|
|
27
32
|
let(:schema) { container.relations[dataset].schema }
|
@@ -30,19 +35,24 @@ RSpec.describe 'ROM::SQL::Schema::PostgresInferrer', :postgres do
|
|
30
35
|
before do
|
31
36
|
dataset = self.dataset
|
32
37
|
conf.relation(dataset) do
|
33
|
-
schema(dataset, infer: true)
|
38
|
+
schema(dataset, infer: true) do
|
39
|
+
attribute :ip, ROM::SQL::Types::String
|
40
|
+
end
|
34
41
|
end
|
35
42
|
end
|
36
43
|
|
37
44
|
it 'can infer attributes for dataset' do
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
45
|
+
source = container.relations[:test_inferrence].name
|
46
|
+
|
47
|
+
expect(schema.to_h).to eql(
|
48
|
+
id: ROM::SQL::Types::PG::UUID.meta(name: :id, source: source, primary_key: true),
|
49
|
+
json_data: ROM::SQL::Types::PG::JSON.optional.meta(name: :json_data, source: source),
|
50
|
+
jsonb_data: ROM::SQL::Types::PG::JSONB.optional.meta(name: :jsonb_data, source: source),
|
51
|
+
money: ROM::SQL::Types::Decimal.meta(name: :money, source: source),
|
52
|
+
tags: ROM::SQL::Types::PG::Array('text').optional.meta(name: :tags, source: source),
|
53
|
+
tag_ids: ROM::SQL::Types::PG::Array('biging').optional.meta(name: :tag_ids, source: source),
|
54
|
+
color: ROM::SQL::Types::String.enum(*colors).optional.meta(name: :color, source: source),
|
55
|
+
ip: ROM::SQL::Types::String.meta(name: :ip, source: source)
|
46
56
|
)
|
47
57
|
end
|
48
58
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
RSpec.describe ROM::SQL::Association::ManyToMany, '#call' do
|
2
|
+
subject(:assoc) do
|
3
|
+
relations[:users].associations[:puzzles]
|
4
|
+
end
|
5
|
+
|
6
|
+
include_context 'database setup'
|
7
|
+
|
8
|
+
with_adapters do
|
9
|
+
before do
|
10
|
+
conn.create_table(:puzzles) do
|
11
|
+
primary_key :id
|
12
|
+
column :text, String, null: false
|
13
|
+
end
|
14
|
+
|
15
|
+
conn.create_table(:puzzle_solvers) do
|
16
|
+
foreign_key :solver_id, :users, null: false
|
17
|
+
foreign_key :puzzle_id, :puzzles, null: false
|
18
|
+
primary_key [:solver_id, :puzzle_id]
|
19
|
+
end
|
20
|
+
|
21
|
+
conf.relation(:puzzle_solvers) do
|
22
|
+
schema(infer: true) do
|
23
|
+
associations do
|
24
|
+
belongs_to :user, foreign_key: :solver_id
|
25
|
+
belongs_to :puzzle
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
conf.relation(:users) do
|
31
|
+
schema(infer: true) do
|
32
|
+
associations do
|
33
|
+
has_many :puzzle_solvers
|
34
|
+
has_many :puzzles, through: :puzzle_solvers, foreign_key: :solver_id
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
joe_id = relations[:users].insert(name: 'Joe')
|
40
|
+
jane_id = relations[:users].insert(name: 'Jane')
|
41
|
+
|
42
|
+
p1_id = relations[:puzzles].insert(text: 'P1')
|
43
|
+
p2_id = relations[:puzzles].insert(text: 'P2')
|
44
|
+
p3_id = relations[:puzzles].insert(text: 'P3')
|
45
|
+
|
46
|
+
relations[:puzzle_solvers].insert(solver_id: joe_id, puzzle_id: p2_id)
|
47
|
+
relations[:puzzle_solvers].insert(solver_id: jane_id, puzzle_id: p2_id)
|
48
|
+
|
49
|
+
relations[:puzzle_solvers].insert(solver_id: joe_id, puzzle_id: p1_id)
|
50
|
+
relations[:puzzle_solvers].insert(solver_id: jane_id, puzzle_id: p3_id)
|
51
|
+
end
|
52
|
+
|
53
|
+
after do
|
54
|
+
conn.drop_table?(:puzzle_solvers)
|
55
|
+
conn.drop_table?(:puzzles)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'prepares joined relations using custom FK' do
|
59
|
+
relation = assoc.call(relations).order(:puzzles__text)
|
60
|
+
|
61
|
+
expect(relation.schema.map(&:to_sym)).
|
62
|
+
to eql(%i[puzzles__id puzzles__text puzzle_solvers__solver_id])
|
63
|
+
|
64
|
+
expect(relation.to_a).
|
65
|
+
to eql([
|
66
|
+
{ id: 1, solver_id: 1, text: 'P1' },
|
67
|
+
{ id: 2, solver_id: 1, text: 'P2' },
|
68
|
+
{ id: 2, solver_id: 2, text: 'P2' },
|
69
|
+
{ id: 3, solver_id: 2, text: 'P3' }
|
70
|
+
])
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|