mongoid_denormalize 0.1.0 → 0.2.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.
data/README.md CHANGED
@@ -3,6 +3,8 @@ Mongoid::Denormalize
3
3
 
4
4
  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
5
 
6
+ Extracted from [coookin'](http://coookin.com), where it is used in production.
7
+
6
8
 
7
9
  Installation
8
10
  ------------
@@ -86,6 +88,27 @@ the parent. When using the `:to` option, the parent will push the values to its
86
88
  denormalize :name, :to => [:posts, :comments]
87
89
 
88
90
 
91
+ Rake tasks
92
+ ----------
93
+
94
+ A rake task is included for verifying and repairing inconsistent denormalizations. This might be useful your records may be modified
95
+ without Mongoid, or if you are using relational associations in combination with embedded records (see *Known issues*).
96
+
97
+ rake db:denormalize
98
+
99
+ This task will only update records that have outdated denormalized fields.
100
+
101
+
102
+ Known issues
103
+ ------------
104
+
105
+ **Relational associations in combination with embedded records**
106
+
107
+ If you are using denormalize with the `:to` option, to denormalize values on a relational association that is embedded in another collection,
108
+ the denormalized fields will not be updated when the parent record is changed. This is due to a limitation in Mongoid that prevents querying
109
+ embedded records through relational associations. One way to overcome this issue is to run `rake db:denormalize` in a cron job.
110
+
111
+
89
112
  Credits
90
113
  -------
91
114
 
@@ -1,9 +1,11 @@
1
+ require File.dirname(__FILE__) + '/railties/railtie' if defined?(Rails::Railtie)
2
+
1
3
  # = Mongoid::Denormalize
2
4
  #
3
5
  # Helper module for denormalizing association attributes in Mongoid models.
4
6
  module Mongoid::Denormalize
5
7
  extend ActiveSupport::Concern
6
-
8
+
7
9
  included do
8
10
  cattr_accessor :denormalize_definitions
9
11
 
@@ -36,6 +38,15 @@ module Mongoid::Denormalize
36
38
  end
37
39
  end
38
40
 
41
+ def denormalized_valid?
42
+ denormalize_from
43
+ !self.changed?
44
+ end
45
+
46
+ def repair_denormalized!
47
+ self.save! unless denormalized_valid?
48
+ end
49
+
39
50
  private
40
51
  def denormalize_from
41
52
  self.denormalize_definitions.each do |definition|
@@ -0,0 +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.options[:name].to_s.classify.constantize
8
+
9
+ unless parent.embedded?
10
+ parent.all.each do |parent_instance|
11
+ parent_instance.send(reflection.options[:inverse_of]).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
+ end
@@ -0,0 +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
9
+ end
File without changes
File without changes
File without changes
@@ -2,9 +2,7 @@ require "spec_helper"
2
2
 
3
3
  describe Mongoid::Denormalize do
4
4
  before(:all) do
5
- Mongoid.master.collections.each do |c|
6
- c.drop rescue nil
7
- end
5
+ Mongoid.master.collections.select {|c| c.name !~ /system/ }.each(&:drop)
8
6
 
9
7
  @post = Post.create!(:title => "Blog post", :body => "Lorem ipsum...", :created_at => Time.parse("Jan 1 2010 12:00"))
10
8
  @user = User.create!(:name => "John Doe", :email => "john@doe.com", :post => @post)
@@ -77,4 +75,29 @@ describe Mongoid::Denormalize do
77
75
  @comment.post_created_at.should eql Time.parse("Jan 1 2011 12:00")
78
76
  end
79
77
  end
78
+
79
+ context "rake task" do
80
+ it "should correct inconsistent denormalizations on regular documents" do
81
+ Post.collection.update({ '_id' => @post.id }, { '$set' => { 'user_name' => 'Clint Eastwood' } })
82
+
83
+ Rake::Task["db:denormalize"].invoke
84
+ Rake::Task["db:denormalize"].reenable
85
+
86
+ @post.reload
87
+ @post.user_name.should eql @user.name
88
+ end
89
+
90
+ it "should correct inconsistent denormalizations on referenced embedded documents" do
91
+ @rake_user = User.create!(:name => "Johnny Depp", :email => "johnny@depp.com")
92
+ @rake_comment = @post.comments.create!(:body => "Depp's comment", :user => @rake_user)
93
+
94
+ @rake_user.update_attributes!(:name => "J. Depp")
95
+
96
+ Rake::Task["db:denormalize"].invoke
97
+ Rake::Task["db:denormalize"].reenable
98
+
99
+ @post.reload
100
+ @post.comments.last.user_name.should eql @rake_user.name
101
+ end
102
+ end
80
103
  end
data/spec/spec_helper.rb CHANGED
@@ -2,15 +2,17 @@ require 'rubygems'
2
2
  require 'spec'
3
3
  require 'mongoid'
4
4
  require 'yaml'
5
+ require 'rake'
6
+
7
+ # Load rake tasks
8
+ load File.expand_path("../../lib/railties/denormalize.rake", __FILE__)
9
+ task :environment do
10
+ Dir.chdir(File.dirname(__FILE__))
11
+ end
5
12
 
6
13
  Mongoid.configure do |config|
7
- settings = YAML.load(File.read(File.join(File.dirname(__FILE__), "database.yml")))
8
-
9
- db = Mongo::Connection.new(settings['host'], settings['port']).db(settings['database'])
10
- db.authenticate(settings['username'], settings['password'])
11
-
12
- config.master = db
14
+ config.master = Mongo::Connection.new.db("mongoid_denormalize_development")
13
15
  end
14
16
 
15
17
  require File.expand_path("../../lib/mongoid_denormalize", __FILE__)
16
- Dir["#{File.dirname(__FILE__)}/models/*.rb"].each { |f| require f }
18
+ Dir["#{File.dirname(__FILE__)}/app/models/*.rb"].each { |f| require f }
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid_denormalize
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
5
4
  prerelease: false
6
5
  segments:
7
6
  - 0
8
- - 1
7
+ - 2
9
8
  - 0
10
- version: 0.1.0
9
+ version: 0.2.0
11
10
  platform: ruby
12
11
  authors:
13
12
  - Logan Raarup
@@ -15,18 +14,16 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2010-07-09 00:00:00 +02:00
17
+ date: 2010-09-07 00:00:00 +02:00
19
18
  default_executable:
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
22
21
  name: mongoid
23
22
  prerelease: false
24
23
  requirement: &id001 !ruby/object:Gem::Requirement
25
- none: false
26
24
  requirements:
27
25
  - - ~>
28
26
  - !ruby/object:Gem::Version
29
- hash: -1848230043
30
27
  segments:
31
28
  - 2
32
29
  - 0
@@ -48,11 +45,8 @@ files:
48
45
  - LICENSE
49
46
  - README.md
50
47
  - lib/mongoid_denormalize.rb
51
- - spec/models/comment.rb
52
- - spec/models/post.rb
53
- - spec/models/user.rb
54
- - spec/mongoid_denormalize_spec.rb
55
- - spec/spec_helper.rb
48
+ - lib/railties/denormalize.rake
49
+ - lib/railties/railtie.rb
56
50
  has_rdoc: true
57
51
  homepage: http://github.com/logandk/mongoid_denormalize
58
52
  licenses: []
@@ -63,33 +57,29 @@ rdoc_options:
63
57
  require_paths:
64
58
  - lib
65
59
  required_ruby_version: !ruby/object:Gem::Requirement
66
- none: false
67
60
  requirements:
68
61
  - - ">="
69
62
  - !ruby/object:Gem::Version
70
- hash: 3
71
63
  segments:
72
64
  - 0
73
65
  version: "0"
74
66
  required_rubygems_version: !ruby/object:Gem::Requirement
75
- none: false
76
67
  requirements:
77
68
  - - ">="
78
69
  - !ruby/object:Gem::Version
79
- hash: 3
80
70
  segments:
81
71
  - 0
82
72
  version: "0"
83
73
  requirements: []
84
74
 
85
75
  rubyforge_project:
86
- rubygems_version: 1.3.7
76
+ rubygems_version: 1.3.6
87
77
  signing_key:
88
78
  specification_version: 3
89
79
  summary: Mongoid denormalization helper.
90
80
  test_files:
91
- - spec/models/comment.rb
92
- - spec/models/post.rb
93
- - spec/models/user.rb
81
+ - spec/app/models/comment.rb
82
+ - spec/app/models/post.rb
83
+ - spec/app/models/user.rb
94
84
  - spec/mongoid_denormalize_spec.rb
95
85
  - spec/spec_helper.rb