all_futures 1.0.3 → 2.0.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.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -1
  3. data/Gemfile.lock +272 -61
  4. data/LICENSE.txt +1 -1
  5. data/README.md +59 -79
  6. data/Rakefile +13 -1
  7. data/SUMMARY.md +22 -2
  8. data/bin/console +8 -0
  9. data/bin/loc +0 -0
  10. data/bin/setup +0 -0
  11. data/bin/standardize +0 -0
  12. data/lib/all_futures/association.rb +42 -0
  13. data/lib/all_futures/association_index.rb +69 -0
  14. data/lib/all_futures/attributes.rb +28 -0
  15. data/lib/all_futures/base.rb +66 -0
  16. data/lib/all_futures/callbacks.rb +71 -0
  17. data/lib/all_futures/configuration.rb +9 -0
  18. data/lib/all_futures/dirty.rb +116 -0
  19. data/lib/all_futures/embeds.rb +40 -0
  20. data/lib/all_futures/errors.rb +37 -0
  21. data/lib/all_futures/finder.rb +214 -0
  22. data/lib/all_futures/locale/en.yml +49 -0
  23. data/lib/all_futures/persistence.rb +595 -0
  24. data/lib/all_futures/presenter.rb +35 -0
  25. data/lib/all_futures/railtie.rb +26 -0
  26. data/lib/all_futures/translation.rb +22 -0
  27. data/lib/all_futures/validations.rb +10 -0
  28. data/lib/all_futures/version.rb +3 -1
  29. data/lib/all_futures/versions.rb +80 -0
  30. data/lib/all_futures.rb +24 -1
  31. data/lib/vendor/ACTIVE_ENTITY_MIT-LICENSE +42 -0
  32. data/lib/vendor/README.md +8 -0
  33. data/lib/vendor/active_entity/aggregations.rb +277 -0
  34. data/lib/vendor/active_entity/associations/embeds/association.rb +134 -0
  35. data/lib/vendor/active_entity/associations/embeds/builder/association.rb +105 -0
  36. data/lib/vendor/active_entity/associations/embeds/builder/collection_association.rb +71 -0
  37. data/lib/vendor/active_entity/associations/embeds/builder/embedded_in.rb +38 -0
  38. data/lib/vendor/active_entity/associations/embeds/builder/embeds_many.rb +13 -0
  39. data/lib/vendor/active_entity/associations/embeds/builder/embeds_one.rb +16 -0
  40. data/lib/vendor/active_entity/associations/embeds/builder/singular_association.rb +28 -0
  41. data/lib/vendor/active_entity/associations/embeds/collection_association.rb +209 -0
  42. data/lib/vendor/active_entity/associations/embeds/collection_proxy.rb +310 -0
  43. data/lib/vendor/active_entity/associations/embeds/embedded_in_association.rb +31 -0
  44. data/lib/vendor/active_entity/associations/embeds/embeds_many_association.rb +15 -0
  45. data/lib/vendor/active_entity/associations/embeds/embeds_one_association.rb +26 -0
  46. data/lib/vendor/active_entity/associations/embeds/singular_association.rb +35 -0
  47. data/lib/vendor/active_entity/associations.rb +168 -0
  48. data/lib/vendor/active_entity/attribute_assignment.rb +87 -0
  49. data/lib/vendor/active_entity/attribute_decorators.rb +90 -0
  50. data/lib/vendor/active_entity/attribute_methods/before_type_cast.rb +78 -0
  51. data/lib/vendor/active_entity/attribute_methods/dirty.rb +180 -0
  52. data/lib/vendor/active_entity/attribute_methods/primary_key.rb +96 -0
  53. data/lib/vendor/active_entity/attribute_methods/query.rb +38 -0
  54. data/lib/vendor/active_entity/attribute_methods/read.rb +44 -0
  55. data/lib/vendor/active_entity/attribute_methods/serialization.rb +90 -0
  56. data/lib/vendor/active_entity/attribute_methods/time_zone_conversion.rb +93 -0
  57. data/lib/vendor/active_entity/attribute_methods/write.rb +54 -0
  58. data/lib/vendor/active_entity/attribute_methods.rb +833 -0
  59. data/lib/vendor/active_entity/attributes.rb +240 -0
  60. data/lib/vendor/active_entity/base.rb +293 -0
  61. data/lib/vendor/active_entity/callbacks.rb +21 -0
  62. data/lib/vendor/active_entity/coders/json.rb +15 -0
  63. data/lib/vendor/active_entity/coders/yaml_column.rb +50 -0
  64. data/lib/vendor/active_entity/core.rb +348 -0
  65. data/lib/vendor/active_entity/enum.rb +260 -0
  66. data/lib/vendor/active_entity/errors.rb +69 -0
  67. data/lib/vendor/active_entity/gem_version.rb +17 -0
  68. data/lib/vendor/active_entity/inheritance.rb +176 -0
  69. data/lib/vendor/active_entity/integration.rb +78 -0
  70. data/lib/vendor/active_entity/locale/en.yml +45 -0
  71. data/lib/vendor/active_entity/model_schema.rb +118 -0
  72. data/lib/vendor/active_entity/nested_attributes.rb +554 -0
  73. data/lib/vendor/active_entity/persistence.rb +20 -0
  74. data/lib/vendor/active_entity/railtie.rb +76 -0
  75. data/lib/vendor/active_entity/readonly_attributes.rb +55 -0
  76. data/lib/vendor/active_entity/reflection.rb +447 -0
  77. data/lib/vendor/active_entity/serialization.rb +28 -0
  78. data/lib/vendor/active_entity/store.rb +291 -0
  79. data/lib/vendor/active_entity/translation.rb +24 -0
  80. data/lib/vendor/active_entity/type/date.rb +9 -0
  81. data/lib/vendor/active_entity/type/date_time.rb +9 -0
  82. data/lib/vendor/active_entity/type/internal/timezone.rb +17 -0
  83. data/lib/vendor/active_entity/type/json.rb +30 -0
  84. data/lib/vendor/active_entity/type/modifiers/array.rb +72 -0
  85. data/lib/vendor/active_entity/type/modifiers/array_without_blank.rb +19 -0
  86. data/lib/vendor/active_entity/type/registry.rb +112 -0
  87. data/lib/vendor/active_entity/type/serialized.rb +71 -0
  88. data/lib/vendor/active_entity/type/text.rb +11 -0
  89. data/lib/vendor/active_entity/type/time.rb +21 -0
  90. data/lib/vendor/active_entity/type/unsigned_integer.rb +17 -0
  91. data/lib/vendor/active_entity/type.rb +75 -0
  92. data/lib/vendor/active_entity/validate_embeds_association.rb +300 -0
  93. data/lib/vendor/active_entity/validations/absence.rb +25 -0
  94. data/lib/vendor/active_entity/validations/associated.rb +60 -0
  95. data/lib/vendor/active_entity/validations/length.rb +26 -0
  96. data/lib/vendor/active_entity/validations/presence.rb +68 -0
  97. data/lib/vendor/active_entity/validations/subset.rb +76 -0
  98. data/lib/vendor/active_entity/validations/uniqueness_in_embeds.rb +91 -0
  99. data/lib/vendor/active_entity/validations/uniqueness_on_active_record.rb +234 -0
  100. data/lib/vendor/active_entity/validations.rb +47 -0
  101. data/lib/vendor/active_entity/version.rb +10 -0
  102. data/lib/vendor/active_entity.rb +99 -0
  103. data/lib/vendor/core_ext/array_without_blank.rb +48 -0
  104. metadata +175 -21
  105. data/lib/all_futures/all_futures.rb +0 -28
  106. data/lib/all_futures/config.rb +0 -14
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveEntity
4
+ module ReadonlyAttributes
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ class_attribute :_attr_readonly, instance_accessor: false, default: []
9
+ end
10
+
11
+ def disable_attr_readonly!
12
+ @_attr_readonly_enabled = false
13
+ end
14
+
15
+ def enable_attr_readonly!
16
+ @_attr_readonly_enabled = true
17
+ end
18
+
19
+ def without_attr_readonly
20
+ return unless block_given?
21
+
22
+ disable_attr_readonly!
23
+ yield self
24
+ enable_attr_readonly!
25
+
26
+ self
27
+ end
28
+
29
+ def _attr_readonly_enabled
30
+ @_attr_readonly_enabled
31
+ end
32
+ alias attr_readonly_enabled? _attr_readonly_enabled
33
+
34
+ def readonly_attribute?(name)
35
+ self.class.readonly_attribute?(name)
36
+ end
37
+
38
+ module ClassMethods
39
+ # Attributes listed as readonly will be used to create a new record but update operations will
40
+ # ignore these fields.
41
+ def attr_readonly(*attributes)
42
+ self._attr_readonly = Set.new(attributes.map(&:to_s)) + (_attr_readonly || [])
43
+ end
44
+
45
+ # Returns an array of all the attributes that have been specified as readonly.
46
+ def readonly_attributes
47
+ _attr_readonly
48
+ end
49
+
50
+ def readonly_attribute?(name) # :nodoc:
51
+ _attr_readonly.include?(name)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,447 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/string/filters"
4
+ require "concurrent/map"
5
+
6
+ module ActiveEntity
7
+ # = Active Entity Reflection
8
+ module Reflection # :nodoc:
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ class_attribute :_reflections, instance_writer: false, default: {}
13
+ class_attribute :aggregate_reflections, instance_writer: false, default: {}
14
+ end
15
+
16
+ class << self
17
+ def create(macro, name, scope, options, ar_or_ae)
18
+ reflection_class_for(macro).new(name, scope, options, ar_or_ae)
19
+
20
+ # TODO: Support bridge to Active Entity
21
+ # reflection = reflection_class_for(macro).new(name, scope, options, ar_or_ae)
22
+ # options[:through] ? ActiveRecord::ThroughReflection.new(reflection) : reflection
23
+ end
24
+
25
+ def add_reflection(ar_or_ae, name, reflection)
26
+ ar_or_ae.clear_reflections_cache
27
+ name = name.to_s
28
+ ar_or_ae._reflections = ar_or_ae._reflections.except(name).merge!(name => reflection)
29
+ end
30
+
31
+ def add_aggregate_reflection(ae, name, reflection)
32
+ ae.aggregate_reflections = ae.aggregate_reflections.merge(name.to_s => reflection)
33
+ end
34
+
35
+ private
36
+
37
+ def reflection_class_for(macro)
38
+ case macro
39
+ when :composed_of
40
+ AggregateReflection
41
+ when :embedded_in
42
+ EmbeddedInReflection
43
+ when :embeds_one
44
+ EmbedsOneReflection
45
+ when :embeds_many
46
+ EmbedsManyReflection
47
+ else
48
+ raise "Unsupported Macro: #{macro}"
49
+ end
50
+ end
51
+ end
52
+
53
+ # \Reflection enables the ability to examine the associations and aggregations of
54
+ # Active Entity classes and objects. This information, for example,
55
+ # can be used in a form builder that takes an Active Entity object
56
+ # and creates input fields for all of the attributes depending on their type
57
+ # and displays the associations to other objects.
58
+ #
59
+ # MacroReflection class has info for AggregateReflection and AssociationReflection
60
+ # classes.
61
+ module ClassMethods
62
+ # Returns an array of AggregateReflection objects for all the aggregations in the class.
63
+ def reflect_on_all_aggregations
64
+ aggregate_reflections.values
65
+ end
66
+
67
+ # Returns the AggregateReflection object for the named +aggregation+ (use the symbol).
68
+ #
69
+ # Account.reflect_on_aggregation(:balance) # => the balance AggregateReflection
70
+ #
71
+ def reflect_on_aggregation(aggregation)
72
+ aggregate_reflections[aggregation.to_s]
73
+ end
74
+
75
+ # Returns a Hash of name of the reflection as the key and an AssociationReflection as the value.
76
+ #
77
+ # Account.reflections # => {"balance" => AggregateReflection}
78
+ #
79
+ def reflections
80
+ @__reflections ||= begin
81
+ ref = {}
82
+
83
+ _reflections.each do |name, reflection|
84
+ parent_reflection = reflection.parent_reflection
85
+
86
+ if parent_reflection
87
+ parent_name = parent_reflection.name
88
+ ref[parent_name.to_s] = parent_reflection
89
+ else
90
+ ref[name] = reflection
91
+ end
92
+ end
93
+
94
+ ref
95
+ end
96
+ end
97
+
98
+ # Returns an array of AssociationReflection objects for all the
99
+ # associations in the class. If you only want to reflect on a certain
100
+ # association type, pass in the symbol (<tt>:has_many</tt>, <tt>:has_one</tt>,
101
+ # <tt>:belongs_to</tt>) as the first parameter.
102
+ #
103
+ # Example:
104
+ #
105
+ # Account.reflect_on_all_associations # returns an array of all associations
106
+ # Account.reflect_on_all_associations(:has_many) # returns an array of all has_many associations
107
+ #
108
+ def reflect_on_all_associations(macro = nil)
109
+ association_reflections = reflections.values
110
+ association_reflections.select! { |reflection| reflection.macro == macro } if macro
111
+ association_reflections
112
+ end
113
+
114
+ # Returns the AssociationReflection object for the +association+ (use the symbol).
115
+ #
116
+ # Account.reflect_on_association(:owner) # returns the owner AssociationReflection
117
+ # Invoice.reflect_on_association(:line_items).macro # returns :has_many
118
+ #
119
+ def reflect_on_association(association)
120
+ reflections[association.to_s]
121
+ end
122
+
123
+ def _reflect_on_association(association) #:nodoc:
124
+ _reflections[association.to_s]
125
+ end
126
+
127
+ def clear_reflections_cache # :nodoc:
128
+ @__reflections = nil
129
+ end
130
+ end
131
+
132
+ # Holds all the methods that are shared between MacroReflection and ThroughReflection.
133
+ #
134
+ # AbstractReflection
135
+ # MacroReflection
136
+ # AggregateReflection
137
+ # AssociationReflection
138
+ # HasManyReflection
139
+ # HasOneReflection
140
+ # BelongsToReflection
141
+ # HasAndBelongsToManyReflection
142
+ # ThroughReflection
143
+ # PolymorphicReflection
144
+ # RuntimeReflection
145
+
146
+ class AbstractReflection
147
+ def embedded?
148
+ false
149
+ end
150
+ end
151
+
152
+ class AbstractEmbeddedReflection < AbstractReflection # :nodoc:
153
+ def embedded?
154
+ true
155
+ end
156
+
157
+ def through_reflection?
158
+ false
159
+ end
160
+
161
+ # Returns a new, unsaved instance of the associated class. +attributes+ will
162
+ # be passed to the class's constructor.
163
+ def build_association(attributes, &block)
164
+ klass.new(attributes, &block)
165
+ end
166
+
167
+ # Returns the class name for the macro.
168
+ #
169
+ # <tt>composed_of :balance, class_name: 'Money'</tt> returns <tt>'Money'</tt>
170
+ # <tt>has_many :clients</tt> returns <tt>'Client'</tt>
171
+ def class_name
172
+ @class_name ||= (options[:class_name] || derive_class_name).to_s
173
+ end
174
+
175
+ def inverse_of
176
+ return unless inverse_name
177
+
178
+ @inverse_of ||= klass._reflect_on_association inverse_name
179
+ end
180
+
181
+ def check_validity_of_inverse!
182
+ if has_inverse? && inverse_of.nil?
183
+ raise InverseOfAssociationNotFoundError.new(self)
184
+ end
185
+ end
186
+
187
+ protected
188
+
189
+ def actual_source_reflection # FIXME: this is a horrible name
190
+ self
191
+ end
192
+ end
193
+
194
+ # Base class for AggregateReflection and AssociationReflection. Objects of
195
+ # AggregateReflection and AssociationReflection are returned by the Reflection::ClassMethods.
196
+ class MacroEmbeddedReflection < AbstractEmbeddedReflection
197
+ # Returns the name of the macro.
198
+ #
199
+ # <tt>composed_of :balance, class_name: 'Money'</tt> returns <tt>:balance</tt>
200
+ # <tt>has_many :clients</tt> returns <tt>:clients</tt>
201
+ attr_reader :name
202
+
203
+ # Returns the hash of options used for the macro.
204
+ #
205
+ # <tt>composed_of :balance, class_name: 'Money'</tt> returns <tt>{ class_name: "Money" }</tt>
206
+ # <tt>has_many :clients</tt> returns <tt>{}</tt>
207
+ attr_reader :options
208
+
209
+ attr_reader :active_entity
210
+
211
+ def initialize(name, scope, options, active_entity)
212
+ @name = name
213
+ @scope = scope
214
+ @options = options
215
+ @active_entity = active_entity
216
+ @klass = options[:anonymous_class]
217
+ end
218
+
219
+ # Returns the class for the macro.
220
+ #
221
+ # <tt>composed_of :balance, class_name: 'Money'</tt> returns the Money class
222
+ # <tt>has_many :clients</tt> returns the Client class
223
+ #
224
+ # class Company < ActiveEntity::Base
225
+ # has_many :clients
226
+ # end
227
+ #
228
+ # Company.reflect_on_association(:clients).klass
229
+ # # => Client
230
+ #
231
+ # <b>Note:</b> Do not call +klass.new+ or +klass.create+ to instantiate
232
+ # a new association object. Use +build_association+ or +create_association+
233
+ # instead. This allows plugins to hook into association object creation.
234
+ def klass
235
+ @klass ||= compute_class(class_name)
236
+ end
237
+
238
+ def compute_class(name)
239
+ name.constantize
240
+ end
241
+
242
+ # Returns +true+ if +self+ and +other_aggregation+ have the same +name+ attribute, +active_entity+ attribute,
243
+ # and +other_aggregation+ has an options hash assigned to it.
244
+ def ==(other_aggregation)
245
+ super ||
246
+ other_aggregation.kind_of?(self.class) &&
247
+ name == other_aggregation.name &&
248
+ !other_aggregation.options.nil? &&
249
+ active_entity == other_aggregation.active_entity
250
+ end
251
+
252
+ private
253
+
254
+ def derive_class_name
255
+ name.to_s.camelize
256
+ end
257
+ end
258
+
259
+ # Holds all the metadata about an aggregation as it was specified in the
260
+ # Active Entity class.
261
+ class AggregateReflection < MacroEmbeddedReflection #:nodoc:
262
+ def mapping
263
+ mapping = options[:mapping] || [name, name]
264
+ mapping.first.is_a?(Array) ? mapping : [mapping]
265
+ end
266
+ end
267
+
268
+ # Holds all the metadata about an association as it was specified in the
269
+ # Active Entity class.
270
+ class EmbeddedAssociationReflection < MacroEmbeddedReflection #:nodoc:
271
+ def compute_class(name)
272
+ active_entity.send(:compute_type, name)
273
+ end
274
+
275
+ attr_reader :type
276
+ attr_accessor :parent_reflection # Reflection
277
+
278
+ def initialize(name, scope, options, active_entity)
279
+ super
280
+ @constructable = calculate_constructable(macro, options)
281
+
282
+ if options[:class_name] && options[:class_name].class == Class
283
+ raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string."
284
+ end
285
+ end
286
+
287
+ def constructable? # :nodoc:
288
+ @constructable
289
+ end
290
+
291
+ def check_validity!
292
+ check_validity_of_inverse!
293
+ end
294
+
295
+ def nested?
296
+ false
297
+ end
298
+
299
+ def has_inverse?
300
+ inverse_name
301
+ end
302
+
303
+ # Returns the macro type.
304
+ #
305
+ # <tt>has_many :clients</tt> returns <tt>:has_many</tt>
306
+ def macro; raise NotImplementedError; end
307
+
308
+ # Returns whether or not this association reflection is for a collection
309
+ # association. Returns +true+ if the +macro+ is either +has_many+ or
310
+ # +has_and_belongs_to_many+, +false+ otherwise.
311
+ def collection?
312
+ false
313
+ end
314
+
315
+ # Returns whether or not the association should be validated as part of
316
+ # the parent's validation.
317
+ #
318
+ # Unless you explicitly disable validation with
319
+ # <tt>validate: false</tt>, validation will take place when:
320
+ #
321
+ # * you explicitly enable validation; <tt>validate: true</tt>
322
+ # * you use autosave; <tt>autosave: true</tt>
323
+ # * the association is a +has_many+ association
324
+ def validate?
325
+ !!options[:validate]
326
+ end
327
+
328
+ # Returns +true+ if +self+ is a +belongs_to+ reflection.
329
+ def embedded_in?; false; end
330
+
331
+ # Returns +true+ if +self+ is a +has_one+ reflection.
332
+ def embeds_one?; false; end
333
+
334
+ def association_class; raise NotImplementedError; end
335
+
336
+ VALID_AUTOMATIC_INVERSE_MACROS = [:embeds_many, :embeds_one, :embedded_in]
337
+
338
+ def extensions
339
+ Array(options[:extend])
340
+ end
341
+
342
+ private
343
+
344
+ def calculate_constructable(_macro, _options)
345
+ true
346
+ end
347
+
348
+ # Attempts to find the inverse association name automatically.
349
+ # If it cannot find a suitable inverse association name, it returns
350
+ # +nil+.
351
+ def inverse_name
352
+ unless defined?(@inverse_name)
353
+ @inverse_name = options.fetch(:inverse_of) { automatic_inverse_of }
354
+ end
355
+
356
+ @inverse_name
357
+ end
358
+
359
+ # returns either +nil+ or the inverse association name that it finds.
360
+ def automatic_inverse_of
361
+ return unless can_find_inverse_of_automatically?(self)
362
+
363
+ inverse_name_candidates =
364
+ begin
365
+ active_entity_name = active_entity.name.demodulize
366
+ [active_entity_name, ActiveSupport::Inflector.pluralize(active_entity_name)]
367
+ end
368
+
369
+ inverse_name_candidates.map! do |candidate|
370
+ ActiveSupport::Inflector.underscore(candidate).to_sym
371
+ end
372
+
373
+ inverse_name_candidates.detect do |inverse_name|
374
+ begin
375
+ reflection = klass._reflect_on_association(inverse_name)
376
+ rescue NameError
377
+ # Give up: we couldn't compute the klass type so we won't be able
378
+ # to find any associations either.
379
+ reflection = false
380
+ end
381
+
382
+ valid_inverse_reflection?(reflection)
383
+ end
384
+ end
385
+
386
+ # Checks if the inverse reflection that is returned from the
387
+ # +automatic_inverse_of+ method is a valid reflection. We must
388
+ # make sure that the reflection's active_entity name matches up
389
+ # with the current reflection's klass name.
390
+ def valid_inverse_reflection?(reflection)
391
+ reflection &&
392
+ klass <= reflection.active_entity &&
393
+ can_find_inverse_of_automatically?(reflection)
394
+ end
395
+
396
+ # Checks to see if the reflection doesn't have any options that prevent
397
+ # us from being able to guess the inverse automatically. First, the
398
+ # <tt>inverse_of</tt> option cannot be set to false. Second, we must
399
+ # have <tt>has_many</tt>, <tt>has_one</tt>, <tt>belongs_to</tt> associations.
400
+ # Third, we must not have options such as <tt>:foreign_key</tt>
401
+ # which prevent us from correctly guessing the inverse association.
402
+ #
403
+ # Anything with a scope can additionally ruin our attempt at finding an
404
+ # inverse, so we exclude reflections with scopes.
405
+ def can_find_inverse_of_automatically?(reflection)
406
+ reflection.options[:inverse_of] != false &&
407
+ VALID_AUTOMATIC_INVERSE_MACROS.include?(reflection.macro)
408
+ end
409
+
410
+ def derive_class_name
411
+ class_name = name.to_s
412
+ class_name = class_name.singularize if collection?
413
+ class_name.camelize
414
+ end
415
+ end
416
+
417
+ class EmbedsManyReflection < EmbeddedAssociationReflection # :nodoc:
418
+ def macro; :embeds_many; end
419
+
420
+ def collection?; true; end
421
+
422
+ def association_class
423
+ Associations::Embeds::EmbedsManyAssociation
424
+ end
425
+ end
426
+
427
+ class EmbedsOneReflection < EmbeddedAssociationReflection # :nodoc:
428
+ def macro; :embeds_one; end
429
+
430
+ def embeds_one?; true; end
431
+
432
+ def association_class
433
+ Associations::Embeds::EmbedsOneAssociation
434
+ end
435
+ end
436
+
437
+ class EmbeddedInReflection < EmbeddedAssociationReflection # :nodoc:
438
+ def macro; :embedded_in; end
439
+
440
+ def embedded_in?; true; end
441
+
442
+ def association_class
443
+ Associations::Embeds::EmbeddedInAssociation
444
+ end
445
+ end
446
+ end
447
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveEntity #:nodoc:
4
+ # = Active Entity \Serialization
5
+ module Serialization
6
+ extend ActiveSupport::Concern
7
+ include ActiveModel::Serializers::JSON
8
+
9
+ included do
10
+ self.include_root_in_json = false
11
+ end
12
+
13
+ def serializable_hash(options = nil)
14
+ options = options ? options.dup : {}
15
+
16
+ include_embeds = options.delete :include_embeds
17
+ if include_embeds
18
+ includes = Array.wrap(options[:include]).concat(self.class.embeds_association_names)
19
+ options[:include] ||= []
20
+ options[:include].concat includes
21
+ end
22
+
23
+ options[:except] = Array(options[:except]).map(&:to_s)
24
+
25
+ super(options)
26
+ end
27
+ end
28
+ end