mongoid 7.0.1 → 7.0.2
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
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/mongoid/association.rb +0 -1
- data/lib/mongoid/association/depending.rb +22 -1
- data/lib/mongoid/association/embedded/embeds_one/proxy.rb +3 -3
- data/lib/mongoid/association/referenced/has_many/proxy.rb +1 -1
- data/lib/mongoid/association/relatable.rb +16 -2
- data/lib/mongoid/attributes/nested.rb +14 -3
- data/lib/mongoid/contextual/map_reduce.rb +1 -1
- data/lib/mongoid/copyable.rb +3 -2
- data/lib/mongoid/document.rb +2 -0
- data/lib/mongoid/matchable.rb +3 -0
- data/lib/mongoid/matchable/nor.rb +37 -0
- data/lib/mongoid/persistable/settable.rb +58 -13
- data/lib/mongoid/persistence_context.rb +5 -1
- data/lib/mongoid/touchable.rb +102 -0
- data/lib/mongoid/version.rb +1 -1
- data/spec/app/models/array_field.rb +7 -0
- data/spec/app/models/updatable.rb +7 -0
- data/spec/mongoid/association/accessors_spec.rb +39 -0
- data/spec/mongoid/association/depending_spec.rb +253 -0
- data/spec/mongoid/association/polymorphic_spec.rb +59 -0
- data/spec/mongoid/association/referenced/belongs_to_spec.rb +3 -3
- data/spec/mongoid/association/referenced/has_one_spec.rb +59 -0
- data/spec/mongoid/attributes/nested_spec.rb +18 -2
- data/spec/mongoid/clients/factory_spec.rb +3 -3
- data/spec/mongoid/clients/options_spec.rb +28 -13
- data/spec/mongoid/clients/sessions_spec.rb +3 -3
- data/spec/mongoid/clients/transactions_spec.rb +369 -0
- data/spec/mongoid/copyable_spec.rb +16 -0
- data/spec/mongoid/matchable/nor_spec.rb +209 -0
- data/spec/mongoid/matchable_spec.rb +26 -1
- data/spec/mongoid/persistable/settable_spec.rb +128 -9
- data/spec/mongoid/{association/touchable_spec.rb → touchable_spec.rb} +28 -7
- data/spec/spec_helper.rb +8 -0
- metadata +457 -448
- metadata.gz.sig +0 -0
- data/lib/mongoid/association/touchable.rb +0 -97
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0e3c2f9aa40e2f20c7620a2ae7684da4ebfc1699e32357dd4aa663d93b7ade33
|
4
|
+
data.tar.gz: 9f0d2145026c3db222638b7d00d842a690294cc6101a582a14a75607c44474a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f9b11ae060df18208b48b911ee39c2954a7855ac7ffc19b073aa21a707e51805bb465b73b7634abb425d983b3d57fbbab044a202853e532c0fc8331141b9734
|
7
|
+
data.tar.gz: 24d37b3c3b77d110d45ec6df6209e8cf4a7821fb787c4d369cd87f01bcf66db0292e101928f8ab2a102f5020c6bb4d7b4b19b13fc2c7765096f5f409251825ff
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/lib/mongoid/association.rb
CHANGED
@@ -3,7 +3,6 @@ require 'mongoid/association/builders'
|
|
3
3
|
require 'mongoid/association/bindable'
|
4
4
|
require 'mongoid/association/depending'
|
5
5
|
require 'mongoid/association/proxy'
|
6
|
-
require 'mongoid/association/touchable'
|
7
6
|
|
8
7
|
require 'mongoid/association/many'
|
9
8
|
require 'mongoid/association/one'
|
@@ -8,7 +8,23 @@ module Mongoid
|
|
8
8
|
|
9
9
|
included do
|
10
10
|
class_attribute :dependents
|
11
|
+
|
12
|
+
# @api private
|
13
|
+
class_attribute :dependents_owner
|
14
|
+
|
11
15
|
self.dependents = []
|
16
|
+
self.dependents_owner = self
|
17
|
+
end
|
18
|
+
|
19
|
+
class_methods do
|
20
|
+
# @api private
|
21
|
+
def _all_dependents
|
22
|
+
superclass_dependents = superclass.respond_to?(:_all_dependents) ? superclass._all_dependents : []
|
23
|
+
dependents + superclass_dependents.reject do |new_dep|
|
24
|
+
dependents.any? do |old_dep| old_dep.name == new_dep.name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
12
28
|
end
|
13
29
|
|
14
30
|
# The valid dependent strategies.
|
@@ -41,6 +57,11 @@ module Mongoid
|
|
41
57
|
def self.define_dependency!(association)
|
42
58
|
validate!(association)
|
43
59
|
association.inverse_class.tap do |klass|
|
60
|
+
if klass.dependents_owner != klass
|
61
|
+
klass.dependents = []
|
62
|
+
klass.dependents_owner = klass
|
63
|
+
end
|
64
|
+
|
44
65
|
if association.dependent && !klass.dependents.include?(association)
|
45
66
|
klass.dependents.push(association)
|
46
67
|
end
|
@@ -63,7 +84,7 @@ module Mongoid
|
|
63
84
|
#
|
64
85
|
# @since 2.0.0.rc.1
|
65
86
|
def apply_delete_dependencies!
|
66
|
-
|
87
|
+
self.class._all_dependents.each do |association|
|
67
88
|
if association.try(:dependent)
|
68
89
|
send("_dependent_#{association.dependent}!", association)
|
69
90
|
end
|
@@ -52,9 +52,9 @@ module Mongoid
|
|
52
52
|
if _assigning?
|
53
53
|
_base.add_atomic_unset(_target) unless replacement
|
54
54
|
else
|
55
|
-
# The associated object will be replaced by the below update, so only
|
56
|
-
# run the callbacks and state-changing code by passing persist: false.
|
57
|
-
_target.destroy(persist:
|
55
|
+
# The associated object will be replaced by the below update if non-nil, so only
|
56
|
+
# run the callbacks and state-changing code by passing persist: false in that case.
|
57
|
+
_target.destroy(persist: !replacement) if persistable?
|
58
58
|
end
|
59
59
|
unbind_one
|
60
60
|
return nil unless replacement
|
@@ -459,7 +459,7 @@ module Mongoid
|
|
459
459
|
collection.insert_many(inserts, session: _session)
|
460
460
|
docs.each do |doc|
|
461
461
|
doc.new_record = false
|
462
|
-
doc.run_after_callbacks(:create, :save)
|
462
|
+
doc.run_after_callbacks(:create, :save) unless _association.autosave?
|
463
463
|
doc.post_persist
|
464
464
|
end
|
465
465
|
end
|
@@ -57,6 +57,10 @@ module Mongoid
|
|
57
57
|
@name = name
|
58
58
|
@options = opts
|
59
59
|
@extension = nil
|
60
|
+
|
61
|
+
@module_path = _class.name ? _class.name.split('::')[0..-2].join('::') : ''
|
62
|
+
@module_path << '::' unless @module_path.empty?
|
63
|
+
|
60
64
|
create_extension!(&block)
|
61
65
|
validate!
|
62
66
|
end
|
@@ -147,7 +151,7 @@ module Mongoid
|
|
147
151
|
#
|
148
152
|
# @since 7.0
|
149
153
|
def relation_class_name
|
150
|
-
@class_name ||= @options[:class_name] || ActiveSupport::Inflector.classify(
|
154
|
+
@class_name ||= @options[:class_name] || ActiveSupport::Inflector.classify(name_with_module)
|
151
155
|
end
|
152
156
|
alias :class_name :relation_class_name
|
153
157
|
|
@@ -321,13 +325,23 @@ module Mongoid
|
|
321
325
|
|
322
326
|
private
|
323
327
|
|
328
|
+
def name_with_module
|
329
|
+
@module_path + name.to_s.capitalize
|
330
|
+
end
|
331
|
+
|
332
|
+
# Gets the model classes with inverse associations of this model. This is used to determine
|
333
|
+
# the classes on the other end of polymorphic relations with models.
|
334
|
+
def inverse_association_classes
|
335
|
+
Mongoid::Config.models.map { |m| inverse_association(m) }.compact.map(&:inverse_class)
|
336
|
+
end
|
337
|
+
|
324
338
|
def setup_index!
|
325
339
|
@owner_class.index(index_spec, background: true) if indexed?
|
326
340
|
end
|
327
341
|
|
328
342
|
def define_touchable!
|
329
343
|
if touchable?
|
330
|
-
|
344
|
+
Touchable.define_touchable!(self)
|
331
345
|
end
|
332
346
|
end
|
333
347
|
|
@@ -42,15 +42,21 @@ module Mongoid
|
|
42
42
|
# to a class method to reject documents with.
|
43
43
|
# @option *args [ Integer ] :limit The max number to create.
|
44
44
|
# @option *args [ true, false ] :update_only Only update existing docs.
|
45
|
+
# @options *args [ true, false ] :autosave Whether autosave should be enabled on the
|
46
|
+
# association. Note that since the default is true, setting autosave to nil will still
|
47
|
+
# enable it.
|
45
48
|
def accepts_nested_attributes_for(*args)
|
46
|
-
options = args.extract_options
|
49
|
+
options = args.extract_options!.dup
|
50
|
+
options[:autosave] = true if options[:autosave].nil?
|
51
|
+
|
47
52
|
options[:reject_if] = REJECT_ALL_BLANK_PROC if options[:reject_if] == :all_blank
|
48
53
|
args.each do |name|
|
49
54
|
meth = "#{name}_attributes="
|
50
55
|
self.nested_attributes["#{name}_attributes"] = meth
|
51
56
|
association = relations[name.to_s]
|
52
57
|
raise Errors::NestedAttributesMetadataNotFound.new(self, name) unless association
|
53
|
-
autosave_nested_attributes(association)
|
58
|
+
autosave_nested_attributes(association) if options[:autosave]
|
59
|
+
|
54
60
|
re_define_method(meth) do |attrs|
|
55
61
|
_assigning do
|
56
62
|
if association.polymorphic? and association.inverse_type
|
@@ -75,7 +81,12 @@ module Mongoid
|
|
75
81
|
#
|
76
82
|
# @since 3.1.4
|
77
83
|
def autosave_nested_attributes(association)
|
78
|
-
|
84
|
+
# In order for the autosave functionality to work properly, the association needs to be
|
85
|
+
# marked as autosave despite the fact that the option isn't present. Because the method
|
86
|
+
# Association#autosave? is implemented by checking the autosave option, this is the most
|
87
|
+
# straightforward way to mark it.
|
88
|
+
if association.autosave? || (association.options[:autosave].nil? && !association.embedded?)
|
89
|
+
association.options[:autosave] = true
|
79
90
|
Association::Referenced::AutoSave.define_autosave!(association)
|
80
91
|
end
|
81
92
|
end
|
@@ -165,7 +165,7 @@ module Mongoid
|
|
165
165
|
def raw
|
166
166
|
validate_out!
|
167
167
|
cmd = command
|
168
|
-
opts = { read: cmd.delete(:read)
|
168
|
+
opts = { read: cmd.delete(:read) } if cmd[:read]
|
169
169
|
@map_reduce.database.command(cmd, (opts || {}).merge(session: _session)).first
|
170
170
|
end
|
171
171
|
alias :results :raw
|
data/lib/mongoid/copyable.rb
CHANGED
@@ -73,8 +73,9 @@ module Mongoid
|
|
73
73
|
next unless attrs.present? && attrs[association.key].present?
|
74
74
|
|
75
75
|
if association.is_a?(Association::Embedded::EmbedsMany)
|
76
|
-
attrs[association.name.to_s].
|
77
|
-
|
76
|
+
attrs[association.name.to_s].each do |attr|
|
77
|
+
embedded_klass = attr.fetch('_type', association.class_name).constantize
|
78
|
+
process_localized_attributes(embedded_klass, attr)
|
78
79
|
end
|
79
80
|
else
|
80
81
|
process_localized_attributes(association.klass, attrs[association.key])
|
data/lib/mongoid/document.rb
CHANGED
@@ -15,6 +15,7 @@ require "mongoid/fields"
|
|
15
15
|
require "mongoid/timestamps"
|
16
16
|
require "mongoid/association"
|
17
17
|
require "mongoid/composable"
|
18
|
+
require "mongoid/touchable"
|
18
19
|
|
19
20
|
module Mongoid
|
20
21
|
|
@@ -23,6 +24,7 @@ module Mongoid
|
|
23
24
|
module Document
|
24
25
|
extend ActiveSupport::Concern
|
25
26
|
include Composable
|
27
|
+
include Mongoid::Touchable::InstanceMethods
|
26
28
|
|
27
29
|
attr_accessor :__selected_fields
|
28
30
|
attr_reader :new_record
|
data/lib/mongoid/matchable.rb
CHANGED
@@ -11,6 +11,7 @@ require "mongoid/matchable/lte"
|
|
11
11
|
require "mongoid/matchable/ne"
|
12
12
|
require "mongoid/matchable/nin"
|
13
13
|
require "mongoid/matchable/or"
|
14
|
+
require "mongoid/matchable/nor"
|
14
15
|
require "mongoid/matchable/size"
|
15
16
|
require "mongoid/matchable/elem_match"
|
16
17
|
require "mongoid/matchable/regexp"
|
@@ -40,6 +41,7 @@ module Mongoid
|
|
40
41
|
"$ne" => Ne,
|
41
42
|
"$nin" => Nin,
|
42
43
|
"$or" => Or,
|
44
|
+
"$nor" => Nor,
|
43
45
|
"$size" => Size
|
44
46
|
}.with_indifferent_access.freeze
|
45
47
|
|
@@ -124,6 +126,7 @@ module Mongoid
|
|
124
126
|
case key.to_s
|
125
127
|
when "$or" then Or.new(value, document)
|
126
128
|
when "$and" then And.new(value, document)
|
129
|
+
when "$nor" then Nor.new(value, document)
|
127
130
|
else Default.new(extract_attribute(document, key))
|
128
131
|
end
|
129
132
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# encoding: utf-8
|
3
|
+
module Mongoid
|
4
|
+
module Matchable
|
5
|
+
|
6
|
+
# Defines behavior for handling $nor expressions in embedded documents.
|
7
|
+
class Nor < Default
|
8
|
+
|
9
|
+
# Does the supplied query match the attribute?
|
10
|
+
#
|
11
|
+
# Note: an empty array as an argument to $nor is prohibited by
|
12
|
+
# MongoDB server. Mongoid does allow this and returns false in this case.
|
13
|
+
#
|
14
|
+
# @example Does this match?
|
15
|
+
# matcher._matches?("$nor" => [ { field => value } ])
|
16
|
+
#
|
17
|
+
# @param [ Array ] conditions The or expression.
|
18
|
+
#
|
19
|
+
# @return [ true, false ] True if matches, false if not.
|
20
|
+
#
|
21
|
+
# @since 6.4.2/7.0.2/7.1.0
|
22
|
+
def _matches?(conditions)
|
23
|
+
if conditions.length == 0
|
24
|
+
# MongoDB does not allow $nor array to be empty, but
|
25
|
+
# Mongoid accepts an empty array for $or which MongoDB also
|
26
|
+
# prohibits
|
27
|
+
return false
|
28
|
+
end
|
29
|
+
conditions.none? do |condition|
|
30
|
+
condition.all? do |key, value|
|
31
|
+
document._matches?(key => value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -14,6 +14,34 @@ module Mongoid
|
|
14
14
|
# @example Set the values.
|
15
15
|
# document.set(title: "sir", dob: Date.new(1970, 1, 1))
|
16
16
|
#
|
17
|
+
# The key can be a dotted sequence of keys, in which case the
|
18
|
+
# top level field is treated as a nested hash and any missing keys
|
19
|
+
# are created automatically:
|
20
|
+
#
|
21
|
+
# @example Set the values using nested hash semantics.
|
22
|
+
# document.set('author.title' => 'Sir')
|
23
|
+
# # => document.author == {'title' => 'Sir'}
|
24
|
+
#
|
25
|
+
# Performing a nested set like this merges values of intermediate keys:
|
26
|
+
#
|
27
|
+
# @example Nested hash value merging.
|
28
|
+
# document.set('author.title' => 'Sir')
|
29
|
+
# document.set('author.name' => 'Linus Torvalds')
|
30
|
+
# # => document.author == {'title' => 'Sir', 'name' => 'Linus Torvalds'}
|
31
|
+
#
|
32
|
+
# If the top level field was not a hash, its original value is discarded
|
33
|
+
# and the field is replaced with a hash.
|
34
|
+
#
|
35
|
+
# @example Nested hash overwriting a non-hash value.
|
36
|
+
# document.set('author' => 'John Doe')
|
37
|
+
# document.set('author.title' => 'Sir')
|
38
|
+
# # => document.author == {'title' => 'Sir'}
|
39
|
+
#
|
40
|
+
# Note that unlike MongoDB's $set, Mongoid's set writes out the entire
|
41
|
+
# field even when setting a subset of the field via the nested hash
|
42
|
+
# semantics. This means performing a $set with nested hash semantics
|
43
|
+
# can overwrite other hash keys within the top level field in the database.
|
44
|
+
#
|
17
45
|
# @param [ Hash ] setters The field/value pairs to set.
|
18
46
|
#
|
19
47
|
# @return [ Document ] The document.
|
@@ -23,17 +51,39 @@ module Mongoid
|
|
23
51
|
prepare_atomic_operation do |ops|
|
24
52
|
process_atomic_operations(setters) do |field, value|
|
25
53
|
|
26
|
-
|
27
|
-
field =
|
54
|
+
field_seq = field.to_s.split('.')
|
55
|
+
field = field_seq.shift
|
56
|
+
if field_seq.length > 0
|
57
|
+
# nested hash path
|
58
|
+
old_value = attributes[field]
|
28
59
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
60
|
+
# if the old value is not a hash, clobber it
|
61
|
+
unless Hash === old_value
|
62
|
+
old_value = {}
|
63
|
+
end
|
64
|
+
|
65
|
+
# descend into the hash, creating intermediate keys as needed
|
66
|
+
cur_value = old_value
|
67
|
+
while field_seq.length > 1
|
68
|
+
cur_key = field_seq.shift
|
69
|
+
# clobber on each level if type is not a hash
|
70
|
+
unless Hash === cur_value[cur_key]
|
71
|
+
cur_value[cur_key] = {}
|
72
|
+
end
|
73
|
+
cur_value = cur_value[cur_key]
|
74
|
+
end
|
75
|
+
|
76
|
+
# now we are on the leaf level, perform the set
|
77
|
+
# and overwrite whatever was on this level before
|
78
|
+
cur_value[field_seq.shift] = value
|
79
|
+
|
80
|
+
# and set value to the value of the top level field
|
81
|
+
# because this is what we pass to $set
|
82
|
+
value = old_value
|
35
83
|
end
|
36
84
|
|
85
|
+
process_attribute(field, value)
|
86
|
+
|
37
87
|
unless relations.include?(field.to_s)
|
38
88
|
ops[atomic_attribute_name(field)] = attributes[field]
|
39
89
|
end
|
@@ -42,10 +92,5 @@ module Mongoid
|
|
42
92
|
end
|
43
93
|
end
|
44
94
|
end
|
45
|
-
|
46
|
-
def hasherizer(keys, value)
|
47
|
-
return value if keys.empty?
|
48
|
-
{}.tap { |hash| hash[keys.shift] = hasherizer(keys, value) }
|
49
|
-
end
|
50
95
|
end
|
51
96
|
end
|
@@ -107,6 +107,10 @@ module Mongoid
|
|
107
107
|
#
|
108
108
|
# @since 6.0.0
|
109
109
|
def client
|
110
|
+
client_options = send(:client_options)
|
111
|
+
if client_options[:read].is_a?(Symbol)
|
112
|
+
client_options = client_options.merge(read: {mode: client_options[:read]})
|
113
|
+
end
|
110
114
|
@client ||= (client = Clients.with_name(client_name)
|
111
115
|
client = client.use(database_name) if database_name_option
|
112
116
|
client.with(client_options))
|
@@ -208,7 +212,7 @@ module Mongoid
|
|
208
212
|
if context = get(object)
|
209
213
|
context.client.close unless (context.cluster.equal?(cluster) || cluster.nil?)
|
210
214
|
end
|
211
|
-
ensure
|
215
|
+
ensure
|
212
216
|
Thread.current["[mongoid][#{object.object_id}]:context"] = nil
|
213
217
|
end
|
214
218
|
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# encoding: utf-8
|
3
|
+
module Mongoid
|
4
|
+
module Touchable
|
5
|
+
|
6
|
+
module InstanceMethods
|
7
|
+
|
8
|
+
# Touch the document, in effect updating its updated_at timestamp and
|
9
|
+
# optionally the provided field to the current time. If any belongs_to
|
10
|
+
# relations exist with a touch option, they will be updated as well.
|
11
|
+
#
|
12
|
+
# @example Update the updated_at timestamp.
|
13
|
+
# document.touch
|
14
|
+
#
|
15
|
+
# @example Update the updated_at and provided timestamps.
|
16
|
+
# document.touch(:audited)
|
17
|
+
#
|
18
|
+
# @note This will not autobuild relations if those options are set.
|
19
|
+
#
|
20
|
+
# @param [ Symbol ] field The name of an additional field to update.
|
21
|
+
#
|
22
|
+
# @return [ true/false ] false if record is new_record otherwise true.
|
23
|
+
#
|
24
|
+
# @since 3.0.0
|
25
|
+
def touch(field = nil)
|
26
|
+
return false if _root.new_record?
|
27
|
+
current = Time.now
|
28
|
+
field = database_field_name(field)
|
29
|
+
write_attribute(:updated_at, current) if respond_to?("updated_at=")
|
30
|
+
write_attribute(field, current) if field
|
31
|
+
|
32
|
+
touches = touch_atomic_updates(field)
|
33
|
+
unless touches["$set"].blank?
|
34
|
+
selector = atomic_selector
|
35
|
+
_root.collection.find(selector).update_one(positionally(selector, touches), session: _session)
|
36
|
+
end
|
37
|
+
run_callbacks(:touch)
|
38
|
+
true
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
extend self
|
43
|
+
|
44
|
+
# Add the association to the touchable relations if the touch option was
|
45
|
+
# provided.
|
46
|
+
#
|
47
|
+
# @example Add the touchable.
|
48
|
+
# Model.define_touchable!(assoc)
|
49
|
+
#
|
50
|
+
# @param [ Association ] association The association metadata.
|
51
|
+
#
|
52
|
+
# @return [ Class ] The model class.
|
53
|
+
#
|
54
|
+
# @since 3.0.0
|
55
|
+
def define_touchable!(association)
|
56
|
+
name = association.name
|
57
|
+
method_name = define_relation_touch_method(name, association)
|
58
|
+
association.inverse_class.tap do |klass|
|
59
|
+
klass.after_save method_name
|
60
|
+
klass.after_destroy method_name
|
61
|
+
klass.after_touch method_name
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
# Define the method that will get called for touching belongs_to
|
68
|
+
# relations.
|
69
|
+
#
|
70
|
+
# @api private
|
71
|
+
#
|
72
|
+
# @example Define the touch relation.
|
73
|
+
# Model.define_relation_touch_method(:band)
|
74
|
+
# Model.define_relation_touch_method(:band, :band_updated_at)
|
75
|
+
#
|
76
|
+
# @param [ Symbol ] name The name of the relation.
|
77
|
+
# @param [ Association ] association The association metadata.
|
78
|
+
#
|
79
|
+
# @since 3.1.0
|
80
|
+
#
|
81
|
+
# @return [ Symbol ] The method name.
|
82
|
+
def define_relation_touch_method(name, association)
|
83
|
+
relation_classes = if association.polymorphic?
|
84
|
+
association.send(:inverse_association_classes)
|
85
|
+
else
|
86
|
+
[ association.relation_class ]
|
87
|
+
end
|
88
|
+
|
89
|
+
relation_classes.each { |c| c.send(:include, InstanceMethods) }
|
90
|
+
method_name = "touch_#{name}_after_create_or_destroy"
|
91
|
+
association.inverse_class.class_eval <<-TOUCH, __FILE__, __LINE__ + 1
|
92
|
+
def #{method_name}
|
93
|
+
without_autobuild do
|
94
|
+
relation = __send__(:#{name})
|
95
|
+
relation.touch #{":#{association.touch_field}" if association.touch_field} if relation
|
96
|
+
end
|
97
|
+
end
|
98
|
+
TOUCH
|
99
|
+
method_name.to_sym
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|