mongoid_denormalize 0.4.2 → 1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6081ab30b9501363e07033bda0c9d8905e9fa4ba
4
+ data.tar.gz: 92668ecc79b16a74fb51c9d279c99e48a37a3825
5
+ SHA512:
6
+ metadata.gz: fcbc69ea331a4d5a13e21730742fd72c907f31958cf7a663278df3d67da3dbfd0902f1f0bca7b0281b63c831d7be8407a3a586d00c6eb2759aebb91479b1f522
7
+ data.tar.gz: 3b489b8eb8727cf5cd8b64783e003b509f45c03e871946d2eb7b14146f32503b730d5df246c593d4f2321511cd982e6ef698c7e4534f3c2938fe960d48d7fc39
data/LICENSE CHANGED
@@ -1,20 +1,20 @@
1
- Copyright (c) 2010 Logan Raarup
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
1
+ Copyright (c) 2010 Logan Raarup
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
20
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,161 +1,168 @@
1
- Mongoid::Denormalize
2
- ====================
3
-
4
- *Note: I am no longer actively maintaining this module, and I do not know whether it is compatible with newer versions of mongoid. If you would like to take ownership of this repository, please let me know.*
5
-
6
-
7
- Helper module for denormalizing association attributes in Mongoid models. Why denormalize? Read *[A Note on Denormalization](http://www.mongodb.org/display/DOCS/MongoDB+Data+Modeling+and+Rails#MongoDBDataModelingandRails-ANoteonDenormalization)*.
8
-
9
- Extracted from [coookin'](http://coookin.com), where it is used in production.
10
-
11
-
12
- Installation
13
- ------------
14
-
15
- Add the gem to your Bundler `Gemfile`:
16
-
17
- gem 'mongoid_denormalize'
18
-
19
- Or install with RubyGems:
20
-
21
- $ gem install mongoid_denormalize
22
-
23
-
24
- Usage
25
- -----
26
-
27
- In your model:
28
-
29
- # Include the helper method
30
- include Mongoid::Denormalize
31
-
32
- # Define your denormalized fields
33
- denormalize :name, :email, :from => :user
34
-
35
-
36
- Example
37
- -------
38
-
39
- class User
40
- include Mongoid::Document
41
- include Mongoid::Denormalize
42
-
43
- has_many :comments
44
- has_many :moderated_comments, :class_name => "Comment", :inverse_of => :moderator
45
-
46
- field :name
47
- field :email
48
-
49
- denormalize :name, :email, :to => :comments
50
- end
51
-
52
- class Comment
53
- include Mongoid::Document
54
- include Mongoid::Denormalize
55
-
56
- belongs_to :user
57
- belongs_to :moderator, :class_name => "User", :inverse_of => :moderated_comments
58
-
59
- field :body
60
-
61
- denormalize :name, :email, :from => :user
62
- end
63
-
64
- >> user = User.create(:name => "John Doe", :email => "john@doe.com")
65
- >> comment = Comment.create(:body => "Lorem ipsum...", :user => user)
66
- >> user.comments << comment
67
- >> comment.user_name
68
- "John Doe"
69
- >> comment.user_email
70
- "john@doe.com"
71
- >> user.update_attributes(:name => "Bill")
72
- >> comment.user_name
73
- "Bill"
74
-
75
-
76
- Options
77
- -------
78
-
79
- Denormalization can happen in either or both directions. When using the `:from` option, the associated objects will fetch the values from
80
- the parent. When using the `:to` option, the parent will push the values to its children.
81
-
82
- # Basic denormalization. Will set the user_name attribute of "self.comments" to the value of "self.name".
83
- denormalize :name, :to => :comments
84
-
85
- # Multiple children. Will set the user_name attribute of "self.posts" and "self.comments" with "self.name".
86
- denormalize :name, :to => [:posts, :comments]
87
-
88
- # Basic denormalization, obeying :inverse_of. Will set the moderator_name attribute of "self.moderated_comments"
89
- denormalize :name, :email, :to => :moderated_comments
90
-
91
- # With custom field name prefix. Will set the commenter_name attribute of "self.comments" (takes precedence over
92
- # inverse_of).
93
- denormalize :name, :to => :comments, :as => :commenter
94
-
95
- # Basic denormalization. Will set the user_name attribute with the associated user's name.
96
- denormalize :name, :from => :user
97
-
98
- # Multiple fields. Will set the user_name and user_email attributes with the associated user's name and email.
99
- denormalize :name, :email, :from => :user
100
-
101
- # Basic denormalization. Will set the moderator_name attribute with the associated author user's name.
102
- denormalize :name, :from => :moderator
103
-
104
- When using `:from`, if the type of the denormalized field is anything but `String` (the default),
105
- you must specify the type with the `:type` option.
106
-
107
- # in User
108
- field :location, :type => Array
109
- denormalize :location, :to => :posts
110
-
111
- # in Post
112
- denormalize :location, :type => Array, :from => :user
113
-
114
- A few notes on behavior:
115
-
116
- `:from` denormalizations are processed as `before_save` callbacks.
117
-
118
- `:to` denormalizations are processed as `after_save` callbacks.
119
-
120
- With `:to`, validations are not run on the object(s) containing the denormalized field(s) when they are saved.
121
-
122
- Rake tasks
123
- ----------
124
-
125
- A rake task is included for verifying and repairing inconsistent denormalizations. This might be useful your records may be modified
126
- without Mongoid, or if you are using relational associations in combination with embedded records (see *Known issues*).
127
-
128
- rake db:denormalize
129
-
130
- This task will only update records that have outdated denormalized fields.
131
-
132
-
133
- Known issues
134
- ------------
135
-
136
- **Relational associations in combination with embedded records**
137
-
138
- It is not recommended nor supported to use mongoid_denormalize to perform denormalization to embedded records through a relational association because
139
- MongoDB/Mongoid do not support direct access to embedded fields via a relational association.
140
-
141
- So, if User has_many :posts and User has_many :comments, but Comments are embedded_in :post, a user can't directly access a comment.
142
-
143
- Contributing
144
- -------
145
-
146
- Clone the repository and run Bundler with `bundle install`. Use `rake -T` to view available rake tasks.
147
-
148
- Contributors
149
- -------
150
- * hubsmoke (https://github.com/hubsmoke)
151
- * Leo Lou (https://github.com/l4u)
152
- * Austin Bales (https://github.com/arbales)
153
- * Isaac Cambron (https://github.com/icambron)
154
- * Shannon Carey (https://github.com/rehevkor5)
155
- * Sebastien Azimi (https://github.com/suruja)
156
-
157
-
158
- Credits
159
- -------
160
-
161
- Copyright (c) 2010 Logan Raarup, released under the MIT license.
1
+ Mongoid::Denormalize
2
+ ====================
3
+
4
+ *Note: I am no longer actively maintaining this module, and I do not know whether it is compatible with newer versions of mongoid. If you would like to take ownership of this repository, please let me know.*
5
+
6
+
7
+ Helper module for denormalizing association attributes in Mongoid models. Why denormalize? Read *[A Note on Denormalization](http://www.mongodb.org/display/DOCS/MongoDB+Data+Modeling+and+Rails#MongoDBDataModelingandRails-ANoteonDenormalization)*.
8
+
9
+ Extracted from [coookin'](http://coookin.com), where it is used in production.
10
+
11
+
12
+ Installation
13
+ ------------
14
+
15
+ Add the gem to your Bundler `Gemfile`:
16
+
17
+ gem 'mongoid_denormalize'
18
+
19
+ Or install with RubyGems:
20
+
21
+ $ gem install mongoid_denormalize
22
+
23
+
24
+ Usage
25
+ -----
26
+
27
+ In your model:
28
+
29
+ # Include the helper method
30
+ include Mongoid::Denormalize
31
+
32
+ # Define your denormalized fields
33
+ denormalize :name, :email, :from => :user
34
+
35
+
36
+ Example
37
+ -------
38
+
39
+ class User
40
+ include Mongoid::Document
41
+ include Mongoid::Denormalize
42
+
43
+ has_many :comments
44
+ has_many :moderated_comments, :class_name => "Comment", :inverse_of => :moderator
45
+
46
+ field :name
47
+ field :email
48
+
49
+ denormalize :name, :email, :to => :comments
50
+ end
51
+
52
+ class Comment
53
+ include Mongoid::Document
54
+ include Mongoid::Denormalize
55
+
56
+ belongs_to :user
57
+ belongs_to :moderator, :class_name => "User", :inverse_of => :moderated_comments
58
+
59
+ field :body
60
+
61
+ denormalize :name, :email, :from => :user
62
+ end
63
+
64
+ >> user = User.create(:name => "John Doe", :email => "john@doe.com")
65
+ >> comment = Comment.create(:body => "Lorem ipsum...", :user => user)
66
+ >> user.comments << comment
67
+ >> comment.user_name
68
+ "John Doe"
69
+ >> comment.user_email
70
+ "john@doe.com"
71
+ >> user.update_attributes(:name => "Bill")
72
+ >> comment.user_name
73
+ "Bill"
74
+
75
+
76
+ Options
77
+ -------
78
+
79
+ Denormalization can happen in either or both directions. When using the `:from` option, the associated objects will fetch the values from
80
+ the parent. When using the `:to` option, the parent will push the values to its children.
81
+
82
+ # Basic denormalization. Will set the user_name attribute of "self.comments" to the value of "self.name".
83
+ denormalize :name, :to => :comments
84
+
85
+ # Multiple children. Will set the user_name attribute of "self.posts" and "self.comments" with "self.name".
86
+ denormalize :name, :to => [:posts, :comments]
87
+
88
+ # Basic denormalization, obeying :inverse_of. Will set the moderator_name attribute of "self.moderated_comments"
89
+ denormalize :name, :email, :to => :moderated_comments
90
+
91
+ # With custom field name prefix. Will set the commenter_name attribute of "self.comments" (takes precedence over
92
+ # inverse_of).
93
+ denormalize :name, :to => :comments, :as => :commenter
94
+ denormalize :name, :from => :comments, :as => :commenter
95
+
96
+ # Basic denormalization. Will set the user_name attribute with the associated user's name.
97
+ denormalize :name, :from => :user
98
+
99
+ # Multiple fields. Will set the user_name and user_email attributes with the associated user's name and email.
100
+ denormalize :name, :email, :from => :user
101
+
102
+ # Basic denormalization. Will set the moderator_name attribute with the associated author user's name.
103
+ denormalize :name, :from => :moderator
104
+
105
+ When using `:from`, if the type of the denormalized field is anything but `String` (the default),
106
+ you must specify the type with the `:type` option.
107
+
108
+ # in User
109
+ field :location, :type => Array
110
+ denormalize :location, :to => :posts
111
+
112
+ # in Post
113
+ denormalize :location, :type => Array, :from => :user
114
+
115
+ A few notes on behavior:
116
+
117
+ `:from` denormalizations are processed as `before_save` callbacks.
118
+
119
+ `:to` denormalizations are processed as `after_save` callbacks.
120
+
121
+ With `:to`, validations are not run on the object(s) containing the denormalized field(s) when they are saved.
122
+
123
+ Rake tasks
124
+ ----------
125
+
126
+ A rake task is included for verifying and repairing inconsistent denormalizations. This might be useful your records may be modified
127
+ without Mongoid, or if you are using relational associations in combination with embedded records (see *Known issues*).
128
+
129
+ rake db:denormalize
130
+
131
+ This task will only update records that have outdated denormalized fields.
132
+
133
+
134
+ Known issues
135
+ ------------
136
+
137
+ **Relational associations in combination with embedded records**
138
+
139
+ It is not recommended nor supported to use mongoid_denormalize to perform denormalization to embedded records through a relational association because
140
+ MongoDB/Mongoid do not support direct access to embedded fields via a relational association.
141
+
142
+ So, if User has_many :posts and User has_many :comments, but Comments are embedded_in :post, a user can't directly access a comment.
143
+
144
+ Contributing
145
+ -------
146
+
147
+ Clone the repository and run Bundler with `bundle install`. Use `rake -T` to view available rake tasks.
148
+
149
+ You can also use `bundle exec guard` for test driven development, if desired.
150
+
151
+ A MongoDB server is required to run the specs. Docker is an easy option:
152
+
153
+ docker run --name mongo3 -d -p 27017:27017 mongo
154
+
155
+ Contributors
156
+ -------
157
+ * hubsmoke (https://github.com/hubsmoke)
158
+ * Leo Lou (https://github.com/l4u)
159
+ * Austin Bales (https://github.com/arbales)
160
+ * Isaac Cambron (https://github.com/icambron)
161
+ * Shannon Carey (https://github.com/rehevkor5)
162
+ * Sebastien Azimi (https://github.com/suruja)
163
+ * HuffMoody (https://github.com/HuffMoody)
164
+
165
+ Credits
166
+ -------
167
+
168
+ Copyright (c) 2010 Logan Raarup, released under the MIT license.
@@ -1,120 +1,121 @@
1
- require 'mongoid_denormalize/version'
2
- require File.dirname(__FILE__) + '/railties/railtie' if defined?(Rails::Railtie)
3
-
4
- # = Mongoid::Denormalize
5
- #
6
- # Helper module for denormalizing association attributes in Mongoid models.
7
- module Mongoid::Denormalize
8
- extend ActiveSupport::Concern
9
-
10
- included do
11
- cattr_accessor :denormalize_definitions
12
-
13
- before_save :denormalize_from
14
- after_save :denormalize_to
15
- end
16
-
17
- module ClassMethods
18
- # Set a field or a number of fields to denormalize. Specify the associated object using the :from or :to options.
19
- #
20
- # def Post
21
- # include Mongoid::Document
22
- # include Mongoid::Denormalize
23
- #
24
- # referenced_in :user
25
- # references_many :comments
26
- #
27
- # denormalize :name, :avatar, :from => :user
28
- # denormalize :created_at, :to => :comments
29
- # end
30
- def denormalize(*args)
31
- *fields, options = args
32
-
33
- (self.denormalize_definitions ||= []) << { :fields => fields, :options => options }
34
-
35
- # Define schema
36
- unless options[:to]
37
- fields.each { |name| field "#{options[:from]}_#{name}", :type => options[:type] || String }
38
- end
39
- end
40
-
41
- def is_denormalized?
42
- true
43
- end
44
- end
45
-
46
- def denormalized_valid?
47
- denormalize_from
48
- !self.changed?
49
- end
50
-
51
- def repair_denormalized!
52
- self.save! unless denormalized_valid?
53
- end
54
-
55
- private
56
- def denormalize_from
57
- Array(self.denormalize_definitions).reject do |definition|
58
- definition[:options][:to]
59
- end.each do |definition|
60
- definition[:fields].each do |name|
61
- field = definition[:options][:from]
62
- # force reload if :from method is an association ; call it normally otherwise
63
- associated = self.class.reflect_on_association(field) ? self.send(field, true) : self.send(field)
64
- self.send("#{field}_#{name}=", associated.try(name))
65
- end
66
- end
67
- end
68
-
69
- def denormalize_to
70
- Array(self.denormalize_definitions).find_all do |definition|
71
- definition[:options][:to]
72
- end.each do |definition|
73
- as = definition[:options][:as]
74
-
75
- assignments = definition[:fields].collect do |source_field|
76
- {
77
- :source_field => source_field.to_s,
78
- :value => self.send(source_field)
79
- }
80
- end
81
-
82
- Array(definition[:options][:to]).each do |association|
83
- relation = []
84
- reflect = self.class.reflect_on_association(association)
85
- relation = reflect.relation.macro unless reflect.nil? || reflect.relation.nil?
86
-
87
- reflect.klass.skip_callback(:save, :before, :denormalize_from) if reflect.klass.try(:is_denormalized?)
88
-
89
- associated = self.send(association)
90
- prefix = (as || reflect.inverse_of || reflect.inverse_class_name).to_s.underscore
91
-
92
- if [:embedded_in, :embeds_one, :referenced_in, :references_one, :has_one, :belongs_to].include? relation
93
- unless associated.blank?
94
- assign_and_save(associated, assignments, prefix)
95
- end
96
- else
97
- associated.to_a.each { |c| assign_and_save(c, assignments, prefix) }
98
- end
99
-
100
- reflect.klass.set_callback(:save, :before, :denormalize_from) if reflect.klass.try(:is_denormalized?)
101
- end
102
- end
103
- end
104
-
105
- def assign_and_save(obj, assignments, prefix)
106
- attributes_hash = Hash[assignments.collect { |assignment|
107
- if self.changed_attributes.has_key?(assignment[:source_field].to_s) ||
108
- self.changed_attributes.has_key?(assignment[:source_field].to_sym)
109
- ["#{prefix}_#{assignment[:source_field]}", assignment[:value]]
110
- end
111
- }.compact]
112
-
113
- unless attributes_hash.empty?
114
- # The more succinct update_attributes(changes, :without_protection => true) requires Mongoid 3.0.0,
115
- # but we only require 2.1.9
116
- obj.write_attributes(attributes_hash, false)
117
- obj.save(:validate => false)
118
- end
119
- end
120
- end
1
+ require 'mongoid_denormalize/version'
2
+ require File.dirname(__FILE__) + '/railties/railtie' if defined?(Rails::Railtie)
3
+
4
+ # = Mongoid::Denormalize
5
+ #
6
+ # Helper module for denormalizing association attributes in Mongoid models.
7
+ module Mongoid::Denormalize
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ cattr_accessor :denormalize_definitions
12
+
13
+ before_save :denormalize_from
14
+ after_save :denormalize_to
15
+ end
16
+
17
+ module ClassMethods
18
+ # Set a field or a number of fields to denormalize. Specify the associated object using the :from or :to options.
19
+ #
20
+ # def Post
21
+ # include Mongoid::Document
22
+ # include Mongoid::Denormalize
23
+ #
24
+ # referenced_in :user
25
+ # references_many :comments
26
+ #
27
+ # denormalize :name, :avatar, :from => :user
28
+ # denormalize :created_at, :to => :comments
29
+ # end
30
+ def denormalize(*args)
31
+ *fields, options = args
32
+
33
+ (self.denormalize_definitions ||= []) << { :fields => fields, :options => options }
34
+
35
+ # Define schema
36
+ unless options[:to]
37
+ prefix = options[:as] || options[:from]
38
+ fields.each do |name|
39
+ field "#{prefix}_#{name}", :type => options[:type] || String
40
+ end
41
+ end
42
+ end
43
+
44
+ def is_denormalized?
45
+ true
46
+ end
47
+ end
48
+
49
+ def denormalized_valid?
50
+ denormalize_from
51
+ !self.changed?
52
+ end
53
+
54
+ def repair_denormalized!
55
+ self.save! unless denormalized_valid?
56
+ end
57
+
58
+ private
59
+ def denormalize_from
60
+ Array(self.denormalize_definitions).reject do |definition|
61
+ definition[:options][:to]
62
+ end.each do |definition|
63
+ definition[:fields].each do |field|
64
+ association = definition[:options][:from]
65
+ prefix = definition[:options][:as] || definition[:options][:from]
66
+ # force reload if :from method is an association ; call it normally otherwise
67
+ associated = self.class.reflect_on_association(association) ? self.send(association, true) : self.send(association)
68
+ self.send("#{prefix}_#{field}=", associated.try(field))
69
+ end
70
+ end
71
+ end
72
+
73
+ def denormalize_to
74
+ Array(self.denormalize_definitions).find_all do |definition|
75
+ definition[:options][:to]
76
+ end.each do |definition|
77
+ as = definition[:options][:as]
78
+
79
+ assignments = definition[:fields].collect do |source_field|
80
+ {
81
+ :source_field => source_field.to_s,
82
+ :value => self.send(source_field)
83
+ }
84
+ end
85
+
86
+ Array(definition[:options][:to]).each do |association|
87
+ relation = []
88
+ reflect = self.class.reflect_on_association(association)
89
+ relation = reflect.relation.macro unless reflect.nil? || reflect.relation.nil?
90
+
91
+ reflect.klass.skip_callback(:save, :before, :denormalize_from) if reflect.klass.try(:is_denormalized?)
92
+
93
+ associated = self.send(association)
94
+ prefix = (as || reflect.inverse_of || reflect.inverse_class_name).to_s.underscore
95
+
96
+ if [:embedded_in, :embeds_one, :referenced_in, :references_one, :has_one, :belongs_to].include? relation
97
+ unless associated.blank?
98
+ assign_and_save(associated, assignments, prefix)
99
+ end
100
+ else
101
+ associated.to_a.each { |c| assign_and_save(c, assignments, prefix) }
102
+ end
103
+
104
+ reflect.klass.set_callback(:save, :before, :denormalize_from) if reflect.klass.try(:is_denormalized?)
105
+ end
106
+ end
107
+ end
108
+
109
+ def assign_and_save(obj, assignments, prefix)
110
+ attributes_hash = Hash[assignments.collect { |assignment|
111
+ if self.changed_attributes.has_key?(assignment[:source_field].to_s) ||
112
+ self.changed_attributes.has_key?(assignment[:source_field].to_sym)
113
+ ["#{prefix}_#{assignment[:source_field]}", assignment[:value]]
114
+ end
115
+ }.compact]
116
+
117
+ unless attributes_hash.empty?
118
+ obj.update_attributes(attributes_hash)
119
+ end
120
+ end
121
+ end
@@ -1,5 +1,5 @@
1
- module Mongoid
2
- module Denormalize
3
- VERSION = '0.4.2'
4
- end
5
- end
1
+ module Mongoid
2
+ module Denormalize
3
+ VERSION = '1.0.0'
4
+ end
5
+ end
@@ -1,39 +1,39 @@
1
- namespace :db do
2
- desc "Verify all denormalizations and repair any inconsistencies"
3
- task :denormalize => :environment do
4
- get_denormalizable_models.each do |klass|
5
- if klass.embedded?
6
- reflection = klass.reflect_on_all_associations(:embedded_in).first
7
- parent = reflection.class_name.to_s.classify.constantize
8
-
9
- unless parent.embedded?
10
- parent.all.each do |parent_instance|
11
- parent_instance.send(reflection.inverse).each(&:repair_denormalized!)
12
- end
13
- end
14
- else
15
- klass.all.each do |instance|
16
- instance.repair_denormalized!
17
- end
18
- end
19
- end
20
- end
21
-
22
- def get_denormalizable_models
23
- documents = []
24
- Dir.glob("app/models/**/*.rb").sort.each do |file|
25
- model_path = file[0..-4].split('/')[2..-1]
26
- begin
27
- klass = model_path.map(&:classify).join('::').constantize
28
-
29
- if klass.ancestors.include?(Mongoid::Document) && klass.ancestors.include?(Mongoid::Denormalize)
30
- documents << klass
31
- end
32
- rescue => e
33
- # Just for non-mongoid objects that dont have the embedded
34
- # attribute at the class level.
35
- end
36
- end
37
- documents
38
- end
1
+ namespace :db do
2
+ desc "Verify all denormalizations and repair any inconsistencies"
3
+ task :denormalize => :environment do
4
+ get_denormalizable_models.each do |klass|
5
+ if klass.embedded?
6
+ reflection = klass.reflect_on_all_associations(:embedded_in).first
7
+ parent = reflection.class_name.to_s.classify.constantize
8
+
9
+ unless parent.embedded?
10
+ parent.all.each do |parent_instance|
11
+ parent_instance.send(reflection.inverse).each(&:repair_denormalized!)
12
+ end
13
+ end
14
+ else
15
+ klass.all.each do |instance|
16
+ instance.repair_denormalized!
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ def get_denormalizable_models
23
+ documents = []
24
+ Dir.glob("app/models/**/*.rb").sort.each do |file|
25
+ model_path = file[0..-4].split('/')[2..-1]
26
+ begin
27
+ klass = model_path.map(&:classify).join('::').constantize
28
+
29
+ if klass.ancestors.include?(Mongoid::Document) && klass.ancestors.include?(Mongoid::Denormalize)
30
+ documents << klass
31
+ end
32
+ rescue => e
33
+ # Just for non-mongoid objects that dont have the embedded
34
+ # attribute at the class level.
35
+ end
36
+ end
37
+ documents
38
+ end
39
39
  end
@@ -1,9 +1,9 @@
1
- require 'rails'
2
-
3
- module Mongoid::Denormalize
4
- class Railtie < Rails::Railtie
5
- rake_tasks do
6
- load 'railties/denormalize.rake'
7
- end
8
- end
1
+ require 'rails'
2
+
3
+ module Mongoid::Denormalize
4
+ class Railtie < Rails::Railtie
5
+ rake_tasks do
6
+ load 'railties/denormalize.rake'
7
+ end
8
+ end
9
9
  end
@@ -1,150 +1,146 @@
1
- require "spec_helper"
2
-
3
- describe Mongoid::Denormalize do
4
- before(:each) do
5
- @post = Post.create!(:title => "Blog post", :body => "Lorem ipsum...", :created_at => Time.parse("Jan 1 2010 12:00"))
6
- @user = User.create!(:name => "John Doe", :email => "john@doe.com", :post => @post, :location => [1, 1], :nickname => "jdoe")
7
- @comment = @post.comments.create(:body => "This is the comment", :user => @user)
8
- @post.reload #neccessary for older versions of Mongoid
9
- @moderated_comment = @post.comments.create(:body => "This is a moderated comment", :moderator => @user)
10
- @article = @user.articles.create!(:title => "Article about Lorem", :body => "Lorem ipsum...", :created_at => Time.parse("Jan 1 2010 12:00"))
11
-
12
- @user.comments << @comment
13
- @user.moderated_comments << @moderated_comment
14
- @user.save
15
- @user.reload
16
- @other_user = User.create!(:name => "Bill")
17
- end
18
-
19
- context "denormalize from" do
20
- it "should define multiple fields for association" do
21
- @post.fields.should have_key "user_name"
22
- @post.fields.should have_key "user_email"
23
- @post.fields.should have_key "user_location"
24
- end
25
-
26
- it "should default to string field type for associated fields" do
27
- @post.fields["user_name"].type.should eql String
28
- end
29
-
30
- it "should allow setting the field type for associated fields" do
31
- @comment.fields["post_created_at"].type.should eql Time
32
- end
33
-
34
- it "should allow multiple declarations for the same association" do
35
- @comment.fields.should have_key "user_name"
36
- @comment.fields.should have_key "user_email"
37
- end
38
-
39
- it "should denormalize fields without specified type" do
40
- @comment.user_name.should eql @user.name
41
- @comment.user_email.should eql @user.email
42
- @post.user_name.should eql @user.name
43
- @post.user_email.should eql @user.email
44
- end
45
-
46
- it "should denormalize fields with specified type" do
47
- @comment.post_created_at.should eql @post.created_at
48
-
49
- @post.user_location.should eql @user.location
50
- end
51
-
52
- it "should use fresh values from database where possible" do
53
- @other_post = Post.create!(:title => "My first blog post")
54
- @other_post.update_attribute(:user_id, @user.id)
55
- @other_post.user_name.should eql @user.name
56
- end
57
-
58
- it "should update denormalized values if attribute is changed" do
59
- @user.update_attributes(:name => "Bob Doe", :location => [4, 4])
60
-
61
- @post.reload #needed for old versions of Mongoid
62
- @post.user_location.should eql @user.location
63
-
64
- @comment.reload #needed for old versions of Mongoid
65
- @comment.user_name.should eql @user.name
66
- end
67
-
68
- it "should update denormalized values if object is changed" do
69
- @other_user = User.create!(:name => "Bill", :email => "bill@doe.com")
70
-
71
- @comment.user = @other_user
72
- @comment.save!
73
-
74
- @comment.user_name.should eql @other_user.name
75
- @comment.user_email.should eql @other_user.email
76
- end
77
- end
78
-
79
- context "denormalize to" do
80
- it "should push denormalized fields to one-to-one association" do
81
- @user.name = "Elvis"
82
- @user.save!
83
-
84
- @post.reload #needed for old versions of Mongoid
85
- @post.user_name.should eql "Elvis"
86
- end
87
-
88
- it "should push denormalized fields to one-to-many association" do
89
- @post.created_at = Time.parse("Jan 1 2011 12:00")
90
- @post.save!
91
-
92
- @comment.reload #needed for old versions of Mongoid
93
- @comment.post_created_at.should eql Time.parse("Jan 1 2011 12:00")
94
- end
95
-
96
- it "should push denormalized fields to association using inverse_of class name" do
97
- @user.update_attributes(:name => "Bob Doe", :email => "bob@doe.com")
98
- @user.save!
99
-
100
- @article.reload #needed for old versions of Mongoid
101
- @article.author_name.should eql "Bob Doe"
102
- @article.author_email.should eql "bob@doe.com"
103
- end
104
-
105
- it "should push to overriden field names" do
106
- @user.nickname = "jonsey"
107
- @user.save!
108
-
109
- @moderated_comment.reload
110
- @moderated_comment.mod_nickname.should eql "jonsey"
111
- end
112
-
113
- it "shouldn't make superfluous saves" do
114
- @comment.should_not_receive(:save)
115
- @post.save!
116
- end
117
- end
118
-
119
- context "rake task" do
120
- it "should correct inconsistent denormalizations on regular documents" do
121
- if ::Mongoid::VERSION < '3'
122
- Post.collection.update({ '_id' => @post.id }, { '$set' => { 'user_name' => 'Clint Eastwood' } })
123
- else
124
- @post.set(:user_name, 'Clint Eastwood')
125
- end
126
-
127
- @post.reload #needed for old versions of Mongoid
128
- @post.user_name.should eq 'Clint Eastwood'
129
-
130
- Rake::Task["db:denormalize"].invoke
131
- Rake::Task["db:denormalize"].reenable
132
-
133
- @post.reload
134
- @post.user_name.should eql @user.name
135
- end
136
-
137
- it "should correct inconsistent denormalizations on referenced embedded documents" do
138
- @rake_user = User.create!(:name => "Johnny Depp", :email => "johnny@depp.com")
139
- @rake_comment = @post.comments.create!(:body => "Depp's comment", :user => @rake_user)
140
-
141
- @rake_user.update_attributes!(:name => "J. Depp")
142
-
143
- Rake::Task["db:denormalize"].invoke
144
- Rake::Task["db:denormalize"].reenable
145
-
146
- @post.reload
147
- @post.comments.last.user_name.should eql @rake_user.name
148
- end
149
- end
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Denormalize do
4
+ before(:each) do
5
+ @post = Post.create!(:title => "Blog post", :body => "Lorem ipsum...", :created_at => Time.parse("Jan 1 2010 12:00"))
6
+ @user = User.create!(:name => "John Doe", :email => "john@doe.com", :post => @post, :location => [1, 1], :nickname => "jdoe")
7
+ @comment = @post.comments.create(:body => "This is the comment", :user => @user)
8
+ @post.reload #neccessary for older versions of Mongoid
9
+ @moderated_comment = @post.comments.create(:body => "This is a moderated comment", :moderator => @user)
10
+ @article = @user.articles.create!(:title => "Article about Lorem", :body => "Lorem ipsum...", :created_at => Time.parse("Jan 1 2010 12:00"))
11
+
12
+ @user.comments << @comment
13
+ @user.moderated_comments << @moderated_comment
14
+ @user.save
15
+ @user.reload
16
+ @other_user = User.create!(:name => "Bill")
17
+ end
18
+
19
+ context "denormalize from" do
20
+ it "should define multiple fields for association" do
21
+ @post.fields.should have_key "user_name"
22
+ @post.fields.should have_key "user_email"
23
+ @post.fields.should have_key "user_location"
24
+ end
25
+
26
+ it "should default to string field type for associated fields" do
27
+ @post.fields["user_name"].type.should eql String
28
+ end
29
+
30
+ it "should allow setting the field type for associated fields" do
31
+ @comment.fields["post_created_at"].type.should eql Time
32
+ end
33
+
34
+ it "should allow multiple declarations for the same association" do
35
+ @comment.fields.should have_key "user_name"
36
+ @comment.fields.should have_key "user_email"
37
+ end
38
+
39
+ it "should denormalize fields without specified type" do
40
+ @comment.user_name.should eql @user.name
41
+ @comment.user_email.should eql @user.email
42
+ @post.user_name.should eql @user.name
43
+ @post.user_email.should eql @user.email
44
+ end
45
+
46
+ it "should denormalize fields with specified type" do
47
+ @comment.post_created_at.should eql @post.created_at
48
+
49
+ @post.user_location.should eql @user.location
50
+ end
51
+
52
+ it "should use fresh values from database where possible" do
53
+ @other_post = Post.create!(:title => "My first blog post")
54
+ @other_post.update_attribute(:user_id, @user.id)
55
+ @other_post.user_name.should eql @user.name
56
+ end
57
+
58
+ it "should update denormalized values if attribute is changed" do
59
+ @user.update_attributes(:name => "Bob Doe", :location => [4, 4])
60
+
61
+ @post.reload #needed for old versions of Mongoid
62
+ @post.user_location.should eql @user.location
63
+
64
+ @comment.reload #needed for old versions of Mongoid
65
+ @comment.user_name.should eql @user.name
66
+ end
67
+
68
+ it "should update denormalized values if object is changed" do
69
+ @other_user = User.create!(:name => "Bill", :email => "bill@doe.com")
70
+
71
+ @comment.user = @other_user
72
+ @comment.save!
73
+
74
+ @comment.user_name.should eql @other_user.name
75
+ @comment.user_email.should eql @other_user.email
76
+ end
77
+ end
78
+
79
+ context "denormalize to" do
80
+ it "should push denormalized fields to one-to-one association" do
81
+ @user.name = "Elvis"
82
+ @user.save!
83
+
84
+ @post.reload #needed for old versions of Mongoid
85
+ @post.user_name.should eql "Elvis"
86
+ end
87
+
88
+ it "should push denormalized fields to one-to-many association" do
89
+ @post.created_at = Time.parse("Jan 1 2011 12:00")
90
+ @post.save!
91
+
92
+ @comment.reload #needed for old versions of Mongoid
93
+ @comment.post_created_at.should eql Time.parse("Jan 1 2011 12:00")
94
+ end
95
+
96
+ it "should push denormalized fields to association using inverse_of class name" do
97
+ @user.update_attributes(:name => "Bob Doe", :email => "bob@doe.com")
98
+ @user.save!
99
+
100
+ @article.reload #needed for old versions of Mongoid
101
+ @article.author_name.should eql "Bob Doe"
102
+ @article.author_email.should eql "bob@doe.com"
103
+ end
104
+
105
+ it "should push to overriden field names" do
106
+ @user.nickname = "jonsey"
107
+ @user.save!
108
+
109
+ @moderated_comment.reload
110
+ @moderated_comment.mod_nickname.should eql "jonsey"
111
+ end
112
+
113
+ it "shouldn't make superfluous saves" do
114
+ @comment.should_not_receive(:save)
115
+ @post.save!
116
+ end
117
+ end
118
+
119
+ context "rake task" do
120
+ it "should correct inconsistent denormalizations on regular documents" do
121
+ @post.set(:user_name => 'Clint Eastwood')
122
+
123
+ @post.reload #needed for old versions of Mongoid
124
+ @post.user_name.should eq 'Clint Eastwood'
125
+
126
+ Rake::Task["db:denormalize"].invoke
127
+ Rake::Task["db:denormalize"].reenable
128
+
129
+ @post.reload
130
+ @post.user_name.should eql @user.name
131
+ end
132
+
133
+ it "should correct inconsistent denormalizations on referenced embedded documents" do
134
+ @rake_user = User.create!(:name => "Johnny Depp", :email => "johnny@depp.com")
135
+ @rake_comment = @post.comments.create!(:body => "Depp's comment", :user => @rake_user)
136
+
137
+ @rake_user.update_attributes!(:name => "J. Depp")
138
+
139
+ Rake::Task["db:denormalize"].invoke
140
+ Rake::Task["db:denormalize"].reenable
141
+
142
+ @post.reload
143
+ @post.comments.last.user_name.should eql @rake_user.name
144
+ end
145
+ end
150
146
  end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid_denormalize
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
5
- prerelease:
4
+ version: 1.0.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Logan Raarup
@@ -14,51 +13,45 @@ dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rake
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - ">="
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: guard-rspec
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - ">="
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - ">="
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: mongoid
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - ">="
52
46
  - !ruby/object:Gem::Version
53
- version: 2.1.9
47
+ version: 4.0.0
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - ">="
60
53
  - !ruby/object:Gem::Version
61
- version: 2.1.9
54
+ version: 4.0.0
62
55
  description: Helper module for denormalizing association attributes in Mongoid models.
63
56
  email: logan@logan.dk
64
57
  executables: []
@@ -67,37 +60,33 @@ extra_rdoc_files:
67
60
  - LICENSE
68
61
  - README.md
69
62
  files:
63
+ - LICENSE
64
+ - README.md
70
65
  - lib/mongoid_denormalize.rb
71
66
  - lib/mongoid_denormalize/version.rb
72
67
  - lib/railties/denormalize.rake
73
68
  - lib/railties/railtie.rb
74
- - LICENSE
75
- - README.md
76
69
  - spec/mongoid_denormalize_spec.rb
77
70
  homepage: http://github.com/logandk/mongoid_denormalize
78
71
  licenses: []
72
+ metadata: {}
79
73
  post_install_message:
80
74
  rdoc_options: []
81
75
  require_paths:
82
76
  - lib
83
77
  required_ruby_version: !ruby/object:Gem::Requirement
84
- none: false
85
78
  requirements:
86
- - - ! '>='
79
+ - - ">="
87
80
  - !ruby/object:Gem::Version
88
81
  version: '0'
89
- segments:
90
- - 0
91
- hash: -889189390443941496
92
82
  required_rubygems_version: !ruby/object:Gem::Requirement
93
- none: false
94
83
  requirements:
95
- - - ! '>='
84
+ - - ">="
96
85
  - !ruby/object:Gem::Version
97
86
  version: '0'
98
87
  requirements: []
99
88
  rubyforge_project:
100
- rubygems_version: 1.8.25
89
+ rubygems_version: 2.4.5
101
90
  signing_key:
102
91
  specification_version: 3
103
92
  summary: Mongoid denormalization helper.