axle_attributes 1.13.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.travis.yml +16 -0
- data/Gemfile +15 -0
- data/README.md +10 -0
- data/Rakefile +18 -0
- data/app/models/attribute_customization.rb +7 -0
- data/app/models/attribute_customization/local_cache.rb +28 -0
- data/app/models/attribute_mapping.rb +15 -0
- data/app/models/attribute_mapping/local_cache.rb +40 -0
- data/axle_attributes.gemspec +22 -0
- data/bin/rails +8 -0
- data/db/migrate/20131118042651_create_attribute_customizations.rb +16 -0
- data/db/migrate/20131121013237_create_attribute_mappings.rb +17 -0
- data/db/migrate/20151120160522_add_editable_to_attribute_customizations.rb +7 -0
- data/lib/axle_attributes.rb +30 -0
- data/lib/axle_attributes/child_definition.rb +42 -0
- data/lib/axle_attributes/conversions.rb +36 -0
- data/lib/axle_attributes/definition.rb +118 -0
- data/lib/axle_attributes/definition/callbacks.rb +34 -0
- data/lib/axle_attributes/definition/customization.rb +51 -0
- data/lib/axle_attributes/definition/formatted.rb +57 -0
- data/lib/axle_attributes/definition/indexed.rb +41 -0
- data/lib/axle_attributes/definition/mappings.rb +48 -0
- data/lib/axle_attributes/dumper.rb +54 -0
- data/lib/axle_attributes/engine.rb +4 -0
- data/lib/axle_attributes/format.rb +74 -0
- data/lib/axle_attributes/has_attributes.rb +104 -0
- data/lib/axle_attributes/has_attributes/json_reader.rb +87 -0
- data/lib/axle_attributes/model.rb +34 -0
- data/lib/axle_attributes/null_definition.rb +11 -0
- data/lib/axle_attributes/parent_definition.rb +37 -0
- data/lib/axle_attributes/provided.rb +67 -0
- data/lib/axle_attributes/regex.rb +4 -0
- data/lib/axle_attributes/segmented.rb +30 -0
- data/lib/axle_attributes/serializations.rb +147 -0
- data/lib/axle_attributes/serializations/builder/serialization.rb +83 -0
- data/lib/axle_attributes/serializations/builder/serialize_many.rb +17 -0
- data/lib/axle_attributes/serializations/builder/serialize_one.rb +7 -0
- data/lib/axle_attributes/serializations/reflection.rb +40 -0
- data/lib/axle_attributes/serializations/serialization.rb +88 -0
- data/lib/axle_attributes/serializations/serialize_many.rb +88 -0
- data/lib/axle_attributes/serializations/serialize_one.rb +34 -0
- data/lib/axle_attributes/serialized_child.rb +58 -0
- data/lib/axle_attributes/validations.rb +29 -0
- data/lib/axle_attributes/versioned.rb +21 -0
- data/test/dummy/README.rdoc +6 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/mailers/.keep +0 -0
- data/test/dummy/app/models/.keep +0 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +12 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +13 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +29 -0
- data/test/dummy/config/environments/production.rb +80 -0
- data/test/dummy/config/environments/test.rb +38 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +12 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +56 -0
- data/test/dummy/db/schema.rb +50 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/dummy/public/404.html +58 -0
- data/test/dummy/public/422.html +58 -0
- data/test/dummy/public/500.html +57 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/factories/all.rb +14 -0
- data/test/helper.rb +25 -0
- data/test/lib/child_definition_test.rb +43 -0
- data/test/lib/conversions_test.rb +39 -0
- data/test/lib/definition/customization_test.rb +36 -0
- data/test/lib/definition/formatted_test.rb +75 -0
- data/test/lib/definition/indexed_test.rb +57 -0
- data/test/lib/definition/mappings_test.rb +26 -0
- data/test/lib/definition_test.rb +84 -0
- data/test/lib/dumper_test.rb +38 -0
- data/test/lib/format_test.rb +64 -0
- data/test/lib/has_attributes/json_reader_test.rb +46 -0
- data/test/lib/has_attributes_test.rb +69 -0
- data/test/lib/model_test.rb +44 -0
- data/test/lib/null_definition_test.rb +27 -0
- data/test/lib/parent_definition_test.rb +75 -0
- data/test/lib/provided_test.rb +46 -0
- data/test/lib/segmented_test.rb +27 -0
- data/test/lib/serializations/reflection_test.rb +24 -0
- data/test/lib/serializations/serialize_many_test.rb +194 -0
- data/test/lib/serializations/serialize_one_test.rb +122 -0
- data/test/lib/serializations_test.rb +24 -0
- data/test/lib/serialized_child_test.rb +91 -0
- data/test/lib/timestamp_attributes_test.rb +14 -0
- data/test/lib/validations_test.rb +8 -0
- data/test/lib/versioned_test.rb +35 -0
- data/test/models/attribute_customization/local_cache_test.rb +16 -0
- data/test/models/attribute_customization_test.rb +8 -0
- data/test/models/attribute_mapping/local_cache_test.rb +31 -0
- data/test/models/attribute_mapping_test.rb +20 -0
- data/test/support/business.rb +22 -0
- data/test/support/pg.rb +9 -0
- data/test/support/vegetable.rb +8 -0
- metadata +215 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
module AxleAttributes
|
2
|
+
module HasAttributes
|
3
|
+
class JsonReader
|
4
|
+
# json = {
|
5
|
+
# {
|
6
|
+
# "location": {
|
7
|
+
# "street": {"type": "string"},
|
8
|
+
# "city": {"type": "string", "readonly": true}
|
9
|
+
# }
|
10
|
+
# "group2": {
|
11
|
+
# },
|
12
|
+
# ...
|
13
|
+
# },
|
14
|
+
# "contacts": {
|
15
|
+
# "type": "serialize_many",
|
16
|
+
# "attributes": {
|
17
|
+
# "first_name": {"type": "string"},
|
18
|
+
# "professional_title": {"type": "string"}
|
19
|
+
# }
|
20
|
+
# }
|
21
|
+
# }
|
22
|
+
#
|
23
|
+
# AxleAttributes::HasAttributes::JsonReader.read_definitions(Widget, json)
|
24
|
+
#
|
25
|
+
def self.read_definitions(model, json, options = {})
|
26
|
+
new(model, options).read_definitions(json)
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_reader :model
|
30
|
+
attr_reader :reader_options
|
31
|
+
def initialize(model, reader_options = {})
|
32
|
+
@model = model
|
33
|
+
@reader_options = reader_options
|
34
|
+
end
|
35
|
+
|
36
|
+
def read_definitions(json)
|
37
|
+
json = ActiveSupport::JSON.decode(json) unless json.is_a?(Hash)
|
38
|
+
|
39
|
+
json.each do |namespace, options|
|
40
|
+
if options['type']
|
41
|
+
read_serialization namespace, options
|
42
|
+
else
|
43
|
+
read_definition_group options
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def read_definition_group(definitions)
|
51
|
+
definitions.each do |attribute_name, options|
|
52
|
+
model.has_attribute attribute_name, normalize_options(options)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
SERIALIZATION_TYPES = %w(serialize_one serialize_many)
|
57
|
+
def read_serialization(serialization_name, options)
|
58
|
+
raise "unknown serialization #{options['type']}" unless SERIALIZATION_TYPES.include?(options['type'])
|
59
|
+
serialization_type = options['type']
|
60
|
+
serialization_attributes = options['attributes']
|
61
|
+
|
62
|
+
child_model = (options['class_name'] || serialization_name.classify).constantize
|
63
|
+
AxleAttributes::HasAttributes::JsonReader.read_definitions(child_model, {serialization_type => serialization_attributes}, reader_options)
|
64
|
+
reflection = model.send(serialization_type, serialization_name.to_sym, options.slice('class_name').symbolize_keys!)
|
65
|
+
end
|
66
|
+
|
67
|
+
SYMBOL_OPTIONS = [:type, :format, :index, :mmdb_name]
|
68
|
+
def normalize_options(options)
|
69
|
+
options.symbolize_keys!
|
70
|
+
|
71
|
+
SYMBOL_OPTIONS.each do |option_name|
|
72
|
+
if (value = options[option_name]).is_a?(String)
|
73
|
+
options[option_name] = value.to_sym
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
options.reverse_merge! default_options
|
78
|
+
|
79
|
+
options
|
80
|
+
end
|
81
|
+
|
82
|
+
def default_options
|
83
|
+
@default_options ||= (reader_options[:defaults] || {})
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module AxleAttributes
|
2
|
+
module Model
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
unless include?(ElasticRecord::Model)
|
7
|
+
include ElasticRecord::Model
|
8
|
+
end
|
9
|
+
|
10
|
+
include AxleAttributes::HasAttributes
|
11
|
+
self.has_attribute_definition_class = '::AxleAttributes::ParentDefinition'
|
12
|
+
add_core_axle_attributes! unless self.name.demodulize == 'Base'
|
13
|
+
|
14
|
+
include AxleAttributes::Provided
|
15
|
+
include AxleAttributes::Segmented
|
16
|
+
include AxleAttributes::Serializations
|
17
|
+
include AxleAttributes::Versioned
|
18
|
+
include AxleAttributes::Validations
|
19
|
+
end
|
20
|
+
|
21
|
+
module ClassMethods
|
22
|
+
def inherited(child)
|
23
|
+
super
|
24
|
+
child.add_core_axle_attributes!
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_core_axle_attributes!
|
28
|
+
has_attribute(:created_at, type: :time, index: true, editable: false) unless attributes['created_at']
|
29
|
+
has_attribute(:updated_at, type: :time, index: true, editable: false) unless attributes['updated_at']
|
30
|
+
has_attribute(:segment_id, type: :integer, index: true, editable: false) unless attributes['segment_id']
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module AxleAttributes
|
2
|
+
class ParentDefinition < ::AxleAttributes::Definition
|
3
|
+
setup do
|
4
|
+
setup_storage!
|
5
|
+
setup_index!
|
6
|
+
setup_versioning!
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def setup_storage!
|
12
|
+
if type
|
13
|
+
storage_options = case type
|
14
|
+
when :text
|
15
|
+
{type: :string}
|
16
|
+
else
|
17
|
+
options.slice(:type, :default)
|
18
|
+
end
|
19
|
+
|
20
|
+
model.attribute(name, storage_options)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def setup_index!
|
25
|
+
if mapping = index_mapping
|
26
|
+
model.elastic_index.mapping[:properties].merge!(name => mapping)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def setup_versioning!
|
31
|
+
if versioned?
|
32
|
+
model.add_versioned_attribute name
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module AxleAttributes
|
2
|
+
module Provided
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
include ActiveModel::AttributeMethods
|
5
|
+
|
6
|
+
included do
|
7
|
+
attribute_method_suffix '_provided?'
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def tracking_disabled?
|
12
|
+
Thread.current[:disable_provided_tracking]
|
13
|
+
end
|
14
|
+
|
15
|
+
def without_provided_tracking
|
16
|
+
Thread.current[:disable_provided_tracking] = true
|
17
|
+
yield
|
18
|
+
ensure
|
19
|
+
Thread.current[:disable_provided_tracking] = false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def provided
|
24
|
+
provided_set.to_a
|
25
|
+
end
|
26
|
+
|
27
|
+
def provided_set
|
28
|
+
@provided_set ||= Set.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def provided?(attr)
|
32
|
+
provided_set.include? attr
|
33
|
+
end
|
34
|
+
|
35
|
+
def save(*)
|
36
|
+
if status = super
|
37
|
+
provided_set.clear
|
38
|
+
end
|
39
|
+
status
|
40
|
+
end
|
41
|
+
|
42
|
+
# Attempts to <tt>save!</tt> the record and clears changed attributes if successful.
|
43
|
+
def save!(*)
|
44
|
+
super.tap do
|
45
|
+
provided_set.clear
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# <tt>reload</tt> the record and clears changed attributes.
|
50
|
+
def reload(*)
|
51
|
+
super.tap do
|
52
|
+
provided_set.clear
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
def attribute_provided?(attr)
|
58
|
+
provided_set.include?(attr)
|
59
|
+
end
|
60
|
+
|
61
|
+
def write_attribute(attr, value)
|
62
|
+
provided_set << attr.to_s unless self.class.tracking_disabled?
|
63
|
+
|
64
|
+
super(attr, value)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'digest'
|
2
|
+
|
3
|
+
module AxleAttributes
|
4
|
+
module Segmented
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
class_attribute :max_segment
|
9
|
+
self.max_segment = 1024
|
10
|
+
|
11
|
+
before_create do
|
12
|
+
regenerate_segment_id unless segment_id
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
def segment_range
|
18
|
+
0..(max_segment-1)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def generate_segment_id
|
23
|
+
Digest::MD5.digest(id.to_s).unpack("L")[0] % max_segment
|
24
|
+
end
|
25
|
+
|
26
|
+
def regenerate_segment_id
|
27
|
+
self.segment_id = generate_segment_id
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
module AxleAttributes
|
2
|
+
module Serializations
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
extend ActiveSupport::Autoload
|
5
|
+
|
6
|
+
autoload :Reflection, 'axle_attributes/serializations/reflection'
|
7
|
+
autoload :Serialization, 'axle_attributes/serializations/serialization'
|
8
|
+
autoload :SerializeMany, 'axle_attributes/serializations/serialize_many'
|
9
|
+
autoload :SerializeOne, 'axle_attributes/serializations/serialize_one'
|
10
|
+
|
11
|
+
module Builder
|
12
|
+
autoload :Serialization, 'axle_attributes/serializations/builder/serialization'
|
13
|
+
autoload :SerializeMany, 'axle_attributes/serializations/builder/serialize_many'
|
14
|
+
autoload :SerializeOne, 'axle_attributes/serializations/builder/serialize_one'
|
15
|
+
end
|
16
|
+
|
17
|
+
included do
|
18
|
+
class_attribute :serialization_reflections
|
19
|
+
self.serialization_reflections = {}
|
20
|
+
|
21
|
+
validate :validate_serialized_objects
|
22
|
+
|
23
|
+
after_save { child_serialization_cache.clear }
|
24
|
+
end
|
25
|
+
|
26
|
+
module ClassMethods
|
27
|
+
# serialize_many serializes a collection of objects into a single column.
|
28
|
+
#
|
29
|
+
# === Example
|
30
|
+
#
|
31
|
+
# class Factory
|
32
|
+
# serialize_many :widgets
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# This adds the following:
|
36
|
+
# <tt>factory.widgets_count</tt> - A counter cache of the number of widgets
|
37
|
+
# <tt>factory.widgets_updated_at</tt> - The last time a widget was modifed
|
38
|
+
# <tt>factory.widgets</tt> - A collection of widgets
|
39
|
+
#
|
40
|
+
# == Options
|
41
|
+
# [:class_name]
|
42
|
+
# The name of the class to instantiate the serialized objects as.
|
43
|
+
def serialize_many(name, options = {})
|
44
|
+
reflection = AxleAttributes::Serializations::Reflection.new(:serialize_many, name, options)
|
45
|
+
AxleAttributes::Serializations::Builder::SerializeMany.new(self, reflection).build!
|
46
|
+
reflection
|
47
|
+
end
|
48
|
+
|
49
|
+
# serialize_one serializes an object into a single column.
|
50
|
+
#
|
51
|
+
# === Example
|
52
|
+
#
|
53
|
+
# class Factory
|
54
|
+
# serialize_one :manager
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# This adds the following:
|
58
|
+
# <tt>factory.manager</tt> - Read the manager.
|
59
|
+
# <tt>factory.manager=(value)</tt> - Write the manager.
|
60
|
+
#
|
61
|
+
# == Options
|
62
|
+
# [:class_name]
|
63
|
+
# The name of the class to instantiate the serialized objects as.
|
64
|
+
def serialize_one(name, options = {})
|
65
|
+
reflection = AxleAttributes::Serializations::Reflection.new(:serialize_one, name, options)
|
66
|
+
AxleAttributes::Serializations::Builder::SerializeOne.new(self, reflection).build!
|
67
|
+
reflection
|
68
|
+
end
|
69
|
+
|
70
|
+
def serialized_many?(name)
|
71
|
+
serialization_reflections[name.to_sym].try :collection?
|
72
|
+
end
|
73
|
+
|
74
|
+
def generated_serialized_object_methods
|
75
|
+
@generated_serialized_object_methods ||= begin
|
76
|
+
mod = const_set(:GeneratedSerializedObjectMethods, Module.new)
|
77
|
+
include mod
|
78
|
+
mod
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns the searches_many instance for the given name, instantiating it if it doesn't already exist
|
84
|
+
def child_serialization(name)
|
85
|
+
serialization = child_serialization_instance_get(name)
|
86
|
+
|
87
|
+
if serialization.nil?
|
88
|
+
reflection = serialization_reflections[name]
|
89
|
+
serialization = reflection.serialization_class.new(self, reflection)
|
90
|
+
child_serialization_instance_set(name, serialization)
|
91
|
+
end
|
92
|
+
|
93
|
+
serialization
|
94
|
+
end
|
95
|
+
|
96
|
+
def reload
|
97
|
+
super
|
98
|
+
child_serialization_cache.clear
|
99
|
+
end
|
100
|
+
|
101
|
+
def validate_serialized_objects
|
102
|
+
child_serialization_cache.each do |name, serialization|
|
103
|
+
next unless serialization.loaded?
|
104
|
+
|
105
|
+
validation_method = serialization.reflection.collection? ? :validate_collection_serialization : :validate_single_serialization
|
106
|
+
send(validation_method, serialization)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def validate_collection_serialization(serialization)
|
111
|
+
serialization.reader.each do |record|
|
112
|
+
if record.invalid?
|
113
|
+
record.errors.each do |attribute, message|
|
114
|
+
attribute = "#{serialization.name}.#{attribute}"
|
115
|
+
errors[attribute] << message
|
116
|
+
errors[attribute].uniq!
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def validate_single_serialization(serialization)
|
123
|
+
record = serialization.reader
|
124
|
+
|
125
|
+
if record && record.invalid?
|
126
|
+
record.errors.each do |attribute, message|
|
127
|
+
attribute = "#{serialization.name}.#{attribute}"
|
128
|
+
errors[attribute] << message
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
def child_serialization_cache
|
136
|
+
@child_serialization_cache ||= {}
|
137
|
+
end
|
138
|
+
|
139
|
+
def child_serialization_instance_get(name)
|
140
|
+
child_serialization_cache[name.to_sym]
|
141
|
+
end
|
142
|
+
|
143
|
+
def child_serialization_instance_set(name, serialization)
|
144
|
+
child_serialization_cache[name.to_sym] = serialization
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module AxleAttributes::Serializations::Builder
|
2
|
+
class Serialization
|
3
|
+
attr_accessor :model, :reflection
|
4
|
+
def initialize(model, reflection)
|
5
|
+
@model = model
|
6
|
+
@reflection = reflection
|
7
|
+
end
|
8
|
+
|
9
|
+
def build!
|
10
|
+
model.serialization_reflections = model.serialization_reflections.merge(reflection.name => reflection)
|
11
|
+
|
12
|
+
define_attributes
|
13
|
+
define_writer
|
14
|
+
define_reader
|
15
|
+
end
|
16
|
+
|
17
|
+
def define_attributes
|
18
|
+
model.attribute_definition_class.new(model, reflection.storage_column, type: :json, index: false, version: true).setup!
|
19
|
+
|
20
|
+
model.has_attributes(meta_attributes)
|
21
|
+
|
22
|
+
setup_definitions_on_parent
|
23
|
+
end
|
24
|
+
|
25
|
+
def mixin
|
26
|
+
model.generated_serialized_object_methods
|
27
|
+
end
|
28
|
+
|
29
|
+
def define_writer
|
30
|
+
name = reflection.name
|
31
|
+
|
32
|
+
mixin.redefine_method "#{name}=" do |records|
|
33
|
+
child_serialization(name).writer(records)
|
34
|
+
end
|
35
|
+
|
36
|
+
mixin.redefine_method "#{name}_attributes=" do |attrs|
|
37
|
+
child_serialization(name).attributes_writer(attrs)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def define_reader
|
42
|
+
name = reflection.name
|
43
|
+
|
44
|
+
mixin.redefine_method(name) do
|
45
|
+
child_serialization(name).reader
|
46
|
+
end
|
47
|
+
|
48
|
+
mixin.redefine_method("#{name}_was") do
|
49
|
+
child_serialization(name).reader_was
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def setup_definitions_on_parent
|
54
|
+
serialized_index_mapping = {
|
55
|
+
type: index_type,
|
56
|
+
properties: {}
|
57
|
+
}
|
58
|
+
|
59
|
+
reflection.klass.attributes.each_value do |definition|
|
60
|
+
definition.nested_path = reflection.name.to_s if reflection.collection?
|
61
|
+
|
62
|
+
model.add_attribute_definition("#{reflection.name}.#{definition.name}", definition)
|
63
|
+
|
64
|
+
if mapping = definition.index_mapping
|
65
|
+
serialized_index_mapping[:properties][definition.name] = mapping
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
model.elastic_index.mapping[:properties].merge!(reflection.name.to_s => serialized_index_mapping)
|
70
|
+
end
|
71
|
+
|
72
|
+
protected
|
73
|
+
|
74
|
+
def index_type
|
75
|
+
raise "index_type must be implemented"
|
76
|
+
end
|
77
|
+
|
78
|
+
def meta_attributes
|
79
|
+
{}
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|