guacamole 0.0.1 → 0.1.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/.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
|