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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 11ef8c53c46264b6203d44eaad523cda0815845e
|
4
|
+
data.tar.gz: c2514bbd7868d4591cd2a714e158bfafa2a36fbf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1d21a1a74c17f0489431b31d648e58cb0fce934808811111f6e01fc11f4307096884fdc7c8246bc302ce41cd5ea992be9e12a48123841797d8dacab5bc2c88df
|
7
|
+
data.tar.gz: 5dc78196284dfeb55ac969afcb79510db21fa31bf5238f26209d8bdbe1ed919a929130313dd9600c07842b110facc88487a7c4e137642293f3f885075b210172
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,35 @@
|
|
1
|
+
## v1.0.0 to-be-released
|
2
|
+
|
3
|
+
This release is based on rom core 3.0.0 with its improved Schema API, which is extended with SQL-specific features.
|
4
|
+
|
5
|
+
Please refer to [the upgrading guide](https://github.com/rom-rb/rom-sql/wiki/Upgrading-from-0.9.x-to-1.0.0) if you're moving from 0.9.x to 1.0.0.
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
* [BREAKING] All relations have schemas (inferred by default, but still possible to override and/or extend) (solnic)
|
10
|
+
* [BREAKING] Schemas are used when defining relation views (solnic)
|
11
|
+
* [BREAKING] Default dataset is set up based on schema (solnic)
|
12
|
+
* Extended query API with support for schema attributes (solnic)
|
13
|
+
* Schemas can project relations automatically (solnic)
|
14
|
+
* New `Schema#qualified` (solnic)
|
15
|
+
* Schema attribute types are now SQL-specific and compatible with query DSL (ie you can pass relation attributes to `select` and they will be automatically converted to valid SQL expressions) (solnic)
|
16
|
+
* Associations support setting custom `view` that will be used to extend association relation (solnic)
|
17
|
+
* Associations support setting custom `foreign_key` names (solnic)
|
18
|
+
* Support for self-referencing associations (ie categories have_many child categories) (solnic)
|
19
|
+
|
20
|
+
### Changed
|
21
|
+
|
22
|
+
* [BREAKING] `Relation#header` has been removed in favor of schemas (solnic)
|
23
|
+
* [BREAKING] `Relation#base` has been removed as now a vanilla relation *is a base relation view* (solnic)
|
24
|
+
* [BREAKING] Deprecated `Commands::Update#change` has been removed (solnic)
|
25
|
+
* [BREAKING] Deprecated `Commands.validator` has been removed (solnic)
|
26
|
+
* [BREAKING] `assoc_macros` plugin has been removed, please use associations from now (solnic)
|
27
|
+
* [internal] Associations use schemas for relation projections (solnic)
|
28
|
+
* [internal] `select`, `select_append`, `project`, `inner_join` and `left_join` use schemas internally (solnic)
|
29
|
+
* [internal] Deprecation and constants are now based on dry-core (flash-gordon)
|
30
|
+
|
31
|
+
[Compare v0.9.1...v1.0.0](https://github.com/rom-rb/rom-sql/compare/v0.9.1...v1.0.0)
|
32
|
+
|
1
33
|
## v0.9.1 2016-12-23
|
2
34
|
|
3
35
|
### Added
|
data/Gemfile
CHANGED
@@ -2,10 +2,13 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
gemspec
|
4
4
|
|
5
|
+
gem 'rom', git: 'https://github.com/rom-rb/rom.git', branch: 'master'
|
6
|
+
gem 'rom-mapper', git: 'https://github.com/rom-rb/rom-mapper.git', branch: 'master'
|
7
|
+
|
5
8
|
group :test do
|
6
9
|
gem 'byebug', platforms: :mri
|
7
10
|
gem 'dry-struct'
|
8
|
-
gem 'activesupport', '~>
|
11
|
+
gem 'activesupport', '~> 5.0'
|
9
12
|
gem 'rspec', '~> 3.1'
|
10
13
|
gem 'codeclimate-test-reporter', require: false
|
11
14
|
gem 'simplecov', require: false
|
@@ -31,9 +31,7 @@ module ROM
|
|
31
31
|
other = __registry__[name]
|
32
32
|
other_dataset = other.name.dataset
|
33
33
|
|
34
|
-
inner_join(other_dataset, keys)
|
35
|
-
.select(*qualified.header.columns)
|
36
|
-
.select_append(*other.prefix(other_dataset).qualified.header)
|
34
|
+
schema.merge(other.schema.wrap).qualified.(inner_join(other_dataset, keys))
|
37
35
|
end
|
38
36
|
end
|
39
37
|
end
|
data/lib/rom/sql/association.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
-
require '
|
1
|
+
require 'dry/core/constants'
|
2
|
+
require 'dry/core/class_attributes'
|
3
|
+
|
4
|
+
require 'rom/types'
|
5
|
+
require 'rom/initializer'
|
2
6
|
require 'rom/sql/qualified_attribute'
|
3
7
|
require 'rom/sql/association/name'
|
4
8
|
|
@@ -8,39 +12,50 @@ module ROM
|
|
8
12
|
#
|
9
13
|
# @api public
|
10
14
|
class Association
|
15
|
+
include Dry::Core::Constants
|
11
16
|
include Dry::Equalizer(:source, :target, :result)
|
12
|
-
|
13
|
-
extend
|
17
|
+
extend Initializer
|
18
|
+
extend Dry::Core::ClassAttributes
|
14
19
|
|
15
20
|
defines :result
|
16
21
|
|
17
22
|
# @!attribute [r] source
|
18
23
|
# @return [ROM::Relation::Name] the source relation name
|
19
|
-
|
24
|
+
param :source
|
20
25
|
|
21
26
|
# @!attribute [r] target
|
22
27
|
# @return [ROM::Relation::Name] the target relation name
|
23
|
-
|
28
|
+
param :target
|
24
29
|
|
25
30
|
# @!attribute [r] relation
|
26
31
|
# @return [Symbol] an optional relation identifier for the target
|
27
|
-
option :relation,
|
32
|
+
option :relation, Types::Strict::Symbol, reader: true, optional: true
|
28
33
|
|
29
34
|
# @!attribute [r] result
|
30
35
|
# @return [Symbol] either :one or :many
|
31
|
-
option :result,
|
36
|
+
option :result, Types::Strict::Symbol, reader: true, default: -> assoc { assoc.class.result }
|
32
37
|
|
33
38
|
# @!attribute [r] as
|
34
39
|
# @return [Symbol] an optional association alias name
|
35
|
-
option :as,
|
40
|
+
option :as, Types::Strict::Symbol, reader: true, optional: true, default: -> assoc { assoc.target.to_sym }
|
41
|
+
|
42
|
+
# @!attribute [r] foreign_key
|
43
|
+
# @return [Symbol] an optional association alias name
|
44
|
+
option :foreign_key, Types::Strict::Symbol, optional: true, reader: true, default: proc { nil }
|
45
|
+
|
46
|
+
# @!attribute [r] view
|
47
|
+
# @return [Symbol] An optional view that should be used to extend assoc relation
|
48
|
+
option :view, reader: true, optional: true, default: proc { nil }
|
36
49
|
|
37
50
|
alias_method :name, :as
|
38
51
|
|
39
|
-
# @api
|
40
|
-
def
|
41
|
-
|
42
|
-
|
43
|
-
|
52
|
+
# @api public
|
53
|
+
def self.new(source, target, options = EMPTY_HASH)
|
54
|
+
super(
|
55
|
+
Name[source],
|
56
|
+
Name[options[:relation] || target, target, options[:as] || target],
|
57
|
+
options
|
58
|
+
)
|
44
59
|
end
|
45
60
|
|
46
61
|
# Returns a qualified attribute name for a given dataset
|
@@ -55,7 +70,7 @@ module ROM
|
|
55
70
|
#
|
56
71
|
# @api public
|
57
72
|
def qualify(name, attribute)
|
58
|
-
QualifiedAttribute[name.
|
73
|
+
QualifiedAttribute[name.to_sym, attribute]
|
59
74
|
end
|
60
75
|
|
61
76
|
protected
|
@@ -64,6 +79,10 @@ module ROM
|
|
64
79
|
def join_key_map(relations)
|
65
80
|
join_keys(relations).to_a.flatten.map(&:to_sym)
|
66
81
|
end
|
82
|
+
|
83
|
+
def self_ref?
|
84
|
+
source.dataset == target.dataset
|
85
|
+
end
|
67
86
|
end
|
68
87
|
end
|
69
88
|
end
|
@@ -1,12 +1,12 @@
|
|
1
|
+
require 'rom/types'
|
2
|
+
|
1
3
|
module ROM
|
2
4
|
module SQL
|
3
5
|
class Association
|
4
6
|
class ManyToMany < Association
|
5
|
-
attr_reader :through
|
6
|
-
|
7
7
|
result :many
|
8
8
|
|
9
|
-
option :through,
|
9
|
+
option :through, type: Types::Strict::Symbol.optional
|
10
10
|
|
11
11
|
# @api private
|
12
12
|
def initialize(*)
|
@@ -24,17 +24,24 @@ module ROM
|
|
24
24
|
left = assocs[target].call(relations)
|
25
25
|
right = relations[target.relation]
|
26
26
|
|
27
|
-
left_fk = join_rel.foreign_key(source.relation)
|
27
|
+
left_fk = foreign_key || join_rel.foreign_key(source.relation)
|
28
28
|
|
29
|
-
|
30
|
-
|
29
|
+
schema =
|
30
|
+
if left.schema.key?(left_fk)
|
31
|
+
left.schema.project(*(right.schema.map(&:name) + [left_fk]))
|
32
|
+
else
|
33
|
+
right.schema.merge(join_rel.schema.project(left_fk))
|
34
|
+
end.qualified
|
31
35
|
|
32
36
|
relation = left
|
33
37
|
.inner_join(source, join_keys(relations))
|
34
|
-
.
|
35
|
-
.order(*right.header.project(*right.primary_key).qualified)
|
38
|
+
.order(*right.schema.project_pk.qualified)
|
36
39
|
|
37
|
-
|
40
|
+
if view
|
41
|
+
schema.(relation.public_send(view))
|
42
|
+
else
|
43
|
+
schema.(relation)
|
44
|
+
end
|
38
45
|
end
|
39
46
|
|
40
47
|
# @api public
|
@@ -68,7 +75,7 @@ module ROM
|
|
68
75
|
# @api private
|
69
76
|
def with_keys(relations, &block)
|
70
77
|
source_key = relations[source.relation].primary_key
|
71
|
-
target_key = relations[through.relation].foreign_key(source.relation)
|
78
|
+
target_key = foreign_key || relations[through.relation].foreign_key(source.relation)
|
72
79
|
return [source_key, target_key] unless block
|
73
80
|
yield(source_key, target_key)
|
74
81
|
end
|
@@ -9,22 +9,28 @@ module ROM
|
|
9
9
|
left = relations[target.relation]
|
10
10
|
right = relations[source.relation]
|
11
11
|
|
12
|
-
|
13
|
-
right_fk =
|
12
|
+
left_pk = left.primary_key
|
13
|
+
right_fk = left.foreign_key(source.relation)
|
14
14
|
|
15
|
-
|
15
|
+
left_schema = left.schema
|
16
|
+
right_schema = right.schema.project_pk
|
16
17
|
|
17
|
-
|
18
|
-
.
|
19
|
-
|
20
|
-
|
18
|
+
schema =
|
19
|
+
if left.schema.key?(right_fk)
|
20
|
+
left_schema
|
21
|
+
else
|
22
|
+
left_schema.merge(right_schema.project_fk(left_pk => right_fk))
|
23
|
+
end.qualified
|
21
24
|
|
22
25
|
relation = left
|
23
|
-
.inner_join(
|
24
|
-
.
|
25
|
-
.order(*right.header.project(*right.primary_key).qualified)
|
26
|
+
.inner_join(source_table, join_keys(relations))
|
27
|
+
.order(*right_schema.qualified)
|
26
28
|
|
27
|
-
|
29
|
+
if view
|
30
|
+
schema.(relation.public_send(view))
|
31
|
+
else
|
32
|
+
schema.(relation)
|
33
|
+
end
|
28
34
|
end
|
29
35
|
|
30
36
|
# @api public
|
@@ -35,7 +41,7 @@ module ROM
|
|
35
41
|
# @api public
|
36
42
|
def join_keys(relations)
|
37
43
|
with_keys(relations) { |source_key, target_key|
|
38
|
-
{ qualify(
|
44
|
+
{ qualify(source_alias, source_key) => qualify(target, target_key) }
|
39
45
|
}
|
40
46
|
end
|
41
47
|
|
@@ -47,9 +53,19 @@ module ROM
|
|
47
53
|
|
48
54
|
protected
|
49
55
|
|
56
|
+
# @api private
|
57
|
+
def source_table
|
58
|
+
self_ref? ? :"#{source.dataset}___#{source_alias}" : source
|
59
|
+
end
|
60
|
+
|
61
|
+
# @api private
|
62
|
+
def source_alias
|
63
|
+
self_ref? ? :"#{source.dataset.to_s[0]}_0" : source
|
64
|
+
end
|
65
|
+
|
50
66
|
# @api private
|
51
67
|
def with_keys(relations, &block)
|
52
|
-
source_key = relations[source.relation].foreign_key(target.relation)
|
68
|
+
source_key = foreign_key || relations[source.relation].foreign_key(target.relation)
|
53
69
|
target_key = relations[target.relation].primary_key
|
54
70
|
return [source_key, target_key] unless block
|
55
71
|
yield(source_key, target_key)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'dry/equalizer'
|
2
2
|
require 'rom/relation/name'
|
3
|
-
require '
|
3
|
+
require 'dry/core/cache'
|
4
4
|
|
5
5
|
module ROM
|
6
6
|
module SQL
|
@@ -8,7 +8,7 @@ module ROM
|
|
8
8
|
class Name
|
9
9
|
include Dry::Equalizer.new(:relation_name, :key)
|
10
10
|
|
11
|
-
extend Cache
|
11
|
+
extend Dry::Core::Cache
|
12
12
|
|
13
13
|
attr_reader :relation_name
|
14
14
|
|
@@ -61,8 +61,16 @@ module ROM
|
|
61
61
|
relation_name.relation
|
62
62
|
end
|
63
63
|
|
64
|
-
def
|
65
|
-
|
64
|
+
def as(aliaz)
|
65
|
+
Name[relation_name.relation, relation_name.dataset, aliaz]
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_sym
|
69
|
+
dataset
|
70
|
+
end
|
71
|
+
|
72
|
+
def sql_literal(ds)
|
73
|
+
Sequel.expr(aliased? ? :"#{dataset}___#{key}" : dataset).sql_literal(ds)
|
66
74
|
end
|
67
75
|
end
|
68
76
|
end
|
@@ -6,16 +6,17 @@ module ROM
|
|
6
6
|
|
7
7
|
# @api public
|
8
8
|
def call(relations)
|
9
|
-
|
10
|
-
|
11
|
-
columns = right.header.qualified.to_a
|
9
|
+
right = relations[target.relation]
|
10
|
+
schema = right.schema.qualified
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
.order(*right.header.project(*right.primary_key).qualified)
|
12
|
+
relation = right
|
13
|
+
.inner_join(source_table, join_keys(relations))
|
14
|
+
.order(*right.schema.project_pk.qualified)
|
17
15
|
|
18
|
-
|
16
|
+
if view
|
17
|
+
schema.(relation.public_send(view))
|
18
|
+
else
|
19
|
+
schema.(relation)
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
@@ -27,7 +28,7 @@ module ROM
|
|
27
28
|
# @api public
|
28
29
|
def join_keys(relations)
|
29
30
|
with_keys(relations) { |source_key, target_key|
|
30
|
-
{ qualify(
|
31
|
+
{ qualify(source_alias, source_key) => qualify(target, target_key) }
|
31
32
|
}
|
32
33
|
end
|
33
34
|
|
@@ -39,10 +40,20 @@ module ROM
|
|
39
40
|
|
40
41
|
protected
|
41
42
|
|
43
|
+
# @api private
|
44
|
+
def source_table
|
45
|
+
self_ref? ? :"#{source.dataset}___#{source_alias}" : source
|
46
|
+
end
|
47
|
+
|
48
|
+
# @api private
|
49
|
+
def source_alias
|
50
|
+
self_ref? ? :"#{source.dataset.to_s[0]}_0" : source
|
51
|
+
end
|
52
|
+
|
42
53
|
# @api private
|
43
54
|
def with_keys(relations, &block)
|
44
55
|
source_key = relations[source.relation].primary_key
|
45
|
-
target_key = relations[target.relation].foreign_key(source.relation)
|
56
|
+
target_key = foreign_key || relations[target.relation].foreign_key(source.relation)
|
46
57
|
return [source_key, target_key] unless block
|
47
58
|
yield(source_key, target_key)
|
48
59
|
end
|
@@ -1,6 +1,3 @@
|
|
1
|
-
require 'rom/support/deprecations'
|
2
|
-
require 'rom/support/constants'
|
3
|
-
|
4
1
|
require 'rom/sql/commands/error_wrapper'
|
5
2
|
require 'rom/sql/commands/transaction'
|
6
3
|
|
@@ -13,52 +10,18 @@ module ROM
|
|
13
10
|
class Update < ROM::Commands::Update
|
14
11
|
adapter :sql
|
15
12
|
|
16
|
-
extend Deprecations
|
17
|
-
|
18
13
|
include Transaction
|
19
14
|
include ErrorWrapper
|
20
15
|
|
21
|
-
option :original, reader: true
|
22
|
-
|
23
16
|
use :schema
|
24
17
|
|
25
|
-
deprecate :set, :call
|
26
|
-
deprecate :to, :call
|
27
|
-
|
28
18
|
# Updates existing tuple in a relation
|
29
19
|
#
|
30
20
|
# @return [Array<Hash>, Hash]
|
31
21
|
#
|
32
22
|
# @api public
|
33
23
|
def execute(tuple)
|
34
|
-
|
35
|
-
validator.call(attributes)
|
36
|
-
|
37
|
-
changed = diff(attributes.to_h)
|
38
|
-
|
39
|
-
if changed.size > 0
|
40
|
-
update(changed)
|
41
|
-
else
|
42
|
-
EMPTY_ARRAY
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
# Update existing tuple only when it changed
|
47
|
-
#
|
48
|
-
# @example
|
49
|
-
# user = rom.relation(:users).one
|
50
|
-
# new_user = { name: 'Jane Doe' }
|
51
|
-
#
|
52
|
-
# rom.command(:users).change(user).call(new_user)
|
53
|
-
#
|
54
|
-
# @param [#to_h, Hash] original The original tuple
|
55
|
-
#
|
56
|
-
# @return [Command::Update]
|
57
|
-
#
|
58
|
-
# @api public
|
59
|
-
def change(original)
|
60
|
-
Deprecations.warn("#{self.class}#change is deprecated. Use repositories with changesets instead")
|
61
|
-
self.class.build(relation, options.merge(original: original.to_h))
|
24
|
+
update(input[tuple].to_h)
|
62
25
|
end
|
63
26
|
|
64
27
|
private
|
@@ -77,17 +40,6 @@ module ROM
|
|
77
40
|
def primary_key
|
78
41
|
relation.primary_key
|
79
42
|
end
|
80
|
-
|
81
|
-
# Check if input tuple is different from the original one
|
82
|
-
#
|
83
|
-
# @api private
|
84
|
-
def diff(tuple)
|
85
|
-
if original
|
86
|
-
Hash[tuple.to_a - (tuple.to_a & original.to_a)]
|
87
|
-
else
|
88
|
-
tuple
|
89
|
-
end
|
90
|
-
end
|
91
43
|
end
|
92
44
|
end
|
93
45
|
end
|