mongoid_denormalize 0.3.0 → 0.4.0

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