mongoid_denormalize 0.3.0 → 0.4.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.
Files changed (3) hide show
  1. data/README.md +40 -10
  2. data/lib/mongoid_denormalize.rb +62 -42
  3. metadata +118 -48
data/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  Mongoid::Denormalize
2
2
  ====================
3
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
+
4
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)*.
5
8
 
6
9
  Extracted from [coookin'](http://coookin.com), where it is used in production.
@@ -30,7 +33,6 @@ In your model:
30
33
  denormalize :name, :email, :from => :user
31
34
 
32
35
 
33
-
34
36
  Example
35
37
  -------
36
38
 
@@ -39,6 +41,7 @@ Example
39
41
  include Mongoid::Denormalize
40
42
 
41
43
  has_many :comments
44
+ has_many :moderated_comments, :class_name => "Comment", :inverse_of => :moderator
42
45
 
43
46
  field :name
44
47
  field :email
@@ -51,6 +54,7 @@ Example
51
54
  include Mongoid::Denormalize
52
55
 
53
56
  belongs_to :user
57
+ belongs_to :moderator, :class_name => "User", :inverse_of => :moderated_comments
54
58
 
55
59
  field :body
56
60
 
@@ -75,20 +79,31 @@ Options
75
79
  Denormalization can happen in either or both directions. When using the `:from` option, the associated objects will fetch the values from
76
80
  the parent. When using the `:to` option, the parent will push the values to its children.
77
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
+
78
95
  # Basic denormalization. Will set the user_name attribute with the associated user's name.
79
96
  denormalize :name, :from => :user
80
-
81
- # Basic denormalization. Will set the user_name attribute of "self.comments" with "self.name".
82
- denormalize :name, :to => :comments
83
-
97
+
84
98
  # Multiple fields. Will set the user_name and user_email attributes with the associated user's name and email.
85
99
  denormalize :name, :email, :from => :user
86
-
87
- # Multiple children. Will set the user_name attribute of "self.posts" and "self.comments" with "self.name".
88
- denormalize :name, :to => [:posts, :comments]
89
100
 
90
- You must specify the type of all denormalizations when using the `:from` option, unless the denormalized type is `String`, the default.
91
-
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
+
92
107
  # in User
93
108
  field :location, :type => Array
94
109
  denormalize :location, :to => :posts
@@ -96,6 +111,14 @@ You must specify the type of all denormalizations when using the `:from` option,
96
111
  # in Post
97
112
  denormalize :location, :type => Array, :from => :user
98
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
+
99
122
  Rake tasks
100
123
  ----------
101
124
 
@@ -117,12 +140,19 @@ It is not recommended nor supported to use mongoid_denormalize to perform denorm
117
140
 
118
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.
119
142
 
143
+ Contributing
144
+ -------
145
+
146
+ Clone the repository and run Bundler with `bundle install` so that you can run the rake tasks.
120
147
 
121
148
  Contributors
122
149
  -------
123
150
  * hubsmoke (https://github.com/hubsmoke)
124
151
  * Leo Lou (https://github.com/l4u)
125
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)
126
156
 
127
157
 
128
158
  Credits
@@ -5,10 +5,10 @@ require File.dirname(__FILE__) + '/railties/railtie' if defined?(Rails::Railtie)
5
5
  # Helper module for denormalizing association attributes in Mongoid models.
6
6
  module Mongoid::Denormalize
7
7
  extend ActiveSupport::Concern
8
-
8
+
9
9
  included do
10
10
  cattr_accessor :denormalize_definitions
11
-
11
+
12
12
  before_save :denormalize_from
13
13
  after_save :denormalize_to
14
14
  end
@@ -26,8 +26,8 @@ module Mongoid::Denormalize
26
26
  # denormalize :name, :avatar, :from => :user
27
27
  # denormalize :created_at, :to => :comments
28
28
  # end
29
- def denormalize(*fields)
30
- options = fields.pop
29
+ def denormalize(*args)
30
+ *fields, options = args
31
31
 
32
32
  (self.denormalize_definitions ||= []) << { :fields => fields, :options => options }
33
33
 
@@ -36,7 +36,7 @@ module Mongoid::Denormalize
36
36
  fields.each { |name| field "#{options[:from]}_#{name}", :type => options[:type] || String }
37
37
  end
38
38
  end
39
-
39
+
40
40
  def is_denormalized?
41
41
  true
42
42
  end
@@ -50,49 +50,69 @@ module Mongoid::Denormalize
50
50
  def repair_denormalized!
51
51
  self.save! unless denormalized_valid?
52
52
  end
53
-
53
+
54
54
  private
55
- def denormalize_from
56
- self.denormalize_definitions.each do |definition|
57
- next if definition[:options][:to]
58
-
59
- definition[:fields].each { |name| self.send("#{definition[:options][:from]}_#{name}=", self.send(definition[:options][:from]).try(name)) }
55
+ def denormalize_from
56
+ Array(self.denormalize_definitions).reject do |definition|
57
+ definition[:options][:to]
58
+ end.each do |definition|
59
+ definition[:fields].each do |name|
60
+ field = definition[:options][:from]
61
+ # force reload if :from method is an association ; call it normally otherwise
62
+ associated = self.class.reflect_on_association(field) ? self.send(field, true) : self.send(field)
63
+ self.send("#{field}_#{name}=", associated.try(name))
60
64
  end
61
65
  end
62
-
63
- def denormalize_to
64
- self.denormalize_definitions.each do |definition|
65
- next unless definition[:options][:to]
66
- assigns = Hash[*definition[:fields].collect { |name| ["#{self.class.name.underscore}_#{name}", self.send(name)] }.flatten(1)]
67
-
68
-
69
- [definition[:options][:to]].flatten.each do |association|
70
- relation = []
71
- reflect = self.class.reflect_on_association(association)
72
- relation = reflect.relation.macro unless reflect.nil? || reflect.relation.nil?
66
+ end
73
67
 
74
- reflect.klass.skip_callback(:save, :before, :denormalize_from) if reflect.klass.try(:is_denormalized?)
68
+ def denormalize_to
69
+ Array(self.denormalize_definitions).find_all do |definition|
70
+ definition[:options][:to]
71
+ end.each do |definition|
72
+ as = definition[:options][:as]
75
73
 
76
- if [:embedded_in, :embeds_one, :referenced_in, :references_one, :has_one, :belongs_to].include? relation
77
- c = self.send(association)
78
-
79
- unless c.blank?
80
- assigns.each { |assign| c.send("#{assign[0]}=", assign[1]) }
81
-
82
- c.save
83
- end
84
- else
85
- c = self.send(association)
86
-
87
- c.to_a.each do |a|
88
- assigns.each { |assign| a.send("#{assign[0]}=", assign[1]) }
89
-
90
- a.save
91
- end
74
+ assignments = definition[:fields].collect do |source_field|
75
+ {
76
+ :source_field => source_field.to_s,
77
+ :value => self.send(source_field)
78
+ }
79
+ end
80
+
81
+ Array(definition[:options][:to]).each do |association|
82
+ relation = []
83
+ reflect = self.class.reflect_on_association(association)
84
+ relation = reflect.relation.macro unless reflect.nil? || reflect.relation.nil?
85
+
86
+ reflect.klass.skip_callback(:save, :before, :denormalize_from) if reflect.klass.try(:is_denormalized?)
87
+
88
+ associated = self.send(association)
89
+ prefix = (as || reflect.inverse_of || reflect.inverse_class_name).to_s.underscore
90
+
91
+ if [:embedded_in, :embeds_one, :referenced_in, :references_one, :has_one, :belongs_to].include? relation
92
+ unless associated.blank?
93
+ assign_and_save(associated, assignments, prefix)
92
94
  end
93
-
94
- reflect.klass.set_callback(:save, :before, :denormalize_from) if reflect.klass.try(:is_denormalized?)
95
+ else
96
+ associated.to_a.each { |c| assign_and_save(c, assignments, prefix) }
95
97
  end
98
+
99
+ reflect.klass.set_callback(:save, :before, :denormalize_from) if reflect.klass.try(:is_denormalized?)
96
100
  end
97
101
  end
98
- end
102
+ end
103
+
104
+ def assign_and_save(obj, assignments, prefix)
105
+ attributes_hash = Hash[assignments.collect do |assignment|
106
+ if self.changed_attributes.has_key?(assignment[:source_field])
107
+ ["#{prefix}_#{assignment[:source_field]}", assignment[:value]]
108
+ end
109
+ end]
110
+
111
+ unless attributes_hash.empty?
112
+ # The more succinct update_attributes(changes, :without_protection => true) requires Mongoid 3.0.0,
113
+ # but we only require 2.1.9
114
+ obj.assign_attributes(attributes_hash, :without_protection => true)
115
+ obj.save(:validate => false)
116
+ end
117
+ end
118
+ end
metadata CHANGED
@@ -1,80 +1,150 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: mongoid_denormalize
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 3
8
- - 0
9
- version: 0.3.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Logan Raarup
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2012-02-05 00:00:00 +01:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
21
- name: mongoid
12
+ date: 2013-06-19 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: mongoid_denormalize
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: bson_ext
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
22
55
  prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- segments:
28
- - 2
29
- - 1
30
- - 9
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: jeweler
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: guard-rspec
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: mongoid
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
31
101
  version: 2.1.9
32
102
  type: :runtime
33
- version_requirements: *id001
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: 2.1.9
34
110
  description: Helper module for denormalizing association attributes in Mongoid models.
35
111
  email: logan@logan.dk
36
112
  executables: []
37
-
38
113
  extensions: []
39
-
40
- extra_rdoc_files:
114
+ extra_rdoc_files:
41
115
  - LICENSE
42
116
  - README.md
43
- files:
117
+ files:
44
118
  - lib/mongoid_denormalize.rb
45
119
  - lib/railties/denormalize.rake
46
120
  - lib/railties/railtie.rb
47
121
  - LICENSE
48
122
  - README.md
49
- has_rdoc: true
50
123
  homepage: http://github.com/logandk/mongoid_denormalize
51
124
  licenses: []
52
-
53
125
  post_install_message:
54
126
  rdoc_options: []
55
-
56
- require_paths:
127
+ require_paths:
57
128
  - lib
58
- required_ruby_version: !ruby/object:Gem::Requirement
59
- requirements:
60
- - - ">="
61
- - !ruby/object:Gem::Version
62
- segments:
63
- - 0
64
- version: "0"
65
- required_rubygems_version: !ruby/object:Gem::Requirement
66
- requirements:
67
- - - ">="
68
- - !ruby/object:Gem::Version
69
- segments:
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - ! '>='
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ segments:
70
136
  - 0
71
- version: "0"
137
+ hash: 4386387219584124888
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ! '>='
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
72
144
  requirements: []
73
-
74
145
  rubyforge_project:
75
- rubygems_version: 1.3.6
146
+ rubygems_version: 1.8.24
76
147
  signing_key:
77
148
  specification_version: 3
78
149
  summary: Mongoid denormalization helper.
79
150
  test_files: []
80
-