guacamole 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/{config/rubocop.yml → .hound.yml} +1 -12
- data/.ruby-version +1 -1
- data/.travis.yml +2 -0
- data/.yardopts +1 -0
- data/CONTRIBUTING.md +3 -3
- data/Gemfile.devtools +24 -12
- data/Guardfile +1 -1
- data/README.md +347 -50
- data/Rakefile +10 -0
- data/config/reek.yml +18 -5
- data/guacamole.gemspec +5 -2
- data/lib/guacamole.rb +1 -0
- data/lib/guacamole/collection.rb +79 -7
- data/lib/guacamole/configuration.rb +56 -2
- data/lib/guacamole/document_model_mapper.rb +87 -7
- data/lib/guacamole/identity_map.rb +124 -0
- data/lib/guacamole/proxies/proxy.rb +42 -0
- data/lib/guacamole/proxies/referenced_by.rb +15 -0
- data/lib/guacamole/proxies/references.rb +15 -0
- data/lib/guacamole/query.rb +11 -0
- data/lib/guacamole/railtie.rb +6 -1
- data/lib/guacamole/railtie/database.rake +57 -3
- data/lib/guacamole/tasks/database.rake +23 -0
- data/lib/guacamole/version.rb +1 -1
- data/lib/rails/generators/guacamole/collection/collection_generator.rb +19 -0
- data/lib/rails/generators/guacamole/collection/templates/collection.rb.tt +5 -0
- data/lib/rails/generators/guacamole/config/config_generator.rb +25 -0
- data/lib/rails/generators/guacamole/config/templates/guacamole.yml +15 -0
- data/lib/rails/generators/guacamole/model/model_generator.rb +25 -0
- data/lib/rails/generators/guacamole/model/templates/model.rb.tt +11 -0
- data/lib/rails/generators/guacamole_generator.rb +28 -0
- data/lib/rails/generators/rails/collection/collection_generator.rb +13 -0
- data/lib/rails/generators/rspec/collection/collection_generator.rb +13 -0
- data/lib/rails/generators/rspec/collection/templates/collection_spec.rb.tt +7 -0
- data/spec/acceptance/association_spec.rb +40 -0
- data/spec/acceptance/basic_spec.rb +19 -2
- data/spec/acceptance/spec_helper.rb +5 -2
- data/spec/fabricators/author.rb +11 -0
- data/spec/fabricators/author_fabricator.rb +7 -0
- data/spec/fabricators/book.rb +11 -0
- data/spec/fabricators/book_fabricator.rb +5 -0
- data/spec/unit/collection_spec.rb +265 -18
- data/spec/unit/configuration_spec.rb +11 -1
- data/spec/unit/document_model_mapper_spec.rb +127 -5
- data/spec/unit/identiy_map_spec.rb +140 -0
- data/spec/unit/query_spec.rb +37 -16
- data/tasks/adjustments.rake +0 -1
- metadata +78 -8
data/Rakefile
CHANGED
@@ -5,3 +5,13 @@ require 'devtools'
|
|
5
5
|
Devtools.init_rake_tasks
|
6
6
|
|
7
7
|
import('./tasks/adjustments.rake')
|
8
|
+
|
9
|
+
desc 'Start a REPL with guacamole loaded (not the Rails part)'
|
10
|
+
task :console do
|
11
|
+
require 'bundler/setup'
|
12
|
+
|
13
|
+
require 'pry'
|
14
|
+
require 'guacamole'
|
15
|
+
ARGV.clear
|
16
|
+
Pry.start
|
17
|
+
end
|
data/config/reek.yml
CHANGED
@@ -4,7 +4,8 @@ Attribute:
|
|
4
4
|
exclude: []
|
5
5
|
BooleanParameter:
|
6
6
|
enabled: true
|
7
|
-
exclude:
|
7
|
+
exclude:
|
8
|
+
- respond_to_missing?
|
8
9
|
ClassVariable:
|
9
10
|
enabled: true
|
10
11
|
exclude: []
|
@@ -18,7 +19,10 @@ DataClump:
|
|
18
19
|
min_clump_size: 2
|
19
20
|
DuplicateMethodCall:
|
20
21
|
enabled: true
|
21
|
-
exclude:
|
22
|
+
exclude:
|
23
|
+
- Guacamole::DocumentModelMapper#document_to_model
|
24
|
+
- Guacamole::DocumentModelMapper#model_to_document
|
25
|
+
- Guacamole::Configuration#_add_missing_methods_to_database
|
22
26
|
max_calls: 1
|
23
27
|
allow_calls: []
|
24
28
|
FeatureEnvy:
|
@@ -26,7 +30,8 @@ FeatureEnvy:
|
|
26
30
|
exclude: []
|
27
31
|
IrresponsibleModule:
|
28
32
|
enabled: true
|
29
|
-
exclude:
|
33
|
+
exclude:
|
34
|
+
- - !ruby/regexp /Generators/
|
30
35
|
LongParameterList:
|
31
36
|
enabled: true
|
32
37
|
exclude: []
|
@@ -40,7 +45,8 @@ LongYieldList:
|
|
40
45
|
max_params: 2
|
41
46
|
NestedIterators:
|
42
47
|
enabled: true
|
43
|
-
exclude:
|
48
|
+
exclude:
|
49
|
+
- Guacamole::Configuration#_add_missing_methods_to_database
|
44
50
|
max_allowed_nesting: 2
|
45
51
|
ignore_iterators: []
|
46
52
|
NilCheck:
|
@@ -52,7 +58,8 @@ RepeatedConditional:
|
|
52
58
|
max_ifs: 2
|
53
59
|
TooManyInstanceVariables:
|
54
60
|
enabled: true
|
55
|
-
exclude:
|
61
|
+
exclude:
|
62
|
+
- Guacamole::DocumentModelMapper
|
56
63
|
max_instance_variables: 3
|
57
64
|
TooManyMethods:
|
58
65
|
enabled: true
|
@@ -62,6 +69,12 @@ TooManyStatements:
|
|
62
69
|
enabled: true
|
63
70
|
exclude:
|
64
71
|
- each
|
72
|
+
- Guacamole::DocumentModelMapper#document_to_model
|
73
|
+
- Guacamole::DocumentModelMapper#model_to_document
|
74
|
+
- Guacamole::Collection::ClassMethods#create_document_from
|
75
|
+
- Guacamole::Collection::ClassMethods#create_referenced_by_models_of
|
76
|
+
- Guacamole::Configuration#_add_missing_methods_to_database
|
77
|
+
- Guacamole::Configuration#create_database_connection_from
|
65
78
|
max_statements: 5
|
66
79
|
UncommunicativeMethodName:
|
67
80
|
enabled: true
|
data/guacamole.gemspec
CHANGED
@@ -18,11 +18,14 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(spec)/})
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.add_dependency 'ashikawa-core', '~> 0.
|
22
|
-
spec.add_dependency 'virtus', '~> 1.0.
|
21
|
+
spec.add_dependency 'ashikawa-core', '~> 0.10.0'
|
22
|
+
spec.add_dependency 'virtus', '~> 1.0.1'
|
23
23
|
spec.add_dependency 'activesupport', '>= 4.0.0'
|
24
24
|
spec.add_dependency 'activemodel', '>= 4.0.0'
|
25
|
+
spec.add_dependency 'hamster', '~> 1.0.1.pre.rc.1'
|
25
26
|
|
26
27
|
spec.add_development_dependency 'fabrication', '~> 2.8.1'
|
28
|
+
spec.add_development_dependency 'faker', '~> 1.2.0'
|
27
29
|
spec.add_development_dependency 'logging', '~> 1.8.1'
|
30
|
+
spec.add_development_dependency 'pry', '~> 0.9.12'
|
28
31
|
end
|
data/lib/guacamole.rb
CHANGED
data/lib/guacamole/collection.rb
CHANGED
@@ -16,7 +16,6 @@ module Guacamole
|
|
16
16
|
# the collection. See the `ClassMethods` submodule for details
|
17
17
|
module Collection
|
18
18
|
extend ActiveSupport::Concern
|
19
|
-
|
20
19
|
# The class methods added to the class via the mixin
|
21
20
|
#
|
22
21
|
# @!method model_to_document(model)
|
@@ -51,6 +50,9 @@ module Guacamole
|
|
51
50
|
# You can use this method for low level communication with the collection.
|
52
51
|
# Details can be found in the Ashikawa::Core documentation.
|
53
52
|
#
|
53
|
+
# @note We're well aware that we return a Ashikawa::Core::Collection here
|
54
|
+
# but naming it a connection. We think the name `connection` still
|
55
|
+
# fits better in this context.
|
54
56
|
# @see http://rubydoc.info/gems/ashikawa-core/Ashikawa/Core/Collection
|
55
57
|
# @return [Ashikawa::Core::Collection]
|
56
58
|
def connection
|
@@ -96,6 +98,31 @@ module Guacamole
|
|
96
98
|
mapper.document_to_model connection.fetch(key)
|
97
99
|
end
|
98
100
|
|
101
|
+
# Persist a model in the collection or replace it in the database, depending if it is already persisted
|
102
|
+
#
|
103
|
+
# * If {Model#persisted? model#persisted?} is `false`, the model will be saved in the collection.
|
104
|
+
# Timestamps, revision and key will be set on the model.
|
105
|
+
# * If {Model#persisted? model#persisted?} is `true`, it replaces the currently saved version of the model with
|
106
|
+
# its new version. It searches for the entry in the database
|
107
|
+
# by key. This will change the updated_at timestamp and revision
|
108
|
+
# of the provided model.
|
109
|
+
#
|
110
|
+
# See also {#create create} and {#replace replace} for explicit usage.
|
111
|
+
#
|
112
|
+
# @param [Model] model The model to be saved
|
113
|
+
# @return [Model] The provided model
|
114
|
+
# @example Save a podcast to the database
|
115
|
+
# podcast = Podcast.new(title: 'Best Show', guest: 'Dirk Breuer')
|
116
|
+
# PodcastsCollection.save(podcast)
|
117
|
+
# podcast.key #=> '27214247'
|
118
|
+
# @example Get a podcast, update its title, replace it
|
119
|
+
# podcast = PodcastsCollection.by_key('27214247')
|
120
|
+
# podcast.title = 'Even better'
|
121
|
+
# PodcastsCollection.save(podcast)
|
122
|
+
def save(model)
|
123
|
+
model.persisted? ? replace(model) : create(model)
|
124
|
+
end
|
125
|
+
|
99
126
|
# Persist a model in the collection
|
100
127
|
#
|
101
128
|
# The model will be saved in the collection. Timestamps, revision
|
@@ -107,7 +134,7 @@ module Guacamole
|
|
107
134
|
# podcast = Podcast.new(title: 'Best Show', guest: 'Dirk Breuer')
|
108
135
|
# PodcastsCollection.save(podcast)
|
109
136
|
# podcast.key #=> '27214247'
|
110
|
-
def
|
137
|
+
def create(model)
|
111
138
|
return false unless model.valid?
|
112
139
|
|
113
140
|
add_timestamps_to_model(model)
|
@@ -125,10 +152,10 @@ module Guacamole
|
|
125
152
|
# PodcastsCollection.delete(podcast)
|
126
153
|
def delete(model_or_key)
|
127
154
|
key = if model_or_key.respond_to? :key
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
155
|
+
model_or_key.key
|
156
|
+
else
|
157
|
+
model_or_key
|
158
|
+
end
|
132
159
|
fetch_document(key).delete
|
133
160
|
key
|
134
161
|
end
|
@@ -220,18 +247,64 @@ module Guacamole
|
|
220
247
|
# Create a document from a model
|
221
248
|
#
|
222
249
|
# @api private
|
250
|
+
# @todo Currently we only save the associated models if those never have been
|
251
|
+
# persisted. In future versions we should add something like `:autosave`
|
252
|
+
# to always save associated models.
|
223
253
|
def create_document_from(model)
|
254
|
+
create_referenced_models_of model
|
255
|
+
|
224
256
|
document = connection.create_document(model_to_document(model))
|
225
257
|
|
226
258
|
model.key = document.key
|
227
259
|
model.rev = document.revision
|
228
260
|
|
261
|
+
create_referenced_by_models_of model
|
262
|
+
|
229
263
|
document
|
230
264
|
end
|
231
265
|
|
266
|
+
# Creates all not yet persisted referenced models of `model`
|
267
|
+
#
|
268
|
+
# Referenced models needs to be created before the parent model, because it needs their `key`
|
269
|
+
#
|
270
|
+
# @api private
|
271
|
+
# @todo This method should be considered 'work in progress'. We already know we need to change this.
|
272
|
+
# @return [void]
|
273
|
+
def create_referenced_models_of(model)
|
274
|
+
mapper.referenced_models.each do |ref_model_name|
|
275
|
+
ref_collection = mapper.collection_for(ref_model_name)
|
276
|
+
|
277
|
+
ref_model = model.send(ref_model_name)
|
278
|
+
next unless ref_model
|
279
|
+
|
280
|
+
ref_collection.save ref_model unless ref_model.persisted?
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
# Creates all not yet persisted models which are referenced by `model`
|
285
|
+
#
|
286
|
+
# Referenced by models needs to created after the parent model, because they need its `key`
|
287
|
+
#
|
288
|
+
# @api private
|
289
|
+
# @todo This method should be considered 'work in progress'. We already know we need to change this.
|
290
|
+
# @return [void]
|
291
|
+
def create_referenced_by_models_of(model)
|
292
|
+
mapper.referenced_by_models.each do |ref_model_name|
|
293
|
+
ref_collection = mapper.collection_for(ref_model_name)
|
294
|
+
|
295
|
+
ref_models = model.send(ref_model_name)
|
296
|
+
|
297
|
+
ref_models.each do |ref_model|
|
298
|
+
ref_model.send("#{model.class.name.demodulize.underscore}=", model)
|
299
|
+
ref_collection.save ref_model unless ref_model.persisted?
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
232
304
|
# Replace a document in the database with this model
|
233
305
|
#
|
234
306
|
# @api private
|
307
|
+
# @note This will **not** update associated models (see {#create})
|
235
308
|
def replace_document_from(model)
|
236
309
|
document = model_to_document(model)
|
237
310
|
response = connection.replace(model.key, document)
|
@@ -240,7 +313,6 @@ module Guacamole
|
|
240
313
|
|
241
314
|
document
|
242
315
|
end
|
243
|
-
|
244
316
|
end
|
245
317
|
end
|
246
318
|
end
|
@@ -4,11 +4,11 @@ require 'logger'
|
|
4
4
|
require 'forwardable'
|
5
5
|
require 'ashikawa-core'
|
6
6
|
require 'active_support/core_ext'
|
7
|
+
require 'yaml'
|
7
8
|
|
8
9
|
require 'guacamole/document_model_mapper'
|
9
10
|
|
10
11
|
module Guacamole
|
11
|
-
|
12
12
|
class << self
|
13
13
|
# Configure Guacamole
|
14
14
|
#
|
@@ -26,6 +26,13 @@ module Guacamole
|
|
26
26
|
def configuration
|
27
27
|
@configuration ||= Configuration
|
28
28
|
end
|
29
|
+
|
30
|
+
# Just an alias to Configuration#logger
|
31
|
+
#
|
32
|
+
# @return [Configuration#logger]
|
33
|
+
def logger
|
34
|
+
configuration.logger
|
35
|
+
end
|
29
36
|
end
|
30
37
|
|
31
38
|
# Current configuration
|
@@ -97,12 +104,16 @@ module Guacamole
|
|
97
104
|
end
|
98
105
|
|
99
106
|
def create_database_connection_from(config)
|
100
|
-
Ashikawa::Core::Database.new do |arango_config|
|
107
|
+
database = Ashikawa::Core::Database.new do |arango_config|
|
101
108
|
arango_config.url = db_url_from(config)
|
102
109
|
arango_config.username = config['username']
|
103
110
|
arango_config.password = config['password']
|
104
111
|
arango_config.logger = logger
|
105
112
|
end
|
113
|
+
|
114
|
+
_add_missing_methods_to_database(database)
|
115
|
+
|
116
|
+
database
|
106
117
|
end
|
107
118
|
|
108
119
|
def db_url_from(config)
|
@@ -118,6 +129,49 @@ module Guacamole
|
|
118
129
|
default_logger.level = Logger::INFO
|
119
130
|
default_logger
|
120
131
|
end
|
132
|
+
|
133
|
+
# FIXME: This is not here to stay! Kill it with fire!
|
134
|
+
#
|
135
|
+
# As soon Ashikawa::Core provides those features
|
136
|
+
# (https://github.com/triAGENS/ashikawa-core/issues/83) immediately
|
137
|
+
# remove this hack. But while this is ugly as hell it ensures we don't
|
138
|
+
# need to change any other related code. Just remove this and we're good.
|
139
|
+
def _add_missing_methods_to_database(database)
|
140
|
+
database.singleton_class.instance_eval do
|
141
|
+
# The raw Faraday connection
|
142
|
+
define_method(:raw_connection) do
|
143
|
+
@connection.connection
|
144
|
+
end
|
145
|
+
|
146
|
+
# The base URI to the ArangoDB server
|
147
|
+
define_method(:arangodb_uri) do |additional_path = ''|
|
148
|
+
uri = raw_connection.url_prefix
|
149
|
+
base_uri = [uri.scheme, '://', uri.host, ':', uri.port].join
|
150
|
+
URI.join(base_uri, additional_path)
|
151
|
+
end
|
152
|
+
|
153
|
+
# Database name query method
|
154
|
+
define_method(:name) do
|
155
|
+
database_regexp = %r{_db/(?<db_name>\w+)/_api}
|
156
|
+
raw_connection.url_prefix.to_s.match(database_regexp)['db_name']
|
157
|
+
end
|
158
|
+
|
159
|
+
# Creates the database
|
160
|
+
define_method(:create) do
|
161
|
+
raw_connection.post(arangodb_uri('/_api/database'), name: name)
|
162
|
+
end
|
163
|
+
|
164
|
+
# Drops the database
|
165
|
+
define_method(:drop) do
|
166
|
+
raw_connection.delete(arangodb_uri("/_api/database/#{name}"))
|
167
|
+
end
|
168
|
+
|
169
|
+
# Truncate the database
|
170
|
+
define_method(:truncate) do
|
171
|
+
collections.each { |collection| collection.truncate! }
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
121
175
|
end
|
122
176
|
end
|
123
177
|
end
|
@@ -1,11 +1,16 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
|
3
|
+
require 'guacamole/proxies/referenced_by'
|
4
|
+
require 'guacamole/proxies/references'
|
5
|
+
|
3
6
|
module Guacamole
|
4
7
|
# This is the default mapper class to map between Ashikawa::Core::Document and
|
5
8
|
# Guacamole::Model instances.
|
6
9
|
#
|
7
10
|
# If you want to build your own mapper, you have to build at least the
|
8
11
|
# `document_to_model` and `model_to_document` methods.
|
12
|
+
#
|
13
|
+
# @note If you plan to bring your own `DocumentModelMapper` please consider using an {Guacamole::IdentityMap}.
|
9
14
|
class DocumentModelMapper
|
10
15
|
# The class to map to
|
11
16
|
#
|
@@ -16,6 +21,8 @@ module Guacamole
|
|
16
21
|
#
|
17
22
|
# @return [Array] An array of embedded models
|
18
23
|
attr_reader :models_to_embed
|
24
|
+
attr_reader :referenced_by_models
|
25
|
+
attr_reader :referenced_models
|
19
26
|
|
20
27
|
# Create a new instance of the mapper
|
21
28
|
#
|
@@ -23,9 +30,42 @@ module Guacamole
|
|
23
30
|
# The Document class is always Ashikawa::Core::Document
|
24
31
|
#
|
25
32
|
# @param [Class] model_class
|
26
|
-
def initialize(model_class)
|
27
|
-
@model_class
|
28
|
-
@
|
33
|
+
def initialize(model_class, identity_map = IdentityMap)
|
34
|
+
@model_class = model_class
|
35
|
+
@identity_map = identity_map
|
36
|
+
@models_to_embed = []
|
37
|
+
@referenced_by_models = []
|
38
|
+
@referenced_models = []
|
39
|
+
end
|
40
|
+
|
41
|
+
class << self
|
42
|
+
# construct the {collection} class for a given model name.
|
43
|
+
#
|
44
|
+
# @example
|
45
|
+
# collection_class = collection_for(:user)
|
46
|
+
# collection_class == userscollection # would be true
|
47
|
+
#
|
48
|
+
# @note This is an class level alias for {DocumentModelMapper#collection_for}
|
49
|
+
# @param [symbol, string] model_name the name of the model
|
50
|
+
# @return [class] the {collection} class for the given model name
|
51
|
+
def collection_for(model_name)
|
52
|
+
"#{model_name.to_s.classify.pluralize}Collection".constantize
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# construct the {collection} class for a given model name.
|
57
|
+
#
|
58
|
+
# @example
|
59
|
+
# collection_class = collection_for(:user)
|
60
|
+
# collection_class == userscollection # would be true
|
61
|
+
#
|
62
|
+
# @todo As of now this is some kind of placeholder method. As soon as we implement
|
63
|
+
# the configuration of the mapping (#12) this will change. Still the {DocumentModelMapper}
|
64
|
+
# seems to be a good place for this functionality.
|
65
|
+
# @param [symbol, string] model_name the name of the model
|
66
|
+
# @return [class] the {collection} class for the given model name
|
67
|
+
def collection_for(model_name)
|
68
|
+
self.class.collection_for model_name
|
29
69
|
end
|
30
70
|
|
31
71
|
# Map a document to a model
|
@@ -34,14 +74,26 @@ module Guacamole
|
|
34
74
|
#
|
35
75
|
# @param [Ashikawa::Core::Document] document
|
36
76
|
# @return [Model] the resulting model with the given Model class
|
77
|
+
# rubocop:disable MethodLength
|
37
78
|
def document_to_model(document)
|
38
|
-
|
79
|
+
identity_map.retrieve_or_store model_class, document.key do
|
80
|
+
model = model_class.new(document.to_h)
|
81
|
+
|
82
|
+
referenced_by_models.each do |ref_model_name|
|
83
|
+
model.send("#{ref_model_name}=", Proxies::ReferencedBy.new(ref_model_name, model))
|
84
|
+
end
|
85
|
+
|
86
|
+
referenced_models.each do |ref_model_name|
|
87
|
+
model.send("#{ref_model_name}=", Proxies::References.new(ref_model_name, document))
|
88
|
+
end
|
39
89
|
|
40
|
-
|
41
|
-
|
90
|
+
model.key = document.key
|
91
|
+
model.rev = document.revision
|
42
92
|
|
43
|
-
|
93
|
+
model
|
94
|
+
end
|
44
95
|
end
|
96
|
+
# rubocop:enable MethodLength
|
45
97
|
|
46
98
|
# Map a model to a document
|
47
99
|
#
|
@@ -49,6 +101,7 @@ module Guacamole
|
|
49
101
|
#
|
50
102
|
# @param [Model] model
|
51
103
|
# @return [Ashikawa::Core::Document] the resulting document
|
104
|
+
# rubocop:disable MethodLength
|
52
105
|
def model_to_document(model)
|
53
106
|
document = model.attributes.dup.except(:key, :rev)
|
54
107
|
models_to_embed.each do |attribute_name|
|
@@ -56,8 +109,21 @@ module Guacamole
|
|
56
109
|
embedded_model.attributes.except(:key, :rev)
|
57
110
|
end
|
58
111
|
end
|
112
|
+
|
113
|
+
referenced_models.each do |ref_model_name|
|
114
|
+
ref_key = [ref_model_name.to_s, 'id'].join('_').to_sym
|
115
|
+
ref_model = model.send ref_model_name
|
116
|
+
document[ref_key] = ref_model.key if ref_model
|
117
|
+
document.delete(ref_model_name)
|
118
|
+
end
|
119
|
+
|
120
|
+
referenced_by_models.each do |ref_model_name|
|
121
|
+
document.delete(ref_model_name)
|
122
|
+
end
|
123
|
+
|
59
124
|
document
|
60
125
|
end
|
126
|
+
# rubocop:enable MethodLength
|
61
127
|
|
62
128
|
# Declare a model to be embedded
|
63
129
|
#
|
@@ -91,5 +157,19 @@ module Guacamole
|
|
91
157
|
def embeds(model_name)
|
92
158
|
@models_to_embed << model_name
|
93
159
|
end
|
160
|
+
|
161
|
+
def referenced_by(model_name)
|
162
|
+
@referenced_by_models << model_name
|
163
|
+
end
|
164
|
+
|
165
|
+
def references(model_name)
|
166
|
+
@referenced_models << model_name
|
167
|
+
end
|
168
|
+
|
169
|
+
private
|
170
|
+
|
171
|
+
def identity_map
|
172
|
+
@identity_map
|
173
|
+
end
|
94
174
|
end
|
95
175
|
end
|