artirix_data_models 0.22.1 → 0.23.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 88e79f89e6e91ab1deda5af61d7dda701857db07
4
- data.tar.gz: 4099f19094480614606364d876d0af9ea301ab2a
3
+ metadata.gz: 4bfb65d885ba816daff5dafaf4f725cbacf35a6e
4
+ data.tar.gz: 84baf5c1431d2b39438ae646e85c450183227f35
5
5
  SHA512:
6
- metadata.gz: 71e7fdf8e33deacada7d9a656d2006f5aa1f8f29f2c2cf6fb57fb36a0b54b2ac9d971970558c02facd79c0a24653cd56dbf55efbf9a460db58fe8cab12de98ac
7
- data.tar.gz: f7b8de3340efd86fe0515bf7d8f4d65e04880d0da1f5ae0ec0826f064cb53308d60608bcca7c297d5883e5652e1a8d96c0f013a6544dc52cf488c63067c880d9
6
+ metadata.gz: 04d9eb00b920c981e36cda90369f200df8c7449c5d9178a8bcd9f59d5c593ce3c6d3178ea2e7fb9954585e5a55ed323a7e02fafdf54141e605e6882a73c8e07b
7
+ data.tar.gz: 55772da2c303dd510e28956f13cebbad4e475b08c6a243813e3f373c08a73d2328ddfaca8c632829f6099f6732573d9ad1159afa673ac32aa36be2b6e77eacea
data/README.md CHANGED
@@ -137,19 +137,21 @@ Your app should extend the `ArtirixDataModels::DAORegistry`. We can override the
137
137
 
138
138
  Also, the Registry class that you want to use in your app should have in its definition a call to `self.mark_as_main_registry`. This call must be **after the override of `setup_config`.**
139
139
 
140
+ You can add loaders that will be called only and memoized with `set_persistent_loader` and loaders that will cbe called every time with `set_transient_loader`. `se_loader` is an alias of `set_persistent_loader`.
141
+
140
142
  ```ruby
141
143
  class DAORegistry < ArtirixDataModels::DAORegistry
142
144
  def setup_config
143
145
  super
144
146
 
145
- set_loader(:aggregations_factory) { AggregationsFactory.new }
147
+ set_persistent_loader(:aggregations_factory) { AggregationsFactory.new }
146
148
 
147
- set_loader(:yacht) { YachtDAO.new gateway: get(:gateway) }
148
- set_loader(:article) { ArticleDAO.new gateway: get(:gateway) }
149
- set_loader(:broker) { BrokerDAO.new gateway: get(:gateway) }
149
+ set_transient_loader(:yacht) { YachtDAO.new gateway: get(:gateway) }
150
+ set_transient_loader(:article) { ArticleDAO.new gateway: get(:gateway) }
151
+ set_transient_loader(:broker) { BrokerDAO.new gateway: get(:gateway) }
150
152
 
151
153
  set_loader(:artirix_hub_api_gateway) { ArtirixDataModels::DataGateway.new connection: ArtirixHubApiService::ConnectionLoader.connection }
152
- set_loader(:lead) { LeadDAO.new gateway: get(:artirix_hub_api_gateway) }
154
+ set_transient_loader(:lead) { LeadDAO.new gateway: get(:artirix_hub_api_gateway) }
153
155
  end
154
156
 
155
157
 
@@ -159,6 +161,16 @@ class DAORegistry < ArtirixDataModels::DAORegistry
159
161
  end
160
162
  ```
161
163
 
164
+ You can use the DAORegistry by invoking it directly (or calling its instance) `DAORegistry.get(:name)` or `DAORegistry.instance.get(:name)`.
165
+
166
+ You can also use an identity map mode (see bellow)
167
+
168
+ ### Identity Map
169
+
170
+ You can use `dao_registry = DAORegistry.with_identity_map`. Then, the DAO's default methods `get`, `find` and `get_some` will register the loaded models into the DAO, acting as an identity map, and will also use that identity map to check for the existence of models with those PKs, returning them if they are found.
171
+
172
+ The Identity Map does not have a TTL, so use it only with transient DAOs -> you don't want the identity map to live between requests, since that will mean that the models will never be forgotten, not being able to see new fresh versions, with the extra problem of memory leak.
173
+
162
174
  ### initializer
163
175
 
164
176
  An initializer should be added for extra configuration.
@@ -315,6 +327,11 @@ end
315
327
 
316
328
  ## Changes
317
329
 
330
+ ### 0.23.0
331
+ - DAORegistry now DI'ed into the DAOs and models, by adding `dao_registry_loader` or a direct `dao_registry`.
332
+ - DAORegistry with support for Identity Map
333
+ - deprecated the use of `Aggregation.from_json`, please use the factory.
334
+
318
335
  ### 0.22.1
319
336
 
320
337
  added message support for DataGateway exceptions
data/bin/rake ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rake' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require "pathname"
10
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require "rubygems"
14
+ require "bundler/setup"
15
+
16
+ load Gem.bin_path("rake", "rake")
@@ -16,6 +16,7 @@ require 'artirix_cache_service'
16
16
 
17
17
 
18
18
  # loading features
19
+ require 'artirix_data_models/with_dao_registry'
19
20
  require 'artirix_data_models/inspectable'
20
21
  require 'artirix_data_models/es_collection'
21
22
  require 'artirix_data_models/aggregation'
@@ -1,14 +1,19 @@
1
1
  module ArtirixDataModels
2
2
  class CommonAggregation
3
3
  include Inspectable
4
+ include ArtirixDataModels::WithDAORegistry
5
+
4
6
  attr_accessor :name
5
7
 
6
8
  def initialize(name)
7
9
  @name = name
8
10
  end
9
11
 
10
- def self.from_json(definition, value_class = Aggregation::Value)
11
- DAORegistry.aggregations_factory.aggregation_from_json(definition, value_class: value_class, aggregation_class: self)
12
+ # DEPRECATED
13
+ def self.from_json(definition, value_class = Aggregation::Value, aggregations_factory: nil)
14
+ ActiveSupport::Deprecation.new('1.0', 'ArtirixDataModels').warn('`Aggregation.from_json` is deprecated in favour of `AggregationsFactory#aggregation_from_json`')
15
+ aggregations_factory ||= DAORegistry.get(:aggregations_factory)
16
+ aggregations_factory.aggregation_from_json(definition, value_class: value_class, aggregation_class: self)
12
17
  end
13
18
 
14
19
  def pretty_name
@@ -2,6 +2,8 @@ module ArtirixDataModels
2
2
  class AggregationsFactory
3
3
  DEFAULT_COLLECTION_CLASS_NAME = ''.freeze
4
4
 
5
+ include ArtirixDataModels::WithDAORegistry
6
+
5
7
  # AGGREGATION CLASS BUILDING
6
8
 
7
9
  def self.sorted_aggregation_class_based_on_index_on(index_array)
@@ -32,7 +34,12 @@ module ArtirixDataModels
32
34
  end
33
35
 
34
36
  def default_loader
35
- proc { |aggregation| Aggregation.from_json aggregation }
37
+ aggregations_factory = self
38
+ proc { |definition|
39
+ aggregations_factory.aggregation_from_json definition,
40
+ value_class: Aggregation::Value,
41
+ aggregation_class: Aggregation
42
+ }
36
43
  end
37
44
 
38
45
  def get_loader(aggregation_name, collection_class)
@@ -4,48 +4,76 @@ module ArtirixDataModels
4
4
 
5
5
  DELEGATED_METHODS = [
6
6
  :partial_mode_fields,
7
+
7
8
  :model_name,
8
9
  :model_class,
10
+
9
11
  :paths_factory,
10
12
  :fake_mode_factory,
13
+
11
14
  :gateway,
15
+
12
16
  :force_fake_enabled,
13
17
  :force_fake_disabled,
14
18
  :remove_force_fake,
15
19
  :fake?,
16
20
  :forced_fake_enabled?,
17
21
  :forced_fake_disabled?,
22
+
18
23
  :empty_collection,
19
24
  :empty_collection_for,
25
+
20
26
  :perform_get,
21
27
  :perform_post,
22
28
  :perform_put,
23
29
  :perform_delete,
30
+
31
+ :dao_registry,
32
+ :dao_registry=,
33
+ :set_dao_registry,
34
+ :dao_registry_loader,
35
+ :dao_registry_loader=,
36
+ :set_dao_registry_loader,
37
+ :set_default_dao_registry_loader,
38
+ :set_default_dao_registry,
24
39
  ]
25
40
 
26
41
  included do
27
42
  include ArtirixDataModels::DAOConcerns::WithResponseAdaptors
43
+ include ArtirixDataModels::WithDAORegistry
28
44
 
29
45
  attr_reader :basic_model_dao
30
46
  delegate *DELEGATED_METHODS, to: :basic_model_dao
31
47
  end
32
48
 
33
49
 
34
- def initialize(gateway: nil, gateway_factory: nil, ignore_default_gateway: false, model_name: nil, model_class: nil, paths_factory: nil, fake_mode_factory: nil)
35
- if gateway.blank? && gateway_factory.blank? && !ignore_default_gateway
36
- gateway = ArtirixDataModels::DAORegistry.gateway
37
- end
50
+ def initialize(dao_registry: nil,
51
+ dao_registry_loader: nil,
52
+ gateway: nil,
53
+ gateway_factory: nil,
54
+ ignore_default_gateway: false,
55
+ model_name: nil,
56
+ model_class: nil,
57
+ paths_factory: nil,
58
+ fake_mode_factory: nil)
38
59
 
39
60
  model_name ||= default_model_name
40
61
  model_class ||= default_model_class
41
62
  paths_factory ||= default_path_factory
42
63
  fake_mode_factory ||= default_fake_mode_factory
43
- @basic_model_dao = ArtirixDataModels::DAORegistry.basic_class.new model_name: model_name,
44
- model_class: model_class,
45
- fake_mode_factory: fake_mode_factory,
46
- paths_factory: paths_factory,
47
- gateway: gateway,
48
- gateway_factory: gateway_factory
64
+
65
+ # temporary dao registry to load basic_class only
66
+ dr = ArtirixDataModels::WithDAORegistry.loader_or_registry_or_default(dao_registry_loader: dao_registry_loader, dao_registry: dao_registry)
67
+ @basic_model_dao = dr.get(:basic_class).new model_name: model_name,
68
+ model_class: model_class,
69
+ fake_mode_factory: fake_mode_factory,
70
+ paths_factory: paths_factory,
71
+ gateway: gateway,
72
+ gateway_factory: gateway_factory,
73
+ dao_registry: dao_registry,
74
+ dao_registry_loader: dao_registry_loader,
75
+ ignore_default_gateway: ignore_default_gateway
76
+
49
77
  end
50
78
 
51
79
  def default_model_name
@@ -88,24 +116,63 @@ module ArtirixDataModels
88
116
  end
89
117
 
90
118
  def get_full(model_pk, model_to_reload: nil, cache_adaptor: nil, **extra_options)
119
+ # we do not check in the registry, since it could be a reload
91
120
  model_to_reload ||= new_model_with_pk(model_pk)
92
121
  cache_adaptor ||= cache_model_adaptor_for_get_full(model_pk, model_to_reload: model_to_reload, **extra_options)
93
- basic_model_dao.get_full(model_pk, model_to_reload: model_to_reload, cache_adaptor: cache_adaptor, **extra_options)
122
+
123
+ model = basic_model_dao.get_full(model_pk, model_to_reload: model_to_reload, cache_adaptor: cache_adaptor, **extra_options)
124
+
125
+ complete_model model
94
126
  end
95
127
 
96
128
  def get(model_pk, cache_adaptor: nil, **extra_options)
129
+ model = dao_registry.get_model model_name, model_pk
130
+ return model if model.present?
131
+
97
132
  cache_adaptor ||= cache_model_adaptor_for_get(model_pk, **extra_options)
98
- basic_model_dao.get(model_pk, cache_adaptor: cache_adaptor, **extra_options)
133
+
134
+ model = basic_model_dao.get(model_pk, cache_adaptor: cache_adaptor, **extra_options)
135
+
136
+ complete_model model
99
137
  end
100
138
 
101
139
  def find(model_pk, cache_adaptor: nil, **extra_options)
140
+ model = dao_registry.get_model model_name, model_pk
141
+ return model if model.present?
142
+
102
143
  cache_adaptor ||= cache_model_adaptor_for_find(model_pk, **extra_options)
103
- basic_model_dao.find(model_pk, cache_adaptor: cache_adaptor, **extra_options)
144
+
145
+ model = basic_model_dao.find(model_pk, cache_adaptor: cache_adaptor, **extra_options)
146
+
147
+ complete_model model
104
148
  end
105
149
 
106
150
  def get_some(model_pks, cache_adaptor: nil, **extra_options)
107
- cache_adaptor ||= cache_model_adaptor_for_get_some(model_pks, **extra_options)
108
- basic_model_dao.get_some(model_pks, cache_adaptor: cache_adaptor, **extra_options)
151
+ registered = Array(model_pks).map do |model_pk|
152
+ [
153
+ model_pk,
154
+ dao_registry.get_model(model_name, model_pk)
155
+ ]
156
+ end.to_h
157
+
158
+ return registered.values if registered.values.all?(&:present?)
159
+
160
+ # load only the missing
161
+ missing_pks = registered.select { |_k, v| v.blank? }.keys
162
+
163
+ cache_adaptor ||= cache_model_adaptor_for_get_some(missing_pks, **extra_options)
164
+
165
+ models = basic_model_dao.get_some(missing_pks, cache_adaptor: cache_adaptor, **extra_options)
166
+
167
+ Array(models).each do |model|
168
+ complete_model model
169
+ end
170
+
171
+ list = registered.values.compact.concat(models)
172
+
173
+ # reorder with the same order of the model_pks
174
+ # (if for any reason it does not have a primary key or if it is not in the list, then use -1 so they are at the start)
175
+ list.sort_by { |m| pk = m.try :primary_key; model_pks.index(pk) || -1 }
109
176
  end
110
177
 
111
178
  private
@@ -134,6 +201,15 @@ module ArtirixDataModels
134
201
  ArtirixDataModels::CachedActionAdaptor::GetSome.new(dao_name: model_name, model_pks: model_pks, **extra_options)
135
202
  end
136
203
 
204
+ def complete_model(model)
205
+ if model
206
+ dao_registry.register_model model
207
+ model.try :set_dao_registry_loader, dao_registry_loader
208
+ end
209
+
210
+ model
211
+ end
212
+
137
213
  module FakeModes
138
214
  module Factory
139
215
 
@@ -145,15 +221,15 @@ module ArtirixDataModels
145
221
  raise NotImplementedError
146
222
  end
147
223
 
148
- def get(model_pk)
224
+ def get(_model_pk)
149
225
  raise NotImplementedError
150
226
  end
151
227
 
152
- def get_full(model_pk, given_model_to_reload = nil)
228
+ def get_full(_model_pk, given_model_to_reload = nil)
153
229
  raise NotImplementedError
154
230
  end
155
231
 
156
- def get_some(model_pks)
232
+ def get_some(_model_pks)
157
233
  raise NotImplementedError
158
234
  end
159
235
 
@@ -25,7 +25,7 @@ module ArtirixDataModels
25
25
  end
26
26
 
27
27
  def response_adaptor_for_collection(from, size, collection_element_model_class = model_class)
28
- model_adaptor_factory.collection collection_element_model_class, from, size
28
+ model_adaptor_factory.collection collection_element_model_class, from, size, dao_registry_loader
29
29
  end
30
30
 
31
31
  def response_adaptor_for_block(&block)
@@ -14,17 +14,18 @@ class ArtirixDataModels::DAORegistry
14
14
 
15
15
  # singleton instance
16
16
  def initialize
17
- @_repository = {}
18
- @_loaders = {}
17
+ @_repository = {}
18
+ @_persistent_loaders = {}
19
+ @_transient_loaders = {}
19
20
 
20
21
  setup_config
21
22
  end
22
23
 
23
24
  def setup_config
24
- set_loader(:aggregations_factory) { ArtirixDataModels::AggregationsFactory.new }
25
- set_loader(:basic_class) { ArtirixDataModels::BasicModelDAO }
26
- set_loader(:gateway) { ArtirixDataModels::DataGateway.new }
27
- set_loader(:model_fields) { ArtirixDataModels::ModelFieldsDAO.new gateway: get(:gateway) }
25
+ set_persistent_loader(:aggregations_factory) { ArtirixDataModels::AggregationsFactory.new }
26
+ set_persistent_loader(:basic_class) { ArtirixDataModels::BasicModelDAO }
27
+ set_persistent_loader(:gateway) { ArtirixDataModels::DataGateway.new }
28
+ set_persistent_loader(:model_fields) { ArtirixDataModels::ModelFieldsDAO.new gateway: get(:gateway) }
28
29
  end
29
30
 
30
31
  def aggregations_factory
@@ -45,36 +46,95 @@ class ArtirixDataModels::DAORegistry
45
46
 
46
47
  def exist?(key)
47
48
  key = key.to_sym
48
- @_repository.key?(key) || @_loaders.key?(key)
49
+ @_repository.key?(key) || @_persistent_loaders.key?(key) || @_transient_loaders.key?(key)
49
50
  end
50
51
 
51
- def get(key)
52
- @_repository[key.to_sym] || call_loader(key)
52
+ def get(key, override_dao_registry: nil)
53
+ x = @_repository[key.to_sym] || call_loader(key)
54
+ if x.present? && override_dao_registry.present? && x.respond_to?(:set_dao_registry)
55
+ x.set_dao_registry override_dao_registry
56
+ end
57
+
58
+ x
53
59
  end
54
60
 
55
- def call_loader(key)
56
- key = key.to_sym
57
- @_repository[key] = @_loaders[key].call
61
+ def set_transient_loader(key, loader = nil, &block)
62
+ key = key.to_sym
63
+
64
+ if block
65
+ @_transient_loaders[key] = block
66
+ elsif loader.respond_to? :call
67
+ @_transient_loaders[key] = loader
68
+ else
69
+ raise ArgumentError, "no block and no loader given for key #{key}"
70
+ end
58
71
  end
59
72
 
60
- def set_loader(key, loader = nil, &block)
73
+ def set_persistent_loader(key, loader = nil, &block)
61
74
  key = key.to_sym
62
75
 
63
76
  if block
64
- @_loaders[key] = block
77
+ @_persistent_loaders[key] = block
65
78
  elsif loader.respond_to? :call
66
- @_loaders[key] = loader
79
+ @_persistent_loaders[key] = loader
67
80
  else
68
81
  raise ArgumentError, "no block and no loader given for key #{key}"
69
82
  end
70
83
  end
71
84
 
85
+ alias_method :set_loader, :set_persistent_loader
86
+
87
+ ################
88
+ # IDENTITY MAP #
89
+ ################
90
+
91
+ def with_identity_map
92
+ IdentityMap.new dao_registry: self
93
+ end
94
+
95
+ # IDENTITY MAP compatible
96
+ def register_model(_model)
97
+ # DO NOTHING
98
+ self
99
+ end
100
+
101
+ def unload_model(_model)
102
+ # DO NOTHING
103
+ self
104
+ end
105
+
106
+ def get_model(_model_dao_name, _primary_key)
107
+ # DO NOTHING
108
+ nil
109
+ end
110
+
111
+ private
112
+ def call_loader(key)
113
+ key = key.to_sym
114
+ if @_persistent_loaders[key]
115
+ @_repository[key] = @_persistent_loaders[key].call
116
+ elsif @_transient_loaders[key]
117
+ @_transient_loaders[key].call
118
+ else
119
+ raise LoaderNotFound, "no loader or transient found for #{key}"
120
+ end
121
+ end
122
+
123
+
72
124
  # static methods
73
125
 
74
126
  def self.set_loader(key, loader = nil, &block)
75
127
  instance.set_loader key, loader, &block
76
128
  end
77
129
 
130
+ def self.set_persistent_loader(key, loader = nil, &block)
131
+ instance.set_persistent_loader key, loader, &block
132
+ end
133
+
134
+ def self.set_transient_loader(key, loader = nil, &block)
135
+ instance.set_transient_loader key, loader, &block
136
+ end
137
+
78
138
  def self.get(key)
79
139
  instance.get key
80
140
  end
@@ -83,6 +143,10 @@ class ArtirixDataModels::DAORegistry
83
143
  instance.exist? key
84
144
  end
85
145
 
146
+ def self.with_identity_map
147
+ instance.with_identity_map
148
+ end
149
+
86
150
  def self.method_missing(method, *args, &block)
87
151
  if exist?(method)
88
152
  get(method)
@@ -95,4 +159,100 @@ class ArtirixDataModels::DAORegistry
95
159
  exist?(method) || super
96
160
  end
97
161
 
162
+ class LoaderNotFound < StandardError
163
+ end
164
+
165
+ class IdentityMap
166
+ include ArtirixDataModels::WithDAORegistry
167
+
168
+ def initialize(dao_registry_loader: nil, dao_registry: nil)
169
+ set_dao_registry_and_loader dao_registry_loader, dao_registry
170
+ @identity_map = {}
171
+ end
172
+
173
+ ##############################
174
+ # DELEGATING TO DAO REGISTRY #
175
+ ##############################
176
+
177
+ delegate :exist?, :aggregations_factory, to: :dao_registry
178
+
179
+ def respond_to_missing?(method_name, include_private = false)
180
+ dao_registry.respond_to? method_name, include_private
181
+ end
182
+
183
+ def method_missing(method_name, *arguments, &block)
184
+ dao_registry.send method_name, *arguments, &block
185
+ end
186
+
187
+ def get(key, override_dao_registry: nil)
188
+ override_dao_registry ||= self
189
+ dao_registry.get key, override_dao_registry: override_dao_registry
190
+ end
191
+
192
+ ###########################
193
+ # IDENTITY MAP FOR MODELS #
194
+ ###########################
195
+
196
+ def register_model(model)
197
+ model_dao_name, primary_key = keys_from_model(model, action: :register)
198
+ return self unless model_dao_name.present? && primary_key.present?
199
+
200
+ log "register model #{model_dao_name}:#{primary_key}"
201
+
202
+ @identity_map[model_dao_name] ||= {}
203
+ @identity_map[model_dao_name][primary_key] = model
204
+
205
+ self
206
+ end
207
+
208
+ def unload_model(model)
209
+ model_dao_name, primary_key = keys_from_model(model, action: :unload)
210
+ return self unless model_dao_name.present? && primary_key.present?
211
+
212
+ log "unload model #{model_dao_name}:#{primary_key}"
213
+
214
+ @identity_map[model_dao_name] ||= {}
215
+ @identity_map[model_dao_name].delete primary_key
216
+
217
+ self
218
+ end
219
+
220
+ def get_model(model_dao_name, primary_key)
221
+ model_dao_name = model_dao_name.to_s
222
+ primary_key = primary_key.to_s
223
+ return nil unless model_dao_name.present? && primary_key.present?
224
+
225
+ @identity_map[model_dao_name] ||= {}
226
+ val = @identity_map[model_dao_name][primary_key]
227
+
228
+ if val.nil?
229
+ log "get model #{model_dao_name}:#{primary_key} NOT PRESENT"
230
+ else
231
+ log "get model #{model_dao_name}:#{primary_key} PRESENT!!!!!"
232
+ end
233
+
234
+ val
235
+ end
236
+
237
+ private
238
+ def log(msg)
239
+ ArtirixDataModels.logger.debug "DAO-REGISTRY-IDENTITY-MAP #{object_id} => #{msg}"
240
+ end
241
+
242
+ def keys_from_model(model, action: :use)
243
+ model_dao_name = model.try :model_dao_name
244
+ primary_key = model.try :primary_key
245
+
246
+ if model_dao_name.blank?
247
+ ArtirixDataModels.logger.error("model does not have a `model_dao_name` #{model}: we cannot #{action} it")
248
+ end
249
+
250
+ if primary_key.blank?
251
+ ArtirixDataModels.logger.error("model does not have a `primary_key` #{model}: we cannot #{action} it")
252
+ end
253
+
254
+ [model_dao_name.to_s, primary_key.to_s]
255
+ end
256
+
257
+ end
98
258
  end
@@ -1,15 +1,38 @@
1
1
  class ArtirixDataModels::BasicModelDAO
2
2
  include ArtirixDataModels::DAOConcerns::WithResponseAdaptors
3
+ include ArtirixDataModels::WithDAORegistry
3
4
 
4
- attr_reader :model_name, :model_class, :paths_factory, :fake_mode_factory, :gateway_factory, :loaded_gateway
5
+ attr_reader :model_name, :model_class, :paths_factory, :fake_mode_factory, :gateway_factory
5
6
 
6
- def initialize(model_name:, model_class:, paths_factory:, gateway:, fake_mode_factory:, gateway_factory:)
7
- @model_name = model_name
8
- @model_class = model_class
9
- @paths_factory = paths_factory
10
- @loaded_gateway = gateway
11
- @gateway_factory = gateway_factory
12
- @fake_mode_factory = fake_mode_factory
7
+ def initialize(dao_registry: nil,
8
+ dao_registry_loader: nil,
9
+ model_name:,
10
+ model_class:,
11
+ paths_factory:,
12
+ gateway:,
13
+ fake_mode_factory:,
14
+ gateway_factory:,
15
+ ignore_default_gateway: false)
16
+
17
+ set_dao_registry_and_loader dao_registry_loader, dao_registry
18
+
19
+ @model_name = model_name
20
+ @model_class = model_class
21
+ @paths_factory = paths_factory
22
+ @loaded_gateway = gateway
23
+ @gateway_factory = gateway_factory
24
+ @fake_mode_factory = fake_mode_factory
25
+ @ignore_default_gateway = ignore_default_gateway
26
+ end
27
+
28
+ def default_gateway_available?
29
+ !@ignore_default_gateway
30
+ end
31
+
32
+ def loaded_gateway
33
+ @loaded_gateway ||= if gateway_factory.blank? && default_gateway_available?
34
+ dao_registry.get(:gateway)
35
+ end
13
36
  end
14
37
 
15
38
  ###########
@@ -62,7 +85,7 @@ class ArtirixDataModels::BasicModelDAO
62
85
  if fake?
63
86
  fake_mode_factory.partial_mode_fields
64
87
  else
65
- ArtirixDataModels::DAORegistry.model_fields.partial_mode_fields_for model_name
88
+ dao_registry.get(:model_fields).partial_mode_fields_for model_name
66
89
  end
67
90
  end
68
91
 
@@ -7,10 +7,15 @@
7
7
  class ArtirixDataModels::ModelFieldsDAO
8
8
  PARTIAL_FIELDS = {}
9
9
 
10
- attr_reader :gateway
10
+ include ArtirixDataModels::WithDAORegistry
11
11
 
12
- def initialize(gateway: nil)
13
- @gateway = gateway || ArtirixDataModels::DAORegistry.gateway
12
+ def initialize(dao_registry: nil, dao_registry_loader: nil, gateway: nil)
13
+ set_dao_registry_and_loader dao_registry_loader, dao_registry
14
+ @gateway = gateway
15
+ end
16
+
17
+ def gateway
18
+ @gateway ||= dao_registry.gateway
14
19
  end
15
20
 
16
21
  def partial_mode_fields_for(model_name)
@@ -3,9 +3,9 @@ require 'oj'
3
3
  module ArtirixDataModels
4
4
  class EsCollection
5
5
 
6
- DEFAULT_SIZE = 10
6
+ DEFAULT_SIZE = 10
7
7
  CACHE_KEY_SECTION_SEPARATOR = '/'.freeze
8
- CACHE_KEY_RESULT_SEPARATOR = '\\'.freeze
8
+ CACHE_KEY_RESULT_SEPARATOR = '\\'.freeze
9
9
 
10
10
  def self.work_with_kaminari
11
11
  require 'kaminari'
@@ -66,16 +66,26 @@ module ArtirixDataModels
66
66
  end
67
67
 
68
68
  include Enumerable
69
+ include ArtirixDataModels::WithDAORegistry
69
70
 
70
71
  attr_reader :klass_or_factory, :response, :from, :size
71
72
 
72
- # @param klass_or_factory [A Model Class|Callable] The model class or the Factory (callable object) to build the model
73
- # @param response [Hash] The full response returned from the DataLayer
74
- # @param from [Int] requested offset (0 by default)
75
- # @param size [Int] requested amount of hits (10 by default)
73
+ # @param klass_or_factory [A Model Class|Callable] The model class or the Factory (callable object) to build the model
74
+ # @param response [Hash] The full response returned from the DataLayer
75
+ # @param from [Int] requested offset (0 by default)
76
+ # @param size [Int] requested amount of hits (10 by default)
76
77
  # @param aggregations_factory [Int] requested amount of hits (10 by default)
77
78
  #
78
- def initialize(klass_or_factory, response:, from: 0, size: DEFAULT_SIZE, aggregations_factory: nil)
79
+ def initialize(klass_or_factory,
80
+ response:,
81
+ from: 0,
82
+ size: DEFAULT_SIZE,
83
+ dao_registry: nil,
84
+ dao_registry_loader: nil,
85
+ aggregations_factory: nil)
86
+
87
+ set_dao_registry_and_loader dao_registry_loader, dao_registry
88
+
79
89
  @klass_or_factory = klass_or_factory
80
90
  @response = response
81
91
  @from = from
@@ -84,7 +94,7 @@ module ArtirixDataModels
84
94
  end
85
95
 
86
96
  def aggregations_factory
87
- @aggregations_factory || ArtirixDataModels::DAORegistry.aggregations_factory
97
+ @aggregations_factory || dao_registry.get(:aggregations_factory)
88
98
  end
89
99
 
90
100
  # The number of total hits for a query
@@ -170,13 +180,23 @@ module ArtirixDataModels
170
180
  def deserialize_document(document)
171
181
  info = info_from_document(document)
172
182
 
173
- if model_factory
174
- model_factory.call info
175
- elsif model_class
176
- model_class.new info
177
- else
178
- raise 'no model class, nor model factory'
183
+ model = if model_factory
184
+ model_factory.call info
185
+ elsif model_class
186
+ model_class.new info
187
+ else
188
+ raise 'no model class, nor model factory'
189
+ end
190
+ complete_model model
191
+ end
192
+
193
+ def complete_model(model)
194
+ if model
195
+ dao_registry.register_model model
196
+ model.try :set_dao_registry_loader, dao_registry_loader
179
197
  end
198
+
199
+ model
180
200
  end
181
201
 
182
202
  def model_factory
@@ -52,9 +52,15 @@ module ArtirixDataModels::GatewayResponseAdaptors
52
52
  new ->(data_list) { Array(data_list).map { |data_hash| model_class.new data_hash } }
53
53
  end
54
54
 
55
- def self.collection(object_class_or_factory, from = 0, size = nil)
55
+ def self.collection(object_class_or_factory, from = 0, size = nil, dao_registry_loader = nil)
56
56
  size ||= ArtirixDataModels.configuration.try(:search_page_size).try(:default) || 10
57
- new ->(data_collection) { ArtirixDataModels::EsCollection.new object_class_or_factory, response: data_collection, from: from, size: size }
57
+ new ->(data_collection) {
58
+ ArtirixDataModels::EsCollection.new object_class_or_factory,
59
+ response: data_collection,
60
+ from: from,
61
+ size: size,
62
+ dao_registry_loader: dao_registry_loader
63
+ }
58
64
  end
59
65
 
60
66
  def self.with_block(&block)
@@ -324,6 +324,15 @@ module ArtirixDataModels
324
324
  module WithDAO
325
325
  extend ActiveSupport::Concern
326
326
 
327
+ included do
328
+ include ArtirixDataModels::WithDAORegistry
329
+ end
330
+
331
+ def initialize(dao_registry: nil, dao_registry_loader: nil, **properties)
332
+ set_dao_registry_and_loader dao_registry_loader, dao_registry
333
+ _set_properties properties
334
+ end
335
+
327
336
  def model_dao_name
328
337
  dao.model_name
329
338
  end
@@ -339,8 +348,8 @@ module ArtirixDataModels
339
348
 
340
349
  def load_dao
341
350
  key = self.class.dao_name
342
- raise UndefinedDAOError unless key.present?
343
- ArtirixDataModels::DAORegistry.send(key)
351
+ raise UndefinedDAOError, "`dao_name` not defined for #{self.class}" unless key.present?
352
+ dao_registry.get(key)
344
353
  end
345
354
 
346
355
  module ClassMethods
@@ -1,3 +1,3 @@
1
1
  module ArtirixDataModels
2
- VERSION = '0.22.1'
2
+ VERSION = '0.23.0'
3
3
  end
@@ -0,0 +1,73 @@
1
+ module ArtirixDataModels::WithDAORegistry
2
+ DEFAULT_DAO_REGISTRY_LOADER = ->() { ArtirixDataModels::DAORegistry.instance }
3
+
4
+ def self.loader_or_registry_or_default(dao_registry: nil, dao_registry_loader: nil)
5
+ raise ArgumentError, 'loader has to respond to :call' if dao_registry_loader.present? && !dao_registry_loader.respond_to?(:call)
6
+
7
+ if dao_registry_loader.respond_to? :call
8
+ dao_registry_loader.call
9
+ elsif dao_registry
10
+ dao_registry
11
+ else
12
+ DEFAULT_DAO_REGISTRY_LOADER.call
13
+ end
14
+ end
15
+
16
+ # set_xxx* methods can be chained (return self)
17
+ # xxx= methods return the value set
18
+
19
+ def dao_registry
20
+ dao_registry_loader.call
21
+ end
22
+
23
+ def dao_registry_loader
24
+ @dao_registry_loader || DEFAULT_DAO_REGISTRY_LOADER
25
+ end
26
+
27
+ attr_writer :dao_registry_loader
28
+
29
+ def set_dao_registry_loader(dao_registry_loader)
30
+ self.dao_registry_loader = dao_registry_loader
31
+ self
32
+ end
33
+
34
+ def dao_registry=(dao_registry)
35
+ if dao_registry
36
+ set_dao_registry_loader ->() { dao_registry }
37
+ else
38
+ set_default_dao_registry_loader
39
+ end
40
+
41
+ dao_registry
42
+ end
43
+
44
+ def set_dao_registry(dao_registry)
45
+ self.dao_registry = dao_registry
46
+ self
47
+ end
48
+
49
+ def default_dao_registry
50
+ DEFAULT_DAO_REGISTRY_LOADER.call
51
+ end
52
+
53
+ def set_default_dao_registry_loader
54
+ @dao_registry_loader = nil
55
+ self
56
+ end
57
+
58
+ alias_method :set_default_dao_registry, :set_default_dao_registry_loader
59
+
60
+ # will use the loader if present, if not it will use the registry, if not present it will do nothing.
61
+ def set_dao_registry_and_loader(dao_registry_loader, dao_registry)
62
+ raise ArgumentError, 'loader has to respond to :call' if dao_registry_loader.present? && !dao_registry_loader.respond_to?(:call)
63
+
64
+ if dao_registry_loader.respond_to? :call
65
+ set_dao_registry_loader dao_registry_loader
66
+ elsif dao_registry
67
+ set_dao_registry dao_registry
68
+ end
69
+
70
+ self
71
+ end
72
+
73
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: artirix_data_models
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.22.1
4
+ version: 0.23.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eduardo Turiño
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-01 00:00:00.000000000 Z
11
+ date: 2016-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -239,6 +239,7 @@ email:
239
239
  - eturino@artirix.com
240
240
  executables:
241
241
  - console
242
+ - rake
242
243
  - setup
243
244
  extensions: []
244
245
  extra_rdoc_files: []
@@ -252,6 +253,7 @@ files:
252
253
  - Rakefile
253
254
  - artirix_data_models.gemspec
254
255
  - bin/console
256
+ - bin/rake
255
257
  - bin/setup
256
258
  - lib/artirix_data_models.rb
257
259
  - lib/artirix_data_models/active_null.rb
@@ -284,6 +286,7 @@ files:
284
286
  - lib/artirix_data_models/spec_support/shared_examples/an_artirix_data_model_model.rb
285
287
  - lib/artirix_data_models/spec_support/shared_examples/has_attributes.rb
286
288
  - lib/artirix_data_models/version.rb
289
+ - lib/artirix_data_models/with_dao_registry.rb
287
290
  - spec/artirix_data_models/dao_registry_spec.rb
288
291
  - spec/artirix_data_models/es_collection_spec.rb
289
292
  - spec/artirix_data_models/gateways/data_gateway_spec.rb