mongoid_denormalize 0.4.2 → 1.0.0

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