mongoid 7.0.1 → 7.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|