mongoid-eager-loading 0.2.0 → 0.3.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 (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