mongoid_relations_dirty_tracking 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 9bd7befbb1f28738d4b2466c5fee8a4f73f82eb2
4
- data.tar.gz: 5f86d528912d3a3a90e3306ac8b60069a90cea37
2
+ SHA256:
3
+ metadata.gz: b6043c61085a0af72034235ae1c4f3b886c08d6c4c913878a21fe3233e5f90dc
4
+ data.tar.gz: 20772362d9765d4a3138ce1324421fc427071102ded5facb7f0ebec35d4237e6
5
5
  SHA512:
6
- metadata.gz: f5f28400a832ca7b5627ce13b4aea1c2c7ba91a885c8b23ab71b76034ba8a59fb4df070f713b6d2430e5abf494c76cb6bd57dfb06f368423dc50bd106306bea2
7
- data.tar.gz: 3d61e3f9e0a3461996150562c9321545d8cb9c3f9ea8bace95d28c709645126360cb4571ef8f244535b34d16adf7963f3fd2e8c8b1aecd8d3a2c82fd4fba4d42
6
+ metadata.gz: 17563973f5795355ae46f49a7dd304b9c24c72107d0c7f6e45220a5e106b35810342916ae7948be6dc7da5ec9aed6b433da55b09db3f49077243d224e134b4ed
7
+ data.tar.gz: 7a9f3391196fe7333d7a0ff08047fdce013d626159eaea8013d2a243e3ebd3aced43d080046419aec5e77f234145e3ca120084558a25b81d8d29d1b6ab968842
@@ -1,22 +1,22 @@
1
- Copyright (c) 2013 David Sevcik
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
+ Copyright (c) 2013 David Sevcik
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,51 +1,80 @@
1
- # Mongoid::RelationsDirtyTracking
2
-
3
- Mongoid extension for tracking changes on document relations.
4
-
5
- ## Installation
6
-
7
- Add this line to your application's Gemfile:
8
-
9
- gem 'mongoid_relations_dirty_tracking', github: 'versative/mongoid_relations_dirty_tracking'
10
-
11
- And then execute:
12
-
13
- $ bundle
14
-
15
- ## Usage
16
-
17
- ```ruby
18
- class SampleDocument
19
- include Mongoid::Document
20
- include Mongoid::RelationsDirtyTracking
21
-
22
- embeds_one :foo
23
- has_many :bars
24
-
25
- field :title, type: String
26
- end
27
-
28
- doc = SampleDocument.create
29
- doc.foo = Foo.new(title: 'foo')
30
- doc.bars << Bar.new(title: 'bar')
31
- doc.title = 'New title'
32
-
33
- doc.relations_changed? # => true
34
- doc.relation_changes # => {"foo" => [nil, {"_id"=>"524c35ad1ac1c23084000040", "title" => "foo"}], "bars" => [nil, [{"_id"=>"524c35ad1ac1c23084000083"}]]}
35
- doc.changed? # => true
36
- doc.changes # => {"title" => [nil, "New title"], "foo" => [nil, {"_id"=>"524c35ad1ac1c23084000040", "title" => "foo"}], "bars" => [nil, [{"_id"=>"524c35ad1ac1c23084000083"}]]}
37
-
38
- doc.save
39
- doc.relations_changed? # => false
40
- doc.relation_changes # => {}
41
- doc.changed? # => false
42
- doc.changes # => {}
43
- ```
44
-
45
- ## Contributing
46
-
47
- 1. Fork it
48
- 2. Create your feature branch (`git checkout -b my-new-feature`)
49
- 3. Commit your changes (`git commit -am 'Add some feature'`)
50
- 4. Push to the branch (`git push origin my-new-feature`)
51
- 5. Create new Pull Request
1
+ # Mongoid::RelationsDirtyTracking
2
+
3
+ Mongoid extension for tracking changes on document relations.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'mongoid_relations_dirty_tracking'
11
+ ```
12
+
13
+ ## Version Support
14
+
15
+ This gem is CI tested using:
16
+
17
+ - Rails 5.1, 5.2, and 6.0
18
+ - Mongoid 7.0 and 7.1
19
+
20
+ ## Usage
21
+
22
+ ```ruby
23
+ class SampleDocument
24
+ include Mongoid::Document
25
+ include Mongoid::RelationsDirtyTracking
26
+
27
+ embeds_one :foo
28
+ has_many :bars
29
+
30
+ field :title, type: String
31
+ end
32
+
33
+ doc = SampleDocument.create
34
+ doc.foo = Foo.new(title: 'foo')
35
+ doc.bars << Bar.new(title: 'bar')
36
+ doc.title = 'New title'
37
+
38
+ doc.relations_changed? # => true
39
+ doc.relation_changes # => {"foo" => [nil, {"_id"=>"524c35ad1ac1c23084000040", "title" => "foo"}], "bars" => [nil, [{"_id"=>"524c35ad1ac1c23084000083"}]]}
40
+ doc.changed_with_relations? # => true
41
+ doc.changes_with_relations # => {"title" => [nil, "New title"], "foo" => [nil, {"_id"=>"524c35ad1ac1c23084000040", "title" => "foo"}], "bars" => [nil, [{"_id"=>"524c35ad1ac1c23084000083"}]]}
42
+
43
+ doc.save
44
+ doc.relations_changed? # => false
45
+ doc.relation_changes # => {}
46
+ doc.changed_with_relations? # => false
47
+ doc.changes_with_relations # => {}
48
+ ```
49
+
50
+ ### Global Disable
51
+
52
+ Relations dirty tracking can be resource intensive.
53
+ You may disable it for a block scope. This is thread-safe
54
+ and will use the [RequestStore gem](https://github.com/steveklabnik/request_store)
55
+ if it is included in your project.
56
+
57
+ ```ruby
58
+ Mongoid::RelationsDirtyTracking.disable do
59
+ doc = SampleDocument.create
60
+ doc.foo = Foo.new(title: 'foo')
61
+ doc.bars << Bar.new(title: 'bar')
62
+
63
+ doc.relations_changed? # => false
64
+ doc.relation_changes # => {}
65
+ end
66
+ ```
67
+
68
+ ## Contributing
69
+
70
+ 1. Fork it
71
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
72
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
73
+ 4. Push to the branch (`git push origin my-new-feature`)
74
+ 5. Create new Pull Request
75
+
76
+ ## Attribution
77
+
78
+ Created 2013 by David Sevcik
79
+
80
+ Maintenance from 2020 onward provided by [TableCheck](https://www.tablecheck.com/en/company/)
@@ -1,108 +1,124 @@
1
- require 'mongoid'
2
- require 'active_support/concern'
3
- require 'active_support/core_ext/module/aliasing'
4
-
5
-
6
- module Mongoid
7
- module RelationsDirtyTracking
8
- extend ActiveSupport::Concern
9
-
10
- included do
11
- after_initialize :store_relations_shadow
12
- after_save :store_relations_shadow
13
-
14
- alias_method_chain :changes, :relations
15
- alias_method_chain :changed?, :relations
16
-
17
- cattr_accessor :relations_dirty_tracking_options
18
- self.relations_dirty_tracking_options = { only: [], except: ['versions'] }
19
-
20
- if self.include? Mongoid::Versioning
21
- include Mongoid::RelationsDirtyTracking::Versioning
22
- end
23
- end
24
-
25
-
26
- def store_relations_shadow
27
- @relations_shadow = {}
28
- self.class.tracked_relations.each do |rel_name|
29
- @relations_shadow[rel_name] = tracked_relation_attributes(rel_name)
30
- end
31
- end
32
-
33
-
34
- def relation_changes
35
- changes = {}
36
- @relations_shadow.each_pair do |rel_name, shadow_values|
37
- current_values = tracked_relation_attributes(rel_name)
38
- if current_values != shadow_values
39
- changes[rel_name] = [shadow_values, current_values]
40
- end
41
- end
42
- changes
43
- end
44
-
45
-
46
- def relations_changed?
47
- !relation_changes.empty?
48
- end
49
-
50
-
51
- def changed_with_relations?
52
- changed_without_relations? or relations_changed?
53
- end
54
-
55
-
56
- def changes_with_relations
57
- (changes_without_relations || {}).merge relation_changes
58
- end
59
-
60
-
61
- def tracked_relation_attributes(rel_name)
62
- rel_name = rel_name.to_s
63
- values = nil
64
- if meta = relations[rel_name]
65
- values = if meta.relation == Mongoid::Relations::Embedded::One
66
- send(rel_name) && send(rel_name).attributes.clone.delete_if {|key, _| key == 'updated_at' }
67
- elsif meta.relation == Mongoid::Relations::Embedded::Many
68
- send(rel_name) && send(rel_name).map {|child| child.attributes.clone.delete_if {|key, _| key == 'updated_at' } }
69
- elsif meta.relation == Mongoid::Relations::Referenced::One
70
- send(rel_name) && { "#{meta.key}" => send(rel_name)[meta.key] }
71
- elsif meta.relation == Mongoid::Relations::Referenced::Many
72
- send("#{rel_name.singularize}_ids").map {|id| { "#{meta.key}" => id } }
73
- elsif meta.relation == Mongoid::Relations::Referenced::ManyToMany
74
- send("#{rel_name.singularize}_ids").map {|id| { "#{meta.primary_key}" => id } }
75
- elsif meta.relation == Mongoid::Relations::Referenced::In
76
- send(meta.foreign_key) && { "#{meta.foreign_key}" => send(meta.foreign_key)}
77
- end
78
- end
79
- values
80
- end
81
-
82
-
83
- module ClassMethods
84
-
85
- def relations_dirty_tracking(options = {})
86
- relations_dirty_tracking_options[:only] += [options[:only] || []].flatten.map(&:to_s)
87
- relations_dirty_tracking_options[:except] += [options[:except] || []].flatten.map(&:to_s)
88
- end
89
-
90
-
91
- def track_relation?(rel_name)
92
- rel_name = rel_name.to_s
93
- options = relations_dirty_tracking_options
94
- to_track = (!options[:only].blank? && options[:only].include?(rel_name)) \
95
- || (options[:only].blank? && !options[:except].include?(rel_name))
96
-
97
- to_track && [Mongoid::Relations::Embedded::One, Mongoid::Relations::Embedded::Many,
98
- Mongoid::Relations::Referenced::One, Mongoid::Relations::Referenced::Many,
99
- Mongoid::Relations::Referenced::ManyToMany, Mongoid::Relations::Referenced::In].include?(relations[rel_name].try(:relation))
100
- end
101
-
102
-
103
- def tracked_relations
104
- @tracked_relations ||= relations.keys.select {|rel_name| track_relation?(rel_name) }
105
- end
106
- end
107
- end
108
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'mongoid'
4
+ require 'active_support/concern'
5
+
6
+ module Mongoid
7
+ module RelationsDirtyTracking
8
+ extend ActiveSupport::Concern
9
+
10
+ class << self
11
+ DISABLED_KEY = 'mongoid/relations_dirty_tracking/disabled'
12
+
13
+ # Runs a block without invoking relations dirty tracking on the current thread.
14
+ # Returns the block return value.
15
+ def disable
16
+ thread_store[DISABLED_KEY] = true
17
+ yield
18
+ ensure
19
+ thread_store[DISABLED_KEY] = false
20
+ end
21
+
22
+ # Returns whether relations dirty tracking is enabled on the current thread.
23
+ def enabled?
24
+ !thread_store[DISABLED_KEY]
25
+ end
26
+
27
+ protected
28
+
29
+ def thread_store
30
+ defined?(RequestStore) ? RequestStore.store : Thread.current
31
+ end
32
+ end
33
+
34
+ module ClassMethods
35
+ def relations_dirty_tracking(options = {})
36
+ relations_dirty_tracking_options[:only] += [options[:only] || []].flatten.map(&:to_s)
37
+ relations_dirty_tracking_options[:except] += [options[:except] || []].flatten.map(&:to_s)
38
+ end
39
+
40
+ def track_relation?(rel_name)
41
+ rel_name = rel_name.to_s
42
+ options = relations_dirty_tracking_options
43
+ to_track = (!options[:only].blank? && options[:only].include?(rel_name)) ||
44
+ (options[:only].blank? && !options[:except].include?(rel_name))
45
+
46
+ trackables = [Mongoid::Association::Embedded::EmbedsOne::Proxy,
47
+ Mongoid::Association::Embedded::EmbedsMany::Proxy,
48
+ Mongoid::Association::Referenced::HasOne::Proxy,
49
+ Mongoid::Association::Referenced::HasMany::Proxy,
50
+ Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy,
51
+ Mongoid::Association::Referenced::BelongsTo::Proxy]
52
+ to_track && trackables.include?(relations[rel_name].try(:relation))
53
+ end
54
+
55
+ def tracked_relations
56
+ @tracked_relations ||= relations.keys.select { |rel_name| track_relation?(rel_name) }
57
+ end
58
+ end
59
+
60
+ included do
61
+ after_initialize :store_relations_shadow
62
+ after_save :store_relations_shadow
63
+
64
+ cattr_accessor :relations_dirty_tracking_options
65
+ self.relations_dirty_tracking_options = { only: [], except: ['versions'] }
66
+
67
+ def store_relations_shadow
68
+ @relations_shadow = {}
69
+ return unless Mongoid::RelationsDirtyTracking.enabled?
70
+ self.class.tracked_relations.each do |rel_name|
71
+ @relations_shadow[rel_name] = tracked_relation_attributes(rel_name)
72
+ end
73
+ end
74
+
75
+ def relation_changes
76
+ return {} unless Mongoid::RelationsDirtyTracking.enabled?
77
+ changes = {}
78
+ @relations_shadow.each_pair do |rel_name, shadow_values|
79
+ current_values = tracked_relation_attributes(rel_name)
80
+ changes[rel_name] = [shadow_values, current_values] if current_values != shadow_values
81
+ end
82
+ changes
83
+ end
84
+
85
+ def relations_changed?
86
+ !relation_changes.empty?
87
+ end
88
+
89
+ def changed_with_relations?
90
+ changed? || relations_changed?
91
+ end
92
+
93
+ def changes_with_relations
94
+ (changes || {}).merge(relation_changes)
95
+ end
96
+
97
+ def tracked_relation_attributes(rel_name)
98
+ rel_name = rel_name.to_s
99
+ meta = relations[rel_name]
100
+ return nil unless meta
101
+ case meta
102
+ when Mongoid::Association::Embedded::EmbedsOne
103
+ val = send(rel_name)
104
+ val && val.attributes.clone.delete_if { |key, _| key == 'updated_at' }
105
+ when Mongoid::Association::Embedded::EmbedsMany
106
+ val = send(rel_name)
107
+ val && val.map { |child| child.attributes.clone.delete_if { |key, _| key == 'updated_at' } }
108
+ when Mongoid::Association::Referenced::HasOne
109
+ send(rel_name) && { meta.key.to_s => send(rel_name)[meta.key] }
110
+ when Mongoid::Association::Referenced::HasMany
111
+ send(rel_name).map { |child| { meta.key.to_s => child.id } }
112
+ when Mongoid::Association::Referenced::HasAndBelongsToMany
113
+ send(rel_name).map { |child| { meta.primary_key.to_s => child.id } }
114
+ when Mongoid::Association::Referenced::BelongsTo
115
+ begin
116
+ send(meta.foreign_key) && { meta.foreign_key.to_s => send(meta.foreign_key) }
117
+ rescue ActiveModel::MissingAttributeError
118
+ {}
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -1,5 +1,7 @@
1
- module Mongoid
2
- module RelationsDirtyTracking
3
- VERSION = "0.1.0"
4
- end
5
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Mongoid
4
+ module RelationsDirtyTracking
5
+ VERSION = '0.2.0'
6
+ end
7
+ end
@@ -1,2 +1,3 @@
1
- require "mongoid/relations_dirty_tracking"
2
- require 'mongoid/relations_dirty_tracking/versioning'
1
+ # frozen_string_literal: true
2
+
3
+ require 'mongoid/relations_dirty_tracking'
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec path: '../../'
@@ -0,0 +1,6 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec path: '../../'
4
+
5
+ gem 'activesupport', '~> 5.1.0'
6
+ gem 'mongoid', '~> 7.0.0'