datamappify 0.30.0 → 0.40.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/CHANGELOG.md +9 -0
- data/ERD.png +0 -0
- data/README.md +78 -16
- data/datamappify.gemspec +4 -3
- data/lib/datamappify/data/criteria/active_record/destroy.rb +1 -1
- data/lib/datamappify/data/criteria/active_record/exists.rb +2 -2
- data/lib/datamappify/data/criteria/active_record/transaction.rb +1 -1
- data/lib/datamappify/data/criteria/common.rb +21 -1
- data/lib/datamappify/data/criteria/relational/count.rb +1 -1
- data/lib/datamappify/data/criteria/relational/find.rb +1 -1
- data/lib/datamappify/data/criteria/relational/save.rb +1 -1
- data/lib/datamappify/data/criteria/sequel/destroy.rb +1 -1
- data/lib/datamappify/data/criteria/sequel/exists.rb +1 -1
- data/lib/datamappify/data/criteria/sequel/transaction.rb +1 -1
- data/lib/datamappify/data/mapper/attribute.rb +9 -0
- data/lib/datamappify/data/mapper.rb +7 -2
- data/lib/datamappify/data/provider/common_provider.rb +1 -1
- data/lib/datamappify/entity/lazy_checking.rb +12 -0
- data/lib/datamappify/entity.rb +4 -0
- data/lib/datamappify/lazy/attributes_handler.rb +123 -0
- data/lib/datamappify/lazy/source_attributes_walker.rb +49 -0
- data/lib/datamappify/lazy.rb +24 -0
- data/lib/datamappify/logger.rb +13 -0
- data/lib/datamappify/repository/lazy_checking.rb +19 -0
- data/lib/datamappify/repository/mapping_dsl.rb +7 -1
- data/lib/datamappify/repository/query_method/callbacks.rb +83 -0
- data/lib/datamappify/repository/query_method/count.rb +6 -1
- data/lib/datamappify/repository/query_method/create.rb +10 -0
- data/lib/datamappify/repository/query_method/destroy.rb +6 -14
- data/lib/datamappify/repository/query_method/exists.rb +17 -0
- data/lib/datamappify/repository/query_method/find.rb +12 -19
- data/lib/datamappify/repository/query_method/method/source_attributes_walker.rb +81 -0
- data/lib/datamappify/repository/query_method/method.rb +74 -25
- data/lib/datamappify/repository/query_method/save.rb +15 -14
- data/lib/datamappify/repository/query_method/update.rb +10 -0
- data/lib/datamappify/repository/query_methods.rb +123 -0
- data/lib/datamappify/repository/unit_of_work/persistent_states/object.rb +122 -0
- data/lib/datamappify/repository/unit_of_work/persistent_states.rb +54 -0
- data/lib/datamappify/repository/unit_of_work/transaction.rb +18 -0
- data/lib/datamappify/repository/unit_of_work.rb +1 -0
- data/lib/datamappify/repository.rb +16 -51
- data/lib/datamappify/version.rb +1 -1
- data/lib/datamappify.rb +3 -1
- data/spec/lazy_spec.rb +73 -0
- data/spec/repository/callbacks_spec.rb +140 -0
- data/spec/repository/dirty_persistence_spec.rb +44 -0
- data/spec/repository/dirty_tracking_spec.rb +82 -0
- data/spec/repository/persistence_spec.rb +41 -119
- data/spec/repository/transactions_spec.rb +25 -0
- data/spec/repository/validation_spec.rb +42 -0
- data/spec/repository_spec.rb +8 -6
- data/spec/spec_helper.rb +2 -2
- data/spec/support/entities/hero_user.rb +5 -0
- data/spec/support/repositories/callbacks_chaining_repository.rb +92 -0
- data/spec/support/repositories/hero_user_repository.rb +30 -0
- data/spec/support/shared/contexts.rb +10 -0
- data/spec/support/tables/sequel.rb +1 -0
- data/spec/unit/repository/query_method_spec.rb +55 -0
- metadata +57 -10
- data/lib/datamappify/repository/query_method/transaction.rb +0 -18
- data/lib/datamappify/repository/query_method.rb +0 -3
@@ -1,12 +1,18 @@
|
|
1
1
|
module Datamappify
|
2
2
|
module Repository
|
3
3
|
module MappingDSL
|
4
|
+
include LazyChecking
|
5
|
+
|
6
|
+
# If the entity is lazy loaded then it assigns
|
7
|
+
# the repository itself back to the entity
|
8
|
+
#
|
4
9
|
# @param entity_class [Class]
|
5
|
-
# entity class
|
6
10
|
#
|
7
11
|
# @return [void]
|
8
12
|
def for_entity(entity_class)
|
9
13
|
data_mapper.entity_class = entity_class
|
14
|
+
|
15
|
+
assign_to_entity if lazy_load?
|
10
16
|
end
|
11
17
|
|
12
18
|
# @param provider_name [String]
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'hooks'
|
2
|
+
|
3
|
+
# Money-patches Hooks
|
4
|
+
module Hooks
|
5
|
+
module ClassMethods
|
6
|
+
# Added the ability to ignore callbacks if the previous callback returns `nil` or `false`
|
7
|
+
#
|
8
|
+
# @return [Boolean]
|
9
|
+
def run_hook_for(name, scope, *args)
|
10
|
+
callbacks = callbacks_for_hook(name)
|
11
|
+
|
12
|
+
callbacks.take_while do |callback|
|
13
|
+
if callback.kind_of? Symbol
|
14
|
+
scope.send(callback, *args)
|
15
|
+
else
|
16
|
+
scope.instance_exec(*args, &callback)
|
17
|
+
end
|
18
|
+
end.length == callbacks.length
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module Datamappify
|
24
|
+
module Repository
|
25
|
+
module QueryMethod
|
26
|
+
module Callbacks
|
27
|
+
def self.included(klass)
|
28
|
+
klass.class_eval do
|
29
|
+
include Hooks
|
30
|
+
|
31
|
+
define_hooks :before_create, :after_create,
|
32
|
+
:before_update, :after_update,
|
33
|
+
:before_save, :after_save,
|
34
|
+
:before_destroy, :after_destroy
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# @param entity [Entity]
|
39
|
+
#
|
40
|
+
# @param types [Symbol]
|
41
|
+
# e.g. :create, :update, :save or :destroy
|
42
|
+
#
|
43
|
+
# @yield callback
|
44
|
+
#
|
45
|
+
# @return [void]
|
46
|
+
def run_callbacks(entity, *types, &block)
|
47
|
+
run_hooks(types, :before, entity) &&
|
48
|
+
(yield_value = block.call) &&
|
49
|
+
run_hooks(types.reverse, :after, entity) &&
|
50
|
+
yield_value
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# @param types [Array<Symbol]
|
56
|
+
# an array of types (e.g. :create, :update, :save or :destroy)
|
57
|
+
#
|
58
|
+
# @param filter [Symbol]
|
59
|
+
# e.g. :before or :after
|
60
|
+
#
|
61
|
+
# @param entity [Entity]
|
62
|
+
#
|
63
|
+
# @return [Boolean]
|
64
|
+
def run_hooks(types, filter, entity)
|
65
|
+
types.take_while do |type|
|
66
|
+
run_hook(hook_for(type, filter), entity)
|
67
|
+
end.length == types.length
|
68
|
+
end
|
69
|
+
|
70
|
+
# @param type [Symbol]
|
71
|
+
# e.g. :create, :update, :save or :destroy
|
72
|
+
#
|
73
|
+
# @param filter [Symbol]
|
74
|
+
# e.g. :before or :after
|
75
|
+
#
|
76
|
+
# @return [String]
|
77
|
+
def hook_for(type, filter)
|
78
|
+
"#{filter}_#{type}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -2,22 +2,14 @@ module Datamappify
|
|
2
2
|
module Repository
|
3
3
|
module QueryMethod
|
4
4
|
class Destroy < Method
|
5
|
-
# @param mapper (see Method#initialize)
|
6
|
-
#
|
7
|
-
# @param id_or_ids_or_entity_or_entities [Entity, Array<Entity>]
|
8
|
-
# an entity or a collection of ids or entities
|
9
|
-
def initialize(mapper, id_or_ids_or_entity_or_entities)
|
10
|
-
super
|
11
|
-
@id_or_ids_or_entity_or_entities = id_or_ids_or_entity_or_entities
|
12
|
-
end
|
13
|
-
|
14
5
|
# @return [void, false]
|
15
|
-
def
|
16
|
-
|
17
|
-
|
18
|
-
end
|
6
|
+
def perform
|
7
|
+
dispatch_criteria_to_default_source(:Destroy, @entity.id)
|
8
|
+
end
|
19
9
|
|
20
|
-
|
10
|
+
# @see Method#writer?
|
11
|
+
def writer?
|
12
|
+
true
|
21
13
|
end
|
22
14
|
end
|
23
15
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Datamappify
|
2
|
+
module Repository
|
3
|
+
module QueryMethod
|
4
|
+
class Exists < Method
|
5
|
+
# @return [Boolean]
|
6
|
+
def perform
|
7
|
+
dispatch_criteria_to_default_source(:Exists, @entity)
|
8
|
+
end
|
9
|
+
|
10
|
+
# @see Method#reader?
|
11
|
+
def reader?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -2,30 +2,18 @@ module Datamappify
|
|
2
2
|
module Repository
|
3
3
|
module QueryMethod
|
4
4
|
class Find < Method
|
5
|
-
# @param
|
5
|
+
# @param options (see Method#initialize)
|
6
6
|
#
|
7
|
-
# @param
|
8
|
-
|
9
|
-
def initialize(mapper, id_or_ids)
|
7
|
+
# @param id [Integer]
|
8
|
+
def initialize(options, id)
|
10
9
|
super
|
11
|
-
@
|
10
|
+
@id = id
|
12
11
|
end
|
13
12
|
|
14
|
-
# @return [Entity, Array<Entity>, nil]
|
15
|
-
def result
|
16
|
-
entities = Array.wrap(@id_or_ids).map { |id| setup_new_entity(id) }.compact
|
17
|
-
|
18
|
-
@id_or_ids.is_a?(Array) ? entities : entities[0]
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
# @param id [Integer]
|
24
|
-
#
|
25
13
|
# @return [Entity, nil]
|
26
|
-
def
|
27
|
-
entity =
|
28
|
-
entity.id = id
|
14
|
+
def perform
|
15
|
+
entity = data_mapper.entity_class.new
|
16
|
+
entity.id = @id
|
29
17
|
|
30
18
|
if dispatch_criteria_to_default_source(:Exists, entity)
|
31
19
|
dispatch_criteria_to_providers(:FindByKey, entity)
|
@@ -35,6 +23,11 @@ module Datamappify
|
|
35
23
|
|
36
24
|
entity
|
37
25
|
end
|
26
|
+
|
27
|
+
# @see Method#reader?
|
28
|
+
def reader?
|
29
|
+
true
|
30
|
+
end
|
38
31
|
end
|
39
32
|
end
|
40
33
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Datamappify
|
2
|
+
module Repository
|
3
|
+
module QueryMethod
|
4
|
+
class Method
|
5
|
+
# Walks through the attributes of the source classes under a provider (e.g. ActiveRecord),
|
6
|
+
# the walker is aware of the dirty state so that certain operations (i.e. #save) can be bypassed
|
7
|
+
class SourceAttributesWalker
|
8
|
+
def initialize(options = {})
|
9
|
+
@entity = options[:entity]
|
10
|
+
@provider_name = options[:provider_name]
|
11
|
+
@attributes = options[:attributes]
|
12
|
+
@dirty_aware = options[:dirty_aware?]
|
13
|
+
@dirty_attributes = options[:dirty_attributes]
|
14
|
+
@query_method = options[:query_method]
|
15
|
+
end
|
16
|
+
|
17
|
+
# @yield [provider_name, source_class, attributes]
|
18
|
+
# action to be performed on the attributes grouped by their source class
|
19
|
+
#
|
20
|
+
# @yieldparam provider_name [String]
|
21
|
+
#
|
22
|
+
# @yieldparam source_class [Class]
|
23
|
+
#
|
24
|
+
# @yieldparam attributes [Set<Data::Mapper::Attribute>]
|
25
|
+
#
|
26
|
+
# @yieldreturn [void]
|
27
|
+
#
|
28
|
+
# @return [void]
|
29
|
+
def execute(&block)
|
30
|
+
@attributes.classify(&:source_class).each do |source_class, attributes|
|
31
|
+
if do_walk?(source_class, attributes)
|
32
|
+
block.call(@provider_name, source_class, attributes)
|
33
|
+
walk_performed(attributes)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
# Whether it is necessary to do the walk
|
41
|
+
#
|
42
|
+
# @param source_class [Class]
|
43
|
+
#
|
44
|
+
# @param attributes [Set<Data::Mapper::Attribute>]
|
45
|
+
#
|
46
|
+
# @return [Boolean]
|
47
|
+
def do_walk?(source_class, attributes)
|
48
|
+
check_dirty?(attributes)
|
49
|
+
end
|
50
|
+
|
51
|
+
# A hook method for when a walk is performed
|
52
|
+
#
|
53
|
+
# @param attributes [Set<Data::Mapper::Attribute>]
|
54
|
+
#
|
55
|
+
# @return [void]
|
56
|
+
def walk_performed(attributes)
|
57
|
+
Logger.performed(@query_method && @query_method.class)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Only walk when it's not dirty aware, or it has dirty attributes
|
61
|
+
#
|
62
|
+
# @param attributes [Set<Data::Mapper::Attribute>]
|
63
|
+
#
|
64
|
+
# @return [Boolean]
|
65
|
+
def check_dirty?(attributes)
|
66
|
+
!@dirty_aware || dirty?(attributes)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Whether the persistent state object is dirty
|
70
|
+
#
|
71
|
+
# @param (see #do_walk?)
|
72
|
+
#
|
73
|
+
# @return [Boolean]
|
74
|
+
def dirty?(attributes)
|
75
|
+
(attributes.map(&:key) & @dirty_attributes).any?
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -1,16 +1,58 @@
|
|
1
|
+
Dir[Datamappify.root.join('repository/query_method/method/*')].each { |file| require file }
|
2
|
+
|
1
3
|
module Datamappify
|
2
4
|
module Repository
|
3
5
|
module QueryMethod
|
4
6
|
# Provides a default set of methods to the varies {QueryMethod} classes
|
5
7
|
class Method
|
6
|
-
# @
|
8
|
+
# @return [Data::Mapper]
|
9
|
+
attr_reader :data_mapper
|
10
|
+
|
11
|
+
# @return [UnitOfWork::PersistentStates]
|
12
|
+
attr_reader :states
|
13
|
+
|
14
|
+
# @param options [Hash]
|
15
|
+
# a hash containing required items like data_mapper and states
|
16
|
+
#
|
17
|
+
# @param entity [Entity]
|
7
18
|
#
|
8
19
|
# @param args [any]
|
9
|
-
def initialize(
|
10
|
-
@
|
20
|
+
def initialize(options, entity = nil, *args)
|
21
|
+
@data_mapper = options[:data_mapper]
|
22
|
+
@states = options[:states]
|
23
|
+
@lazy_load = options[:lazy_load?]
|
24
|
+
@entity = entity
|
25
|
+
end
|
26
|
+
|
27
|
+
# Should the method be aware of the dirty state?
|
28
|
+
# i.e. {Find} probably doesn't whereas {Save} does
|
29
|
+
#
|
30
|
+
# @note Override this method for individual query methods
|
31
|
+
#
|
32
|
+
# @return [Boolean]
|
33
|
+
def dirty_aware?
|
34
|
+
false
|
35
|
+
end
|
36
|
+
|
37
|
+
# The method is for reading data?
|
38
|
+
#
|
39
|
+
# @note Override this method for individual query methods
|
40
|
+
#
|
41
|
+
# @return [Boolean]
|
42
|
+
def reader?
|
43
|
+
false
|
44
|
+
end
|
45
|
+
|
46
|
+
# The method is for writing data?
|
47
|
+
#
|
48
|
+
# @note Override this method for individual query methods
|
49
|
+
#
|
50
|
+
# @return [Boolean]
|
51
|
+
def writer?
|
52
|
+
false
|
11
53
|
end
|
12
54
|
|
13
|
-
|
55
|
+
private
|
14
56
|
|
15
57
|
# Dispatches a {Criteria} according to
|
16
58
|
# the {Data::Mapper data mapper}'s default provider and default source class
|
@@ -19,7 +61,9 @@ module Datamappify
|
|
19
61
|
#
|
20
62
|
# @param args [any]
|
21
63
|
def dispatch_criteria_to_default_source(criteria_name, *args)
|
22
|
-
|
64
|
+
data_mapper.default_provider.build_criteria(
|
65
|
+
criteria_name, data_mapper.default_source_class, *args
|
66
|
+
)
|
23
67
|
end
|
24
68
|
|
25
69
|
# Dispatches a {Criteria} via {#attributes_walker}
|
@@ -30,8 +74,8 @@ module Datamappify
|
|
30
74
|
#
|
31
75
|
# @return [void]
|
32
76
|
def dispatch_criteria_to_providers(criteria_name, entity)
|
33
|
-
attributes_walker do |provider_name, source_class, attributes|
|
34
|
-
|
77
|
+
attributes_walker(entity) do |provider_name, source_class, attributes|
|
78
|
+
data_mapper.provider(provider_name).build_criteria(
|
35
79
|
criteria_name, source_class, entity, attributes
|
36
80
|
)
|
37
81
|
end
|
@@ -39,33 +83,38 @@ module Datamappify
|
|
39
83
|
|
40
84
|
# Walks through the attributes and performs actions on them
|
41
85
|
#
|
42
|
-
# @
|
43
|
-
# action to be performed on the attributes grouped by their source class
|
86
|
+
# @param entity [Entity]
|
44
87
|
#
|
45
|
-
# @
|
88
|
+
# @yield (see SourceAttributesWalker#execute)
|
46
89
|
#
|
47
|
-
# @yieldparam
|
90
|
+
# @yieldparam (see SourceAttributesWalker#execute)
|
48
91
|
#
|
49
|
-
# @
|
92
|
+
# @yieldreturn (see SourceAttributesWalker#execute)
|
50
93
|
#
|
51
94
|
# @return [void]
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
95
|
+
#
|
96
|
+
# @see SourceAttributesWalker#execute
|
97
|
+
def attributes_walker(entity, &block)
|
98
|
+
UnitOfWork::Transaction.new(data_mapper) do
|
99
|
+
data_mapper.classified_attributes.each do |provider_name, attributes|
|
100
|
+
source_attributes_walker.new({
|
101
|
+
:entity => entity,
|
102
|
+
:provider_name => provider_name,
|
103
|
+
:attributes => attributes,
|
104
|
+
:dirty_aware? => dirty_aware?,
|
105
|
+
:dirty_attributes => states.find(entity).changed,
|
106
|
+
:query_method => self
|
107
|
+
}).execute(&block)
|
58
108
|
end
|
59
109
|
end
|
60
110
|
end
|
61
111
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
id_or_entity.is_a?(Integer) ? id_or_entity : id_or_entity.id
|
112
|
+
def source_attributes_walker
|
113
|
+
if @lazy_load
|
114
|
+
Lazy::SourceAttributesWalker
|
115
|
+
else
|
116
|
+
SourceAttributesWalker
|
117
|
+
end
|
69
118
|
end
|
70
119
|
end
|
71
120
|
end
|
@@ -2,26 +2,27 @@ module Datamappify
|
|
2
2
|
module Repository
|
3
3
|
module QueryMethod
|
4
4
|
class Save < Method
|
5
|
-
# @
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
def initialize(mapper, entity_or_entities)
|
10
|
-
super
|
11
|
-
@entity_or_entities = entity_or_entities
|
12
|
-
end
|
13
|
-
|
14
|
-
# @return [Entity, Array<Entity>, false]
|
15
|
-
def result
|
16
|
-
Array.wrap(@entity_or_entities).each do |entity|
|
17
|
-
create_or_update(entity)
|
5
|
+
# @return [Entity, false]
|
6
|
+
def perform
|
7
|
+
states.update(@entity) do
|
8
|
+
create_or_update(@entity)
|
18
9
|
end
|
19
10
|
|
20
|
-
@
|
11
|
+
@entity
|
21
12
|
rescue Data::EntityInvalid
|
22
13
|
false
|
23
14
|
end
|
24
15
|
|
16
|
+
# @see Method#dirty_aware?
|
17
|
+
def dirty_aware?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
# @see Method#writer?
|
22
|
+
def writer?
|
23
|
+
true
|
24
|
+
end
|
25
|
+
|
25
26
|
private
|
26
27
|
|
27
28
|
# @param entity [Entity]
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'datamappify/repository/query_method/method'
|
2
|
+
|
3
|
+
Dir[Datamappify.root.join('repository/query_method/*')].each { |file| require file }
|
4
|
+
|
5
|
+
module Datamappify
|
6
|
+
module Repository
|
7
|
+
module QueryMethods
|
8
|
+
def self.included(klass)
|
9
|
+
klass.class_eval do
|
10
|
+
include QueryMethod::Callbacks
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Does the entity exist already in the repository?
|
15
|
+
#
|
16
|
+
# @param entity [Entity]
|
17
|
+
#
|
18
|
+
# @return [Boolean]
|
19
|
+
def exists?(entity)
|
20
|
+
QueryMethod::Exists.new(query_options, entity).perform
|
21
|
+
end
|
22
|
+
|
23
|
+
# @param id [Integer]
|
24
|
+
# an entity id or a collection of entity ids
|
25
|
+
#
|
26
|
+
# @return [Entity, nil]
|
27
|
+
def find(id)
|
28
|
+
QueryMethod::Find.new(query_options, id).perform
|
29
|
+
end
|
30
|
+
|
31
|
+
# @param entity [Entity]
|
32
|
+
# an entity or a collection of entities
|
33
|
+
#
|
34
|
+
# @return [Entity, false]
|
35
|
+
def create(entity)
|
36
|
+
run_callbacks entity, :save, :create do
|
37
|
+
QueryMethod::Create.new(query_options, entity).perform
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# @param (see #create)
|
42
|
+
#
|
43
|
+
# @raise [Data::EntityNotSaved]
|
44
|
+
#
|
45
|
+
# @return [Entity]
|
46
|
+
def create!(entity)
|
47
|
+
create(entity) || raise(Data::EntityNotSaved)
|
48
|
+
end
|
49
|
+
|
50
|
+
# @param entity [Entity]
|
51
|
+
# an entity or a collection of entities
|
52
|
+
#
|
53
|
+
# @return [Entity, false]
|
54
|
+
def update(entity)
|
55
|
+
run_callbacks entity, :save, :update do
|
56
|
+
QueryMethod::Update.new(query_options, entity).perform
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# @param (see #update)
|
61
|
+
#
|
62
|
+
# @raise [Data::EntityNotSaved]
|
63
|
+
#
|
64
|
+
# @return [Entity]
|
65
|
+
def update!(entity)
|
66
|
+
update(entity) || raise(Data::EntityNotSaved)
|
67
|
+
end
|
68
|
+
|
69
|
+
# @param entity [Entity]
|
70
|
+
# an entity or a collection of entities
|
71
|
+
#
|
72
|
+
# @return [Entity, false]
|
73
|
+
def save(entity)
|
74
|
+
exists?(entity) ? update(entity) : create(entity)
|
75
|
+
end
|
76
|
+
|
77
|
+
# @param (see #save)
|
78
|
+
#
|
79
|
+
# @raise [Data::EntityNotSaved]
|
80
|
+
#
|
81
|
+
# @return [Entity]
|
82
|
+
def save!(entity)
|
83
|
+
exists?(entity) ? update!(entity) : create!(entity)
|
84
|
+
end
|
85
|
+
|
86
|
+
# @param entity [Entity]
|
87
|
+
#
|
88
|
+
# @return [void, false]
|
89
|
+
def destroy(entity)
|
90
|
+
run_callbacks entity, :destroy do
|
91
|
+
QueryMethod::Destroy.new(query_options, entity).perform
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# @param (see #destroy)
|
96
|
+
#
|
97
|
+
# @raise [Data::EntityNotDestroyed]
|
98
|
+
#
|
99
|
+
# @return [void]
|
100
|
+
def destroy!(entity)
|
101
|
+
destroy(entity) || raise(Data::EntityNotDestroyed)
|
102
|
+
end
|
103
|
+
|
104
|
+
# @return [Integer]
|
105
|
+
def count
|
106
|
+
QueryMethod::Count.new(query_options).perform
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
# Some default, required objects passed into each query method
|
112
|
+
#
|
113
|
+
# @return [Hash]
|
114
|
+
def query_options
|
115
|
+
{
|
116
|
+
:data_mapper => data_mapper,
|
117
|
+
:states => states,
|
118
|
+
:lazy_load? => lazy_load?
|
119
|
+
}
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|