mongoid-eager-loading 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.rvmrc.example +2 -0
- data/.watchr +24 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +54 -0
- data/LICENSE +20 -0
- data/README.md +35 -0
- data/Rakefile +45 -0
- data/lib/mongoid-eager-loading.rb +8 -0
- data/lib/mongoid-eager-loading/mongoid/criteria.rb +18 -0
- data/lib/mongoid-eager-loading/mongoid/criterion/eager_loading.rb +116 -0
- data/lib/mongoid-eager-loading/mongoid/finders.rb +5 -0
- data/lib/mongoid-eager-loading/version.rb +5 -0
- data/mongoid-eager-loading.gemspec +28 -0
- data/spec/config/mongoid.yml +21 -0
- data/spec/models/account.rb +10 -0
- data/spec/models/address.rb +52 -0
- data/spec/models/agent.rb +8 -0
- data/spec/models/animal.rb +15 -0
- data/spec/models/answer.rb +4 -0
- data/spec/models/callbacks.rb +47 -0
- data/spec/models/category.rb +13 -0
- data/spec/models/comment.rb +10 -0
- data/spec/models/country_code.rb +6 -0
- data/spec/models/description.rb +8 -0
- data/spec/models/employer.rb +5 -0
- data/spec/models/favorite.rb +8 -0
- data/spec/models/game.rb +14 -0
- data/spec/models/inheritance.rb +72 -0
- data/spec/models/location.rb +5 -0
- data/spec/models/login.rb +6 -0
- data/spec/models/mixed_drink.rb +4 -0
- data/spec/models/name.rb +13 -0
- data/spec/models/namespacing.rb +11 -0
- data/spec/models/paranoid_post.rb +18 -0
- data/spec/models/parents.rb +32 -0
- data/spec/models/patient.rb +15 -0
- data/spec/models/person.rb +113 -0
- data/spec/models/pet.rb +7 -0
- data/spec/models/pet_owner.rb +6 -0
- data/spec/models/phone.rb +7 -0
- data/spec/models/post.rb +25 -0
- data/spec/models/preference.rb +7 -0
- data/spec/models/question.rb +8 -0
- data/spec/models/survey.rb +6 -0
- data/spec/models/translation.rb +5 -0
- data/spec/models/user.rb +8 -0
- data/spec/models/user_account.rb +9 -0
- data/spec/models/vet_visit.rb +5 -0
- data/spec/models/video.rb +5 -0
- data/spec/mongoid-eager-loading/mongoid/criteria_spec.rb +26 -0
- data/spec/mongoid-eager-loading/mongoid/criterion/eager_loading_spec.rb +103 -0
- data/spec/spec_helper.rb +29 -0
- metadata +213 -0
data/.gitignore
ADDED
data/.rvmrc.example
ADDED
data/.watchr
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# vim:set filetype=ruby:
|
2
|
+
def run(cmd)
|
3
|
+
puts cmd
|
4
|
+
system cmd
|
5
|
+
end
|
6
|
+
|
7
|
+
def spec(file)
|
8
|
+
if File.exists?(file)
|
9
|
+
run("rspec #{file}")
|
10
|
+
else
|
11
|
+
puts("Spec: #{file} does not exist.")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
watch("spec/.*/*_spec\.rb") do |match|
|
16
|
+
puts(match[0])
|
17
|
+
spec(match[0])
|
18
|
+
end
|
19
|
+
|
20
|
+
watch("lib/(.*/.*)\.rb") do |match|
|
21
|
+
puts(match[1])
|
22
|
+
spec("spec/#{match[1]}_spec.rb")
|
23
|
+
end
|
24
|
+
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
mongoid-eager-loading (0.1.0)
|
5
|
+
mongoid (~> 2.0.0.beta.18)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: http://rubygems.org/
|
9
|
+
specs:
|
10
|
+
activemodel (3.0.1)
|
11
|
+
activesupport (= 3.0.1)
|
12
|
+
builder (~> 2.1.2)
|
13
|
+
i18n (~> 0.4.1)
|
14
|
+
activesupport (3.0.1)
|
15
|
+
bson (1.1.1)
|
16
|
+
bson_ext (1.1.1)
|
17
|
+
builder (2.1.2)
|
18
|
+
diff-lcs (1.1.2)
|
19
|
+
i18n (0.4.1)
|
20
|
+
mocha (0.9.9)
|
21
|
+
rake
|
22
|
+
mongo (1.0.9)
|
23
|
+
bson (>= 1.0.5)
|
24
|
+
mongoid (2.0.0.beta.19)
|
25
|
+
activemodel (~> 3.0)
|
26
|
+
mongo (= 1.0.9)
|
27
|
+
tzinfo (~> 0.3.22)
|
28
|
+
will_paginate (~> 3.0.pre)
|
29
|
+
rake (0.8.7)
|
30
|
+
rspec (2.0.1)
|
31
|
+
rspec-core (~> 2.0.1)
|
32
|
+
rspec-expectations (~> 2.0.1)
|
33
|
+
rspec-mocks (~> 2.0.1)
|
34
|
+
rspec-core (2.0.1)
|
35
|
+
rspec-expectations (2.0.1)
|
36
|
+
diff-lcs (>= 1.1.2)
|
37
|
+
rspec-mocks (2.0.1)
|
38
|
+
rspec-core (~> 2.0.1)
|
39
|
+
rspec-expectations (~> 2.0.1)
|
40
|
+
tzinfo (0.3.23)
|
41
|
+
watchr (0.7)
|
42
|
+
will_paginate (3.0.pre2)
|
43
|
+
|
44
|
+
PLATFORMS
|
45
|
+
ruby
|
46
|
+
|
47
|
+
DEPENDENCIES
|
48
|
+
bson_ext
|
49
|
+
bundler (>= 1.0.0)
|
50
|
+
mocha
|
51
|
+
mongoid (~> 2.0.0.beta.18)
|
52
|
+
mongoid-eager-loading!
|
53
|
+
rspec (~> 2.0.0)
|
54
|
+
watchr
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Richard Huang (flyerhzm@gmail.com)
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
mongoid-eager-loading
|
2
|
+
=====================
|
3
|
+
|
4
|
+
mongoid-eager-loading adds the eager loading feature for mongoid.
|
5
|
+
|
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
|
+
|
8
|
+
Usage
|
9
|
+
-----
|
10
|
+
|
11
|
+
define it in your Gemfile
|
12
|
+
|
13
|
+
gem "mongoid-eager-loading"
|
14
|
+
|
15
|
+
include the module after Mongoid::Document
|
16
|
+
|
17
|
+
class User
|
18
|
+
include Mongoid::Document
|
19
|
+
include Mongoid::EagerLoading
|
20
|
+
end
|
21
|
+
|
22
|
+
then you can use the eager loading like
|
23
|
+
|
24
|
+
Post.includes(:user)
|
25
|
+
Post.includes(:user, :comment)
|
26
|
+
|
27
|
+
Author
|
28
|
+
------
|
29
|
+
Richard Huang :: flyerhzm@gmail.com :: @flyerhzm
|
30
|
+
|
31
|
+
Copyright
|
32
|
+
---------
|
33
|
+
Copyright (c) 2010 Richard Huang. See LICENSE for details.
|
34
|
+
|
35
|
+
[0]: https://github.com/mongoid/mongoid/pull/391
|
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler.setup
|
3
|
+
|
4
|
+
require "rake"
|
5
|
+
require "rake/rdoctask"
|
6
|
+
require "rspec"
|
7
|
+
require "rspec/core/rake_task"
|
8
|
+
|
9
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
10
|
+
|
11
|
+
task :build do
|
12
|
+
system "gem build mongoid-eager-loading.gemspec"
|
13
|
+
end
|
14
|
+
|
15
|
+
task :install => :build do
|
16
|
+
system "sudo gem install mongoid-eager-loading-#{Mongoid::EagerLoading::VERSION}.gem"
|
17
|
+
end
|
18
|
+
|
19
|
+
task :release => :build do
|
20
|
+
puts "Tagging #{Mongoid::EagerLoading::VERSION}..."
|
21
|
+
system "git tag -a #{Mongoid::EagerLoading::VERSION} -m 'Tagging #{Mongoid::EagerLoading::VERSION}'"
|
22
|
+
puts "Pushing to Github..."
|
23
|
+
system "git push --tags"
|
24
|
+
puts "Pushing to rubygems.org..."
|
25
|
+
system "gem push mongoid-eager-loading-#{Mongoid::EagerLoading::VERSION}.gem"
|
26
|
+
end
|
27
|
+
|
28
|
+
Rspec::Core::RakeTask.new(:spec) do |spec|
|
29
|
+
spec.pattern = "spec/**/*_spec.rb"
|
30
|
+
end
|
31
|
+
|
32
|
+
Rspec::Core::RakeTask.new('spec:progress') do |spec|
|
33
|
+
spec.rspec_opts = %w(--format progress)
|
34
|
+
spec.pattern = "spec/**/*_spec.rb"
|
35
|
+
end
|
36
|
+
|
37
|
+
Rake::RDocTask.new do |rdoc|
|
38
|
+
rdoc.rdoc_dir = "rdoc"
|
39
|
+
rdoc.title = "mongoid-eager-loading #{Mongoid::EagerLoading::VERSION}"
|
40
|
+
rdoc.rdoc_files.include("README*")
|
41
|
+
rdoc.rdoc_files.include("lib/**/*.rb")
|
42
|
+
end
|
43
|
+
|
44
|
+
task :default => :spec
|
45
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Mongoid::Criteria.class_eval do
|
2
|
+
include Mongoid::Criterion::EagerLoading
|
3
|
+
|
4
|
+
alias_method :origin_each, :each
|
5
|
+
|
6
|
+
def each(&block)
|
7
|
+
if @eager_loadings
|
8
|
+
# if eager loadings are used, preload the associations.
|
9
|
+
docs = []
|
10
|
+
context.iterate { |doc| docs << doc }
|
11
|
+
preload(docs)
|
12
|
+
docs.each(&block)
|
13
|
+
self
|
14
|
+
else
|
15
|
+
origin_each(&block)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Criterion
|
3
|
+
module EagerLoading
|
4
|
+
# EagerLoading criterion are used when eager loading the associations.
|
5
|
+
#
|
6
|
+
# Example:
|
7
|
+
#
|
8
|
+
# <tt>criteria.includes(:user)</tt>
|
9
|
+
#
|
10
|
+
# <tt>criteria.includes(:user, :post)</tt>
|
11
|
+
#
|
12
|
+
# Returns: <tt>self</tt>
|
13
|
+
attr_accessor :eager_loadings, :id_document_map, :id_associations_map
|
14
|
+
|
15
|
+
def includes(*options)
|
16
|
+
@eager_loadings = options
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
def preload(documents)
|
21
|
+
document_class = documents.first.class
|
22
|
+
@eager_loadings.each do |eager_loading|
|
23
|
+
setup_associations(documents, association_reflection(document_class, eager_loading))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
def ignore_includes
|
29
|
+
@eager_loadings = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def association_reflection(document_class, eager_loading)
|
33
|
+
document_class.reflect_on_association(eager_loading)
|
34
|
+
end
|
35
|
+
|
36
|
+
def setup_associations(documents, reflection)
|
37
|
+
if reflection.association == Mongoid::Associations::ReferencesOne
|
38
|
+
setup_associations_with_ids(documents, reflection, true)
|
39
|
+
elsif reflection.association == Mongoid::Associations::ReferencesMany
|
40
|
+
setup_associations_with_ids(documents, reflection, false)
|
41
|
+
elsif reflection.association == Mongoid::Associations::ReferencesManyAsArray
|
42
|
+
setup_associations_with_foreign_keys(documents, reflection, false)
|
43
|
+
elsif reflection.association == Mongoid::Associations::ReferencedIn
|
44
|
+
setup_associations_with_foreign_keys(documents, reflection, true)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def setup_associations_with_ids(documents, reflection, one=true)
|
49
|
+
ids = []
|
50
|
+
documents.each do |document|
|
51
|
+
id_document_map[document.id] = document
|
52
|
+
ids << document.id if document.id
|
53
|
+
end
|
54
|
+
|
55
|
+
association_class = reflection.name.singularize.camelize.constantize
|
56
|
+
ignore_includes
|
57
|
+
eager_associations = association_class.where(reflection.foreign_key.to_sym.in => ids).to_a
|
58
|
+
eager_associations.each do |eager_association|
|
59
|
+
add_id_association(eager_association.send(reflection.foreign_key), eager_association)
|
60
|
+
end
|
61
|
+
|
62
|
+
id_document_map.each do |id, document|
|
63
|
+
document.send("#{reflection.name}=", one ? id_associations_map[id].first : id_associations_map[id])
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def setup_associations_with_foreign_keys(documents, reflection, one)
|
68
|
+
ids = []
|
69
|
+
foreign_key_name = reflection.foreign_key
|
70
|
+
documents.each do |document|
|
71
|
+
foreign_key_value = document.send(foreign_key_name)
|
72
|
+
if one
|
73
|
+
id_document_map[foreign_key_value] = document
|
74
|
+
ids << foreign_key_value if foreign_key_value
|
75
|
+
elsif foreign_key_value
|
76
|
+
foreign_key_value.each do |fkv|
|
77
|
+
id_document_map[fkv] = document
|
78
|
+
ids << fkv if fkv
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
association_class = reflection.name.singularize.camelize.constantize
|
84
|
+
ignore_includes
|
85
|
+
eager_associations = association_class.find(ids).to_a
|
86
|
+
eager_associations.each do |eager_association|
|
87
|
+
add_id_association(eager_association.id, eager_association)
|
88
|
+
end
|
89
|
+
|
90
|
+
id_document_map.each do |id, document|
|
91
|
+
foreign_key_value = document.send(foreign_key_name)
|
92
|
+
associations = \
|
93
|
+
if one
|
94
|
+
id_associations_map[foreign_key_value].first
|
95
|
+
else
|
96
|
+
foreign_key_value.collect { |fkv| id_associations_map[fkv] }.flatten.uniq
|
97
|
+
end
|
98
|
+
document.send("#{reflection.name}=", associations)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def id_document_map
|
103
|
+
@id_doccument_map ||= {}
|
104
|
+
end
|
105
|
+
|
106
|
+
def id_associations_map
|
107
|
+
@id_associations_map ||= {}
|
108
|
+
end
|
109
|
+
|
110
|
+
def add_id_association(id, association)
|
111
|
+
id_associations_map[id] ||= []
|
112
|
+
id_associations_map[id] << association
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path("../lib/mongoid-eager-loading/version", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "mongoid-eager-loading"
|
6
|
+
s.version = Mongoid::EagerLoading::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ["Richard Huang"]
|
9
|
+
s.email = ["flyerhzm@gmail.com"]
|
10
|
+
s.homepage = "http://rubygems.org/gems/mongoid-eager-loading"
|
11
|
+
s.summary = "eager loading for mongoid"
|
12
|
+
s.description = "eager loading for mongoid"
|
13
|
+
|
14
|
+
s.required_rubygems_version = ">= 1.3.6"
|
15
|
+
s.rubyforge_project = "mongoid-eager-loading"
|
16
|
+
|
17
|
+
s.add_dependency "mongoid", "~> 2.0.0.beta.18"
|
18
|
+
|
19
|
+
s.add_development_dependency "bundler", ">= 1.0.0"
|
20
|
+
s.add_development_dependency "rspec", "~> 2.0.0"
|
21
|
+
s.add_development_dependency "mocha"
|
22
|
+
s.add_development_dependency "watchr"
|
23
|
+
s.add_development_dependency "bson_ext"
|
24
|
+
|
25
|
+
s.files = `git ls-files`.split("\n")
|
26
|
+
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
27
|
+
s.require_path = 'lib'
|
28
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
defaults: &defaults
|
2
|
+
host: localhost
|
3
|
+
slaves:
|
4
|
+
# - host: localhost
|
5
|
+
# port: 27018
|
6
|
+
# - host: localhost
|
7
|
+
# port: 27019
|
8
|
+
allow_dynamic_fields: false
|
9
|
+
include_root_in_json: true
|
10
|
+
parameterize_keys: false
|
11
|
+
persist_in_safe_mode: false
|
12
|
+
raise_not_found_error: false
|
13
|
+
reconnect_time: 5
|
14
|
+
autocreate_indexes: false
|
15
|
+
persist_types: false
|
16
|
+
option_no_exist: false
|
17
|
+
skip_version_check: false
|
18
|
+
|
19
|
+
test:
|
20
|
+
<<: *defaults
|
21
|
+
database: mongoid_config_test
|
@@ -0,0 +1,52 @@
|
|
1
|
+
class Address
|
2
|
+
include Mongoid::Document
|
3
|
+
|
4
|
+
attr_accessor :mode
|
5
|
+
|
6
|
+
field :address_type
|
7
|
+
field :number, :type => Integer
|
8
|
+
field :street
|
9
|
+
field :city
|
10
|
+
field :state
|
11
|
+
field :post_code
|
12
|
+
field :parent_title
|
13
|
+
field :services, :type => Array
|
14
|
+
field :latlng, :type => Array
|
15
|
+
key :street
|
16
|
+
embeds_many :locations
|
17
|
+
|
18
|
+
embedded_in :addressable, :inverse_of => :addresses do
|
19
|
+
def extension
|
20
|
+
"Testing"
|
21
|
+
end
|
22
|
+
def doctor?
|
23
|
+
title == "Dr"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
named_scope :rodeo, where(:street => "Rodeo Dr") do
|
28
|
+
def mansion?
|
29
|
+
all? { |address| address.street == "Rodeo Dr" }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
validates_presence_of :street, :on => :update
|
34
|
+
|
35
|
+
def set_parent=(set = false)
|
36
|
+
self.parent_title = addressable.title if set
|
37
|
+
end
|
38
|
+
|
39
|
+
class << self
|
40
|
+
def california
|
41
|
+
where(:state => "CA")
|
42
|
+
end
|
43
|
+
|
44
|
+
def homes
|
45
|
+
where(:address_type => "Home")
|
46
|
+
end
|
47
|
+
|
48
|
+
def streets
|
49
|
+
all.map(&:street)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|