mongoid-eager-loading 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/Gemfile.lock +13 -12
  2. data/README.md +12 -10
  3. data/benchmark/benchmark.rb +11 -4
  4. data/lib/mongoid-eager-loading.rb +1 -6
  5. data/lib/mongoid-eager-loading/mongoid/criterion/eager_loading.rb +36 -36
  6. data/lib/mongoid-eager-loading/version.rb +1 -1
  7. data/mongoid-eager-loading.gemspec +4 -3
  8. data/spec/models/account.rb +11 -5
  9. data/spec/models/address.rb +8 -1
  10. data/spec/models/address_component.rb +5 -0
  11. data/spec/models/agent.rb +2 -3
  12. data/spec/models/animal.rb +8 -5
  13. data/spec/models/answer.rb +1 -1
  14. data/spec/models/bar.rb +5 -0
  15. data/spec/models/book.rb +5 -0
  16. data/spec/models/business.rb +7 -0
  17. data/spec/models/callbacks.rb +2 -2
  18. data/spec/models/category.rb +3 -3
  19. data/spec/models/country_code.rb +1 -1
  20. data/spec/models/description.rb +3 -0
  21. data/spec/models/drug.rb +5 -0
  22. data/spec/models/favorite.rb +1 -3
  23. data/spec/models/fruits.rb +11 -0
  24. data/spec/models/game.rb +2 -1
  25. data/spec/models/house.rb +4 -0
  26. data/spec/models/inheritance.rb +19 -4
  27. data/spec/models/location.rb +1 -1
  28. data/spec/models/membership.rb +4 -0
  29. data/spec/models/movie.rb +5 -0
  30. data/spec/models/name.rb +1 -1
  31. data/spec/models/page.rb +5 -0
  32. data/spec/models/page_question.rb +4 -0
  33. data/spec/models/paranoid_post.rb +1 -1
  34. data/spec/models/parents.rb +1 -1
  35. data/spec/models/patient.rb +2 -2
  36. data/spec/models/person.rb +27 -12
  37. data/spec/models/pet.rb +1 -1
  38. data/spec/models/pet_owner.rb +1 -1
  39. data/spec/models/phone.rb +1 -1
  40. data/spec/models/post.rb +6 -4
  41. data/spec/models/preference.rb +2 -1
  42. data/spec/models/question.rb +3 -3
  43. data/spec/models/quiz.rb +4 -0
  44. data/spec/models/rating.rb +6 -0
  45. data/spec/models/role.rb +5 -0
  46. data/spec/models/shelf.rb +5 -0
  47. data/spec/models/slave_address_numbers.rb +14 -0
  48. data/spec/models/survey.rb +1 -2
  49. data/spec/models/tracking_id_validation_history.rb +25 -0
  50. data/spec/models/translation.rb +1 -1
  51. data/spec/models/user.rb +3 -2
  52. data/spec/models/user_account.rb +3 -2
  53. data/spec/models/vet_visit.rb +1 -1
  54. data/spec/models/video.rb +1 -1
  55. data/spec/models/wiki_page.rb +6 -0
  56. data/spec/mongoid-eager-loading/mongoid/criterion/eager_loading_spec.rb +19 -0
  57. data/spec/spec_helper.rb +1 -1
  58. metadata +93 -59
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mongoid-eager-loading (0.2.0)
4
+ mongoid-eager-loading (0.3.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -11,18 +11,18 @@ GEM
11
11
  builder (~> 2.1.2)
12
12
  i18n (~> 0.4)
13
13
  activesupport (3.0.3)
14
- bson (1.1.1)
15
- bson_ext (1.1.1)
14
+ bson (1.2.0)
15
+ bson_ext (1.2.0)
16
16
  builder (2.1.2)
17
17
  diff-lcs (1.1.2)
18
- i18n (0.4.2)
18
+ i18n (0.5.0)
19
19
  mocha (0.9.9)
20
20
  rake
21
- mongo (1.1.1)
22
- bson (>= 1.1.1)
23
- mongoid (2.0.0.beta.20)
21
+ mongo (1.2.0)
22
+ bson (>= 1.2.0)
23
+ mongoid (2.0.0.rc.6)
24
24
  activemodel (~> 3.0)
25
- mongo (~> 1.1)
25
+ mongo (~> 1.2)
26
26
  tzinfo (~> 0.3.22)
27
27
  will_paginate (~> 3.0.pre)
28
28
  rake (0.8.7)
@@ -36,7 +36,7 @@ GEM
36
36
  rspec-mocks (2.0.1)
37
37
  rspec-core (~> 2.0.1)
38
38
  rspec-expectations (~> 2.0.1)
39
- tzinfo (0.3.23)
39
+ tzinfo (0.3.24)
40
40
  watchr (0.7)
41
41
  will_paginate (3.0.pre2)
42
42
 
@@ -44,11 +44,12 @@ PLATFORMS
44
44
  ruby
45
45
 
46
46
  DEPENDENCIES
47
- bson_ext (~> 1.1.1)
47
+ bson (= 1.2.0)
48
+ bson_ext (= 1.2.0)
48
49
  bundler (>= 1.0.0)
49
50
  mocha
50
- mongo (~> 1.1.1)
51
- mongoid (= 2.0.0.beta.20)
51
+ mongo (= 1.2.0)
52
+ mongoid (= 2.0.0.rc.6)
52
53
  mongoid-eager-loading!
53
54
  rspec (~> 2.0.0)
54
55
  watchr
data/README.md CHANGED
@@ -5,7 +5,7 @@ mongoid-eager-loading adds the eager loading feature for mongoid.
5
5
 
6
6
  Originally it is my [pull request][0] for mongoid, but it is not accepted yet, so I created this gem to get the eager loading benefits easily for my projects.
7
7
 
8
- I only test it in mongoid-2.0.0.beta.19, maybe you can try it on other mongoid version, and let me know if it works fine.
8
+ I only test it in mongoid 2.0.0.beta.19 and 2.0.0.beta.20, maybe you can try it on other mongoid version, and let me know if it works fine.
9
9
 
10
10
  Usage
11
11
  -----
@@ -18,7 +18,7 @@ suppose you have a mongoid model Post
18
18
 
19
19
  class Post
20
20
  include Mongoid::Document
21
-
21
+
22
22
  referenced_in :user
23
23
  references_many :comments
24
24
  end
@@ -27,9 +27,9 @@ then you can use the eager loading like
27
27
 
28
28
  Post.includes(:user)
29
29
  Post.includes(:user, :comments)
30
-
30
+
31
31
  eager loading can be only used on referenced_in, references_one and references_many associations.
32
-
32
+
33
33
  Benchmark
34
34
  ---------
35
35
 
@@ -37,12 +37,14 @@ I also run a [benchmark][1] on my local computer, the result is as follows
37
37
 
38
38
  Starting benchmark...
39
39
  user system total real
40
- Finding 10 posts with person, without eager loading 0.010000 0.000000 0.010000 ( 0.006538)
41
- Finding 10 posts with person, with eager loading 0.000000 0.000000 0.000000 ( 0.005235)
42
- Finding 50 posts with person, without eager loading 0.020000 0.000000 0.020000 ( 0.027912)
43
- Finding 50 posts with person, with eager loading 0.020000 0.000000 0.020000 ( 0.020103)
44
- Finding 100 posts with person, without eager loading 0.040000 0.000000 0.040000 ( 0.055197)
45
- Finding 100 posts with person, with eager loading 0.030000 0.010000 0.040000 ( 0.040644)
40
+ Finding 10 posts with person, without eager loading 0.000000 0.000000 0.000000 ( 0.005373)
41
+ Finding 10 posts with person, with eager loading 0.010000 0.000000 0.010000 ( 0.002984)
42
+ Finding 50 posts with person, without eager loading 0.010000 0.000000 0.010000 ( 0.022207)
43
+ Finding 50 posts with person, with eager loading 0.010000 0.000000 0.010000 ( 0.006831)
44
+ Finding 100 posts with person, without eager loading 0.040000 0.000000 0.040000 ( 0.050991)
45
+ Finding 100 posts with person, with eager loading 0.010000 0.000000 0.010000 ( 0.012867)
46
+ Finding 1000 posts with person, without eager loading 0.390000 0.050000 0.440000 ( 0.477983)
47
+ Finding 1000 posts with person, with eager loading 0.120000 0.010000 0.130000 ( 0.128879)
46
48
 
47
49
  Author
48
50
  ------
@@ -5,7 +5,8 @@ require "mongoid"
5
5
  require "mongoid-eager-loading"
6
6
 
7
7
  Mongoid.configure do |config|
8
- config.master = Mongo::Connection.new.db("mongoid_perf_test", :logger => Logger.new($stdout, :info))
8
+ #config.master = Mongo::Connection.new('localhost', 27018, :logger => Logger.new($stdout)).db("mongoid_perf_test")
9
+ config.master = Mongo::Connection.new.db("mongoid_perf_test")
9
10
  end
10
11
 
11
12
  Mongoid.master.collection("people").drop
@@ -36,22 +37,28 @@ Benchmark.bm(60) do |bm|
36
37
  bm.report("Finding 10 posts with person, without eager loading") do
37
38
  Post.limit(10).each { |p| p.person.name }
38
39
  end
39
-
40
40
  bm.report("Finding 10 posts with person, with eager loading") do
41
41
  Post.limit(10).includes(:person).each { |p| p.person.name }
42
42
  end
43
+
43
44
  bm.report("Finding 50 posts with person, without eager loading") do
44
45
  Post.limit(50).each { |p| p.person.name }
45
46
  end
46
-
47
47
  bm.report("Finding 50 posts with person, with eager loading") do
48
48
  Post.limit(50).includes(:person).each { |p| p.person.name }
49
49
  end
50
+
50
51
  bm.report("Finding 100 posts with person, without eager loading") do
51
52
  Post.limit(100).each { |p| p.person.name }
52
53
  end
53
-
54
54
  bm.report("Finding 100 posts with person, with eager loading") do
55
55
  Post.limit(100).includes(:person).each { |p| p.person.name }
56
56
  end
57
+
58
+ bm.report("Finding 1000 posts with person, without eager loading") do
59
+ Post.limit(1000).each { |p| p.person.name }
60
+ end
61
+ bm.report("Finding 1000 posts with person, with eager loading") do
62
+ Post.limit(1000).includes(:person).each { |p| p.person.name }
63
+ end
57
64
  end
@@ -1,8 +1,3 @@
1
1
  require 'mongoid-eager-loading/mongoid/criterion/eager_loading'
2
2
  require 'mongoid-eager-loading/mongoid/criteria'
3
- require 'mongoid-eager-loading/mongoid/finders'
4
-
5
- module Mongoid
6
- module EagerLoading
7
- end
8
- end
3
+ require 'mongoid-eager-loading/mongoid/finders'
@@ -35,75 +35,75 @@ module Mongoid
35
35
  end
36
36
 
37
37
  def setup_associations(documents, reflection)
38
- if reflection.association == Mongoid::Associations::ReferencesOne
38
+ case reflection.macro
39
+ when :references_one
39
40
  setup_associations_with_ids(documents, reflection, true)
40
- elsif reflection.association == Mongoid::Associations::ReferencesMany
41
+ when :references_many
41
42
  setup_associations_with_ids(documents, reflection, false)
42
- elsif reflection.association == Mongoid::Associations::ReferencesManyAsArray
43
+ when :references_and_referenced_in_many
43
44
  setup_associations_with_foreign_keys(documents, reflection, false)
44
- elsif reflection.association == Mongoid::Associations::ReferencedIn
45
+ when :referenced_in
45
46
  setup_associations_with_foreign_keys(documents, reflection, true)
46
47
  end
47
48
  end
48
49
 
49
50
  def setup_associations_with_ids(documents, reflection, one=true)
50
- ids = []
51
- documents.each do |document|
52
- add_id_document(document.id, document)
53
- ids << document.id if document.id
54
- end
51
+ ids = association_ids(documents, reflection)
55
52
 
56
- association_class = reflection.name.singularize.camelize.constantize
57
53
  ignore_includes
58
- eager_associations = association_class.where(reflection.foreign_key.to_sym.in => ids.uniq).to_a
54
+ eager_associations = reflection.klass.where(reflection.foreign_key.to_sym.in => ids.uniq).to_a
59
55
  eager_associations.each do |eager_association|
60
56
  add_id_association(eager_association.send(reflection.foreign_key), eager_association)
61
57
  end
62
58
 
63
- id_documents_map.each do |id, documents|
64
- documents.each do |document|
65
- document.instance_variable_set("@#{reflection.name}", one ? id_associations_map[id].first : id_associations_map[id])
66
- end
67
- end
59
+ assign_associations(documents, reflection)
68
60
  end
69
61
 
70
62
  def setup_associations_with_foreign_keys(documents, reflection, one)
71
- ids = []
72
- foreign_key_name = reflection.foreign_key
73
- documents.each do |document|
74
- foreign_key_value = document.send(foreign_key_name)
75
- if one
76
- add_id_document(foreign_key_value, document)
77
- ids << foreign_key_value if foreign_key_value
78
- elsif foreign_key_value
79
- foreign_key_value.each do |fkv|
80
- add_id_document(fkv, document)
81
- ids << fkv if fkv
82
- end
83
- end
84
- end
63
+ ids = association_ids(documents, reflection)
85
64
 
86
- association_class = reflection.name.singularize.camelize.constantize
87
65
  ignore_includes
88
- eager_associations = association_class.find(ids.uniq).to_a
66
+ eager_associations = reflection.klass.find(ids.uniq).to_a
89
67
  eager_associations.each do |eager_association|
90
68
  add_id_association(eager_association.id, eager_association)
91
69
  end
92
70
 
71
+ assign_associations(documents, reflection)
72
+ end
73
+
74
+ def association_ids(documents, reflection)
75
+ ids = []
76
+ key_name = reflection.key
77
+ documents.each do |document|
78
+ key_value = document.send(key_name)
79
+ to_array(key_value).each do |v|
80
+ add_id_document(v, document)
81
+ ids << v
82
+ end
83
+ end
84
+ ids
85
+ end
86
+
87
+ def assign_associations(documents, reflection)
93
88
  id_documents_map.each do |id, documents|
94
89
  documents.each do |document|
95
- foreign_key_value = document.send(foreign_key_name)
90
+ key_value = document.send(reflection.key)
96
91
  associations = \
97
- if one
98
- id_associations_map[foreign_key_value].first
92
+ if key_value.is_a?(Array)
93
+ key_value.collect { |v| id_associations_map[v] }
99
94
  else
100
- foreign_key_value.collect { |fkv| id_associations_map[fkv] }.flatten.uniq
95
+ id_associations_map[key_value] ? id_associations_map[key_value].first : nil
101
96
  end
102
97
  document.instance_variable_set("@#{reflection.name}", associations)
103
98
  end
104
99
  end
105
100
  end
106
101
 
102
+ def to_array(value)
103
+ array = value.is_a?(Array) ? value : [value]
104
+ array.compact
105
+ end
106
+
107
107
  def id_documents_map
108
108
  @id_documents_map ||= {}
109
109
  end
@@ -1,5 +1,5 @@
1
1
  module Mongoid
2
2
  module EagerLoading
3
- VERSION = "0.2.0"
3
+ VERSION = "0.3.0"
4
4
  end
5
5
  end
@@ -15,12 +15,13 @@ Gem::Specification.new do |s|
15
15
  s.rubyforge_project = "mongoid-eager-loading"
16
16
 
17
17
  s.add_development_dependency "bundler", ">= 1.0.0"
18
- s.add_development_dependency "mongoid", "2.0.0.beta.20"
18
+ s.add_development_dependency "mongo", "1.2.0"
19
+ s.add_development_dependency "bson", "1.2.0"
20
+ s.add_development_dependency "bson_ext", "1.2.0"
21
+ s.add_development_dependency "mongoid", "2.0.0.rc.6"
19
22
  s.add_development_dependency "rspec", "~> 2.0.0"
20
23
  s.add_development_dependency "mocha"
21
24
  s.add_development_dependency "watchr"
22
- s.add_development_dependency "bson_ext", "~> 1.1.1"
23
- s.add_development_dependency "mongo", "~> 1.1.1"
24
25
 
25
26
  s.files = `git ls-files`.split("\n")
26
27
  s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
@@ -1,10 +1,16 @@
1
1
  class Account
2
2
  include Mongoid::Document
3
+ field :number, :type => String
4
+ field :balance, :type => String
5
+ field :nickname, :type => String
6
+ field :name, :type => String
7
+
8
+ embeds_many :memberships
3
9
  referenced_in :creator, :class_name => "User", :foreign_key => :creator_id
4
10
  referenced_in :person
5
- field :number
6
- field :balance
7
- field :nickname
8
-
9
- attr_accessible :nickname
11
+
12
+ attr_accessible :nickname, :name
13
+
14
+ validates_presence_of :name
15
+ validates_length_of :name, :maximum => 10, :on => :create
10
16
  end
@@ -15,7 +15,7 @@ class Address
15
15
  key :street
16
16
  embeds_many :locations
17
17
 
18
- embedded_in :addressable, :inverse_of => :addresses do
18
+ embedded_in :addressable, :polymorphic => true do
19
19
  def extension
20
20
  "Testing"
21
21
  end
@@ -24,6 +24,8 @@ class Address
24
24
  end
25
25
  end
26
26
 
27
+ referenced_in :account
28
+
27
29
  named_scope :rodeo, where(:street => "Rodeo Dr") do
28
30
  def mansion?
29
31
  all? { |address| address.street == "Rodeo Dr" }
@@ -31,11 +33,16 @@ class Address
31
33
  end
32
34
 
33
35
  validates_presence_of :street, :on => :update
36
+ validates_format_of :street, :with => /\D/, :allow_nil => true
34
37
 
35
38
  def set_parent=(set = false)
36
39
  self.parent_title = addressable.title if set
37
40
  end
38
41
 
42
+ def <=>(other)
43
+ street <=> other.street
44
+ end
45
+
39
46
  class << self
40
47
  def california
41
48
  where(:state => "CA")
@@ -0,0 +1,5 @@
1
+ class AddressComponent
2
+ include Mongoid::Document
3
+ field :street, :type => String
4
+ embedded_in :person
5
+ end
@@ -2,7 +2,6 @@ class Agent
2
2
  include Mongoid::Document
3
3
  field :title
4
4
  field :number
5
- embeds_many :names
6
- references_many :posts, :foreign_key => :poster_id
7
- accepts_nested_attributes_for :posts, :allow_destroy => true
5
+ embeds_many :names, :as => :namable
6
+ referenced_in :game
8
7
  end
@@ -1,15 +1,18 @@
1
1
  class Animal
2
2
  include Mongoid::Document
3
3
  field :name
4
- field :tags, :type => Array
4
+ field :tags, :type => Array
5
5
  key :name
6
- embedded_in :person, :inverse_of => :pet
7
-
6
+
7
+ embedded_in :person
8
+
9
+ accepts_nested_attributes_for :person
10
+
8
11
  def tag_list
9
12
  tags.join(", ")
10
13
  end
11
-
14
+
12
15
  def tag_list=(_tag_list)
13
16
  self.tags = _tag_list.split(",").map(&:strip)
14
- end
17
+ end
15
18
  end
@@ -1,4 +1,4 @@
1
1
  class Answer
2
2
  include Mongoid::Document
3
- embedded_in :question, :inverse_of => :answers
3
+ embedded_in :question
4
4
  end
@@ -0,0 +1,5 @@
1
+ class Bar
2
+ include Mongoid::Document
3
+ field :name, :type => String
4
+ references_one :rating, :as => :ratable
5
+ end
@@ -0,0 +1,5 @@
1
+ class Book
2
+ include Mongoid::Document
3
+ field :title, :type => String
4
+ references_one :rating, :as => :ratable, :dependent => :nullify
5
+ end
@@ -0,0 +1,7 @@
1
+ class Business
2
+ include Mongoid::Document
3
+
4
+ set_database :secondary
5
+
6
+ field :name
7
+ end
@@ -20,13 +20,13 @@ end
20
20
  class Song
21
21
  include Mongoid::Document
22
22
  field :title
23
- embedded_in :artist, :inverse_of => :songs
23
+ embedded_in :artist
24
24
  end
25
25
 
26
26
  class Label
27
27
  include Mongoid::Document
28
28
  field :name
29
- embedded_in :artist, :inverse_of => :labels
29
+ embedded_in :artist
30
30
  before_validation :cleanup
31
31
 
32
32
  private
@@ -5,9 +5,9 @@ end
5
5
 
6
6
  class Category
7
7
  include Mongoid::Document
8
- embedded_in :root_category, :inverse_of => :categories
9
- embedded_in :category, :inverse_of => :categories
8
+ embedded_in :root_category
9
+ embedded_in :category
10
10
  embeds_many :categories
11
11
 
12
12
  field :name
13
- end
13
+ end