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.
- data/README.md +40 -10
- data/lib/mongoid_denormalize.rb +62 -42
- 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
|
-
|
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
|
data/lib/mongoid_denormalize.rb
CHANGED
@@ -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(*
|
30
|
-
options =
|
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
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
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
|
-
|
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
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
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
|
-
|
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
|
-
|
5
|
-
|
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
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
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
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
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
|
-
|
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.
|
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
|
-
|