Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

copy from pull request http://github.com/mongoid/mongoid/pull/391

  • Loading branch information...
commit 0e5f563ed17fb36019fff0ac4cf70fd09743b0e2 1 parent bd4b5db
@flyerhzm authored
Showing with 1,006 additions and 13 deletions.
  1. +1 −0  .gitignore
  2. +2 −0  .rvmrc.example
  3. +24 −0 .watchr
  4. +54 −0 Gemfile.lock
  5. +5 −4 lib/mongoid-eager-loading.rb
  6. +18 −0 lib/mongoid-eager-loading/mongoid/criteria.rb
  7. +116 −0 lib/mongoid-eager-loading/mongoid/criterion/eager_loading.rb
  8. +5 −0 lib/mongoid-eager-loading/mongoid/finders.rb
  9. +2 −4 lib/mongoid-eager-loading/version.rb
  10. +11 −5 mongoid-eager-loading.gemspec
  11. +21 −0 spec/config/mongoid.yml
  12. +10 −0 spec/models/account.rb
  13. +52 −0 spec/models/address.rb
  14. +8 −0 spec/models/agent.rb
  15. +15 −0 spec/models/animal.rb
  16. +4 −0 spec/models/answer.rb
  17. +47 −0 spec/models/callbacks.rb
  18. +13 −0 spec/models/category.rb
  19. +10 −0 spec/models/comment.rb
  20. +6 −0 spec/models/country_code.rb
  21. +8 −0 spec/models/description.rb
  22. +5 −0 spec/models/employer.rb
  23. +8 −0 spec/models/favorite.rb
  24. +14 −0 spec/models/game.rb
  25. +72 −0 spec/models/inheritance.rb
  26. +5 −0 spec/models/location.rb
  27. +6 −0 spec/models/login.rb
  28. +4 −0 spec/models/mixed_drink.rb
  29. +13 −0 spec/models/name.rb
  30. +11 −0 spec/models/namespacing.rb
  31. +18 −0 spec/models/paranoid_post.rb
  32. +32 −0 spec/models/parents.rb
  33. +15 −0 spec/models/patient.rb
  34. +113 −0 spec/models/person.rb
  35. +7 −0 spec/models/pet.rb
  36. +6 −0 spec/models/pet_owner.rb
  37. +7 −0 spec/models/phone.rb
  38. +25 −0 spec/models/post.rb
  39. +7 −0 spec/models/preference.rb
  40. +8 −0 spec/models/question.rb
  41. +6 −0 spec/models/survey.rb
  42. +5 −0 spec/models/translation.rb
  43. +8 −0 spec/models/user.rb
  44. +9 −0 spec/models/user_account.rb
  45. +5 −0 spec/models/vet_visit.rb
  46. +5 −0 spec/models/video.rb
  47. +28 −0 spec/mongoid-eager-loading/mongoid/criteria_spec.rb
  48. +103 −0 spec/mongoid-eager-loading/mongoid/criterion/eager_loading_spec.rb
  49. +29 −0 spec/spec_helper.rb
View
1  .gitignore
@@ -1,3 +1,4 @@
pkg/*
*.gem
.bundle
+.rvmrc
View
2  .rvmrc.example
@@ -0,0 +1,2 @@
+rvm_gemset_create_on_use_flag=1
+rvm gemset use mongoid-eager-loading
View
24 .watchr
@@ -0,0 +1,24 @@
+# vim:set filetype=ruby:
+def run(cmd)
+ puts cmd
+ system cmd
+end
+
+def spec(file)
+ if File.exists?(file)
+ run("rspec #{file}")
+ else
+ puts("Spec: #{file} does not exist.")
+ end
+end
+
+watch("spec/.*/*_spec\.rb") do |match|
+ puts(match[0])
+ spec(match[0])
+end
+
+watch("lib/(.*/.*)\.rb") do |match|
+ puts(match[1])
+ spec("spec/#{match[1]}_spec.rb")
+end
+
View
54 Gemfile.lock
@@ -0,0 +1,54 @@
+PATH
+ remote: .
+ specs:
+ mongoid-eager-loading (0.0.1)
+ mongoid (~> 2.0.0.beta.19)
+
+GEM
+ remote: http://rubygems.org/
+ specs:
+ activemodel (3.0.1)
+ activesupport (= 3.0.1)
+ builder (~> 2.1.2)
+ i18n (~> 0.4.1)
+ activesupport (3.0.1)
+ bson (1.1.1)
+ bson_ext (1.1.1)
+ builder (2.1.2)
+ diff-lcs (1.1.2)
+ i18n (0.4.1)
+ mocha (0.9.9)
+ rake
+ mongo (1.0.9)
+ bson (>= 1.0.5)
+ mongoid (2.0.0.beta.19)
+ activemodel (~> 3.0)
+ mongo (= 1.0.9)
+ tzinfo (~> 0.3.22)
+ will_paginate (~> 3.0.pre)
+ rake (0.8.7)
+ rspec (2.0.1)
+ rspec-core (~> 2.0.1)
+ rspec-expectations (~> 2.0.1)
+ rspec-mocks (~> 2.0.1)
+ rspec-core (2.0.1)
+ rspec-expectations (2.0.1)
+ diff-lcs (>= 1.1.2)
+ rspec-mocks (2.0.1)
+ rspec-core (~> 2.0.1)
+ rspec-expectations (~> 2.0.1)
+ tzinfo (0.3.23)
+ watchr (0.7)
+ will_paginate (3.0.pre2)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ bson_ext
+ bundler (>= 1.0.0)
+ mocha
+ mongoid (~> 2.0.0.beta.19)
+ mongoid-eager-loading!
+ rspec (~> 2.0.0)
+ watchr
View
9 lib/mongoid-eager-loading.rb
@@ -1,7 +1,8 @@
+require 'mongoid-eager-loading/mongoid/criterion/eager_loading'
+require 'mongoid-eager-loading/mongoid/criteria'
+require 'mongoid-eager-loading/mongoid/finders'
+
module Mongoid
- module Eager
- module Loading
- # Your code goes here...
- end
+ module EagerLoading
end
end
View
18 lib/mongoid-eager-loading/mongoid/criteria.rb
@@ -0,0 +1,18 @@
+Mongoid::Criteria.class_eval do
+ include Mongoid::Criterion::EagerLoading
+
+ alias_method :origin_each, :each
+
+ def each(&block)
+ if @eager_loadings
+ # if eager loadings are used, preload the associations.
+ docs = []
+ context.iterate { |doc| docs << doc }
+ preload(docs)
+ docs.each(&block)
+ self
+ else
+ origin_each(&block)
+ end
+ end
+end
View
116 lib/mongoid-eager-loading/mongoid/criterion/eager_loading.rb
@@ -0,0 +1,116 @@
+module Mongoid
+ module Criterion
+ module EagerLoading
+ # EagerLoading criterion are used when eager loading the associations.
+ #
+ # Example:
+ #
+ # <tt>criteria.includes(:user)</tt>
+ #
+ # <tt>criteria.includes(:user, :post)</tt>
+ #
+ # Returns: <tt>self</tt>
+ attr_accessor :eager_loadings, :id_document_map, :id_associations_map
+
+ def includes(*options)
+ @eager_loadings = options
+ self
+ end
+
+ def preload(documents)
+ document_class = documents.first.class
+ @eager_loadings.each do |eager_loading|
+ setup_associations(documents, association_reflection(document_class, eager_loading))
+ end
+ end
+
+ private
+ def ignore_includes
+ @eager_loadings = nil
+ end
+
+ def association_reflection(document_class, eager_loading)
+ document_class.reflect_on_association(eager_loading)
+ end
+
+ def setup_associations(documents, reflection)
+ if reflection.association == Mongoid::Associations::ReferencesOne
+ setup_associations_with_ids(documents, reflection, true)
+ elsif reflection.association == Mongoid::Associations::ReferencesMany
+ setup_associations_with_ids(documents, reflection, false)
+ elsif reflection.association == Mongoid::Associations::ReferencesManyAsArray
+ setup_associations_with_foreign_keys(documents, reflection, false)
+ elsif reflection.association == Mongoid::Associations::ReferencedIn
+ setup_associations_with_foreign_keys(documents, reflection, true)
+ end
+ end
+
+ def setup_associations_with_ids(documents, reflection, one=true)
+ ids = []
+ documents.each do |document|
+ id_document_map[document.id] = document
+ ids << document.id
+ end
+
+ association_class = reflection.name.singularize.camelize.constantize
+ ignore_includes
+ eager_associations = association_class.where(reflection.foreign_key.to_sym.in => ids).to_a
+ eager_associations.each do |eager_association|
+ add_id_association(eager_association.send(reflection.foreign_key), eager_association)
+ end
+
+ id_document_map.each do |id, document|
+ document.send("#{reflection.name}=", one ? id_associations_map[id].first : id_associations_map[id])
+ end
+ end
+
+ def setup_associations_with_foreign_keys(documents, reflection, one)
+ ids = []
+ foreign_key_name = reflection.foreign_key
+ documents.each do |document|
+ foreign_key_value = document.send(foreign_key_name)
+ if one
+ id_document_map[foreign_key_value] = document
+ ids << foreign_key_value
+ elsif foreign_key_value
+ foreign_key_value.each do |fkv|
+ id_document_map[fkv] = document
+ ids << fkv
+ end
+ end
+ end
+
+ association_class = reflection.name.singularize.camelize.constantize
+ ignore_includes
+ eager_associations = association_class.find(ids).to_a
+ eager_associations.each do |eager_association|
+ add_id_association(eager_association.id, eager_association)
+ end
+
+ id_document_map.each do |id, document|
+ foreign_key_value = document.send(foreign_key_name)
+ associations = \
+ if one
+ id_associations_map[foreign_key_value].first
+ else
+ foreign_key_value.collect { |fkv| id_associations_map[fkv] }.flatten.uniq
+ end
+ document.send("#{reflection.name}=", associations)
+ end
+ end
+
+ def id_document_map
+ @id_doccument_map ||= {}
+ end
+
+ def id_associations_map
+ @id_associations_map ||= {}
+ end
+
+ def add_id_association(id, association)
+ id_associations_map[id] ||= []
+ id_associations_map[id] << association
+ end
+ end
+ end
+end
View
5 lib/mongoid-eager-loading/mongoid/finders.rb
@@ -0,0 +1,5 @@
+Mongoid::Finders.class_eval do
+ def includes(*args)
+ criteria.send(:includes, *args)
+ end
+end
View
6 lib/mongoid-eager-loading/version.rb
@@ -1,7 +1,5 @@
module Mongoid
- module Eager
- module Loading
- VERSION = "0.0.1"
- end
+ module EagerLoading
+ VERSION = "0.0.1"
end
end
View
16 mongoid-eager-loading.gemspec
@@ -3,18 +3,24 @@ require File.expand_path("../lib/mongoid-eager-loading/version", __FILE__)
Gem::Specification.new do |s|
s.name = "mongoid-eager-loading"
- s.version = Mongoid::Eager::Loading::VERSION
+ s.version = Mongoid::EagerLoading::VERSION
s.platform = Gem::Platform::RUBY
- s.authors = []
- s.email = []
+ s.authors = ["Richard Huang"]
+ s.email = ["flyerhzm@gmail.com"]
s.homepage = "http://rubygems.org/gems/mongoid-eager-loading"
- s.summary = "TODO: Write a gem summary"
- s.description = "TODO: Write a gem description"
+ s.summary = "eager loading for mongoid"
+ s.description = "eager loading for mongoid"
s.required_rubygems_version = ">= 1.3.6"
s.rubyforge_project = "mongoid-eager-loading"
+ s.add_dependency "mongoid", "~> 2.0.0.beta.18"
+
s.add_development_dependency "bundler", ">= 1.0.0"
+ s.add_development_dependency "rspec", "~> 2.0.0"
+ s.add_development_dependency "mocha"
+ s.add_development_dependency "watchr"
+ s.add_development_dependency "bson_ext"
s.files = `git ls-files`.split("\n")
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
View
21 spec/config/mongoid.yml
@@ -0,0 +1,21 @@
+defaults: &defaults
+ host: localhost
+ slaves:
+ # - host: localhost
+ # port: 27018
+ # - host: localhost
+ # port: 27019
+ allow_dynamic_fields: false
+ include_root_in_json: true
+ parameterize_keys: false
+ persist_in_safe_mode: false
+ raise_not_found_error: false
+ reconnect_time: 5
+ autocreate_indexes: false
+ persist_types: false
+ option_no_exist: false
+ skip_version_check: false
+
+test:
+ <<: *defaults
+ database: mongoid_config_test
View
10 spec/models/account.rb
@@ -0,0 +1,10 @@
+class Account
+ include Mongoid::Document
+ referenced_in :creator, :class_name => "User", :foreign_key => :creator_id
+ referenced_in :person
+ field :number
+ field :balance
+ field :nickname
+
+ attr_accessible :nickname
+end
View
52 spec/models/address.rb
@@ -0,0 +1,52 @@
+class Address
+ include Mongoid::Document
+
+ attr_accessor :mode
+
+ field :address_type
+ field :number, :type => Integer
+ field :street
+ field :city
+ field :state
+ field :post_code
+ field :parent_title
+ field :services, :type => Array
+ field :latlng, :type => Array
+ key :street
+ embeds_many :locations
+
+ embedded_in :addressable, :inverse_of => :addresses do
+ def extension
+ "Testing"
+ end
+ def doctor?
+ title == "Dr"
+ end
+ end
+
+ named_scope :rodeo, where(:street => "Rodeo Dr") do
+ def mansion?
+ all? { |address| address.street == "Rodeo Dr" }
+ end
+ end
+
+ validates_presence_of :street, :on => :update
+
+ def set_parent=(set = false)
+ self.parent_title = addressable.title if set
+ end
+
+ class << self
+ def california
+ where(:state => "CA")
+ end
+
+ def homes
+ where(:address_type => "Home")
+ end
+
+ def streets
+ all.map(&:street)
+ end
+ end
+end
View
8 spec/models/agent.rb
@@ -0,0 +1,8 @@
+class Agent
+ include Mongoid::Document
+ field :title
+ field :number
+ embeds_many :names
+ references_many :posts, :foreign_key => :poster_id
+ accepts_nested_attributes_for :posts, :allow_destroy => true
+end
View
15 spec/models/animal.rb
@@ -0,0 +1,15 @@
+class Animal
+ include Mongoid::Document
+ field :name
+ field :tags, :type => Array
+ key :name
+ embedded_in :person, :inverse_of => :pet
+
+ def tag_list
+ tags.join(", ")
+ end
+
+ def tag_list=(_tag_list)
+ self.tags = _tag_list.split(",").map(&:strip)
+ end
+end
View
4 spec/models/answer.rb
@@ -0,0 +1,4 @@
+class Answer
+ include Mongoid::Document
+ embedded_in :question, :inverse_of => :answers
+end
View
47 spec/models/callbacks.rb
@@ -0,0 +1,47 @@
+class Artist
+ include Mongoid::Document
+ field :name
+ embeds_many :songs
+ embeds_many :labels
+
+ before_create :before_create_stub
+ after_create :create_songs
+
+ protected
+ def before_create_stub
+ true
+ end
+
+ def create_songs
+ 2.times { |n| songs.create!(:title => "#{n}") }
+ end
+end
+
+class Song
+ include Mongoid::Document
+ field :title
+ embedded_in :artist, :inverse_of => :songs
+end
+
+class Label
+ include Mongoid::Document
+ field :name
+ embedded_in :artist, :inverse_of => :labels
+ before_validation :cleanup
+
+ private
+ def cleanup
+ self.name = self.name.downcase.capitalize
+ end
+end
+
+class ValidationCallback
+ include Mongoid::Document
+ field :history, :type => Array, :default => []
+ validate do
+ self.history << :validate
+ end
+
+ before_validation { self.history << :before_validation }
+ after_validation { self.history << :after_validation }
+end
View
13 spec/models/category.rb
@@ -0,0 +1,13 @@
+class RootCategory
+ include Mongoid::Document
+ embeds_many :categories
+end
+
+class Category
+ include Mongoid::Document
+ embedded_in :root_category, :inverse_of => :categories
+ embedded_in :category, :inverse_of => :categories
+ embeds_many :categories
+
+ field :name
+end
View
10 spec/models/comment.rb
@@ -0,0 +1,10 @@
+class Comment
+ include Mongoid::Document
+ include Mongoid::Versioning
+ include Mongoid::Timestamps
+ field :title
+
+ field :text
+ key :text
+ validates_presence_of :text
+end
View
6 spec/models/country_code.rb
@@ -0,0 +1,6 @@
+class CountryCode
+ include Mongoid::Document
+ field :code, :type => Integer
+ key :code
+ embedded_in :phone_number, :inverse_of => :country_codes
+end
View
8 spec/models/description.rb
@@ -0,0 +1,8 @@
+class Description
+ include Mongoid::Document
+
+ field :details
+
+ referenced_in :user
+ referenced_in :updater, :class_name => 'User'
+end
View
5 spec/models/employer.rb
@@ -0,0 +1,5 @@
+class Employer
+ def id
+ "1"
+ end
+end
View
8 spec/models/favorite.rb
@@ -0,0 +1,8 @@
+class Favorite
+ include Mongoid::Document
+
+ field :title
+ validates_uniqueness_of :title, :case_sensitive => false
+
+ embedded_in :person, :inverse_of => :favorites
+end
View
14 spec/models/game.rb
@@ -0,0 +1,14 @@
+class Game
+ include Mongoid::Document
+ field :high_score, :type => Integer, :default => 500
+ field :score, :type => Integer, :default => 0
+ field :name
+ referenced_in :person, :index => true
+ enslave and cache
+
+ attr_protected :_id
+
+ set_callback(:initialize, :after) do |document|
+ write_attribute("name", "Testing")
+ end
+end
View
72 spec/models/inheritance.rb
@@ -0,0 +1,72 @@
+class Canvas
+ include Mongoid::Document
+ field :name
+ embeds_many :shapes
+ embeds_one :writer
+ embeds_one :palette
+
+ def render
+ shapes.each { |shape| render }
+ end
+end
+
+class Browser < Canvas
+ field :version, :type => Integer
+ def render; end
+end
+
+class Firefox < Browser
+ field :user_agent
+ def render; end
+end
+
+class Shape
+ include Mongoid::Document
+ field :x, :type => Integer, :default => 0
+ field :y, :type => Integer, :default => 0
+
+ embedded_in :canvas, :inverse_of => :shapes
+
+ def render; end
+end
+
+class Square < Shape
+ field :width, :type => Integer, :default => 0
+ field :height, :type => Integer, :default => 0
+end
+
+class Circle < Shape
+ field :radius, :type => Integer, :default => 0
+end
+
+class Writer
+ include Mongoid::Document
+ field :speed, :type => Integer, :default => 0
+
+ embedded_in :canvas, :inverse_of => :writer
+
+ def write; end
+end
+
+class HtmlWriter < Writer
+ def write; end
+end
+
+class PdfWriter < Writer
+ def write; end
+end
+
+class Palette
+ include Mongoid::Document
+ embedded_in :canvas, :inverse_of => :palette
+ embeds_many :tools
+end
+
+class Tool
+ include Mongoid::Document
+ embedded_in :palette, :inverse_of => :tools
+end
+
+class Pencil < Tool; end
+
+class Eraser < Tool; end
View
5 spec/models/location.rb
@@ -0,0 +1,5 @@
+class Location
+ include Mongoid::Document
+ field :name
+ embedded_in :address, :inverse_of => :locations
+end
View
6 spec/models/login.rb
@@ -0,0 +1,6 @@
+class Login
+ include Mongoid::Document
+ field :username
+ key :username
+ validates_uniqueness_of :username
+end
View
4 spec/models/mixed_drink.rb
@@ -0,0 +1,4 @@
+class MixedDrink
+ include Mongoid::Document
+ field :name
+end
View
13 spec/models/name.rb
@@ -0,0 +1,13 @@
+class Name
+ include Mongoid::Document
+ field :first_name
+ field :last_name
+ field :parent_title
+ key :first_name, :last_name
+ embeds_many :translations
+ embedded_in :namable, :inverse_of => [:name, :names]
+
+ def set_parent=(set = false)
+ self.parent_title = namable.title if set
+ end
+end
View
11 spec/models/namespacing.rb
@@ -0,0 +1,11 @@
+module Medical
+ class Patient
+ include Mongoid::Document
+ field :name
+ embeds_many :prescriptions, :class_name => "Medical::Prescription"
+ end
+ class Prescription
+ include Mongoid::Document
+ field :name
+ end
+end
View
18 spec/models/paranoid_post.rb
@@ -0,0 +1,18 @@
+class ParanoidPost
+ include Mongoid::Document
+ include Mongoid::Versioning
+ include Mongoid::Timestamps
+ include Mongoid::Paranoia
+ field :title
+ referenced_in :person
+
+ references_many :tags, :stored_as => :array
+
+ named_scope :recent, where(:created_at => { "$lt" => Time.now, "$gt" => 30.days.ago })
+
+ class << self
+ def old
+ where(:created_at => { "$lt" => 30.days.ago })
+ end
+ end
+end
View
32 spec/models/parents.rb
@@ -0,0 +1,32 @@
+class ParentDoc
+ include Mongoid::Document
+
+ embeds_many :child_docs
+
+ field :statistic
+ field :children_order, :type => Array, :default => [] # hold all the children's id
+end
+
+
+class ChildDoc
+ include Mongoid::Document
+
+ embedded_in :parent_doc, :inverse_of => :child_docs
+
+ attr_writer :position
+
+ after_save :update_position
+
+ def position
+ exsited_position = parent_doc.children_order.index(id)
+ exsited_position ? exsited_position + 1 : parent_doc.aspects.size
+ end
+
+ def update_position
+ if @position && (@position.to_i > 0)
+ parent_doc.children_order.delete(id)
+ parent_doc.children_order.insert(@position.to_i - 1, id)
+ parent_doc.save
+ end
+ end
+end
View
15 spec/models/patient.rb
@@ -0,0 +1,15 @@
+class Email
+ include Mongoid::Document
+ field :address
+ validates_uniqueness_of :address
+ embedded_in :patient, :inverse_of => :email
+end
+
+class Patient
+ include Mongoid::Document
+ field :title
+ store_in :inpatient
+ embeds_many :addresses
+ embeds_one :email
+ validates_presence_of :title, :on => :create
+end
View
113 spec/models/person.rb
@@ -0,0 +1,113 @@
+class Person
+ include Mongoid::Document
+ include Mongoid::Timestamps
+ include Mongoid::EagerLoading
+
+ attr_accessor :mode
+
+ field :title
+ field :terms, :type => Boolean
+ field :pets, :type => Boolean, :default => false
+ field :age, :type => Integer, :default => 100
+ field :dob, :type => Date
+ field :mixed_drink, :type => MixedDrink
+ field :employer_id
+ field :lunch_time, :type => Time
+ field :aliases, :type => Array
+ field :map, :type => Hash
+ field :score, :type => Integer
+ field :blood_alcohol_content, :type => Float, :default => lambda{ 0.0 }
+ field :last_drink_taken_at, :type => Date, :default => lambda { 1.day.ago.in_time_zone("Alaska") }
+ field :ssn
+ field :owner_id, :type => Integer
+ field :security_code
+ field :reading, :type => Object
+
+ index :age
+ index :addresses
+ index :dob
+ index :name
+ index :title
+ index :ssn, :unique => true
+
+ attr_reader :rescored
+
+ attr_protected :security_code, :owner_id
+
+ embeds_many :favorites
+ embeds_many :videos
+ embeds_many :phone_numbers, :class_name => "Phone"
+ embeds_many :addresses do
+ def extension
+ "Testing"
+ end
+ def find_by_street(street)
+ @target.select { |doc| doc.street == street }
+ end
+ end
+
+ embeds_one :pet, :class_name => "Animal"
+ embeds_one :name do
+ def extension
+ "Testing"
+ end
+ def dawkins?
+ first_name == "Richard" && last_name == "Dawkins"
+ end
+ end
+
+ accepts_nested_attributes_for :addresses, :reject_if => lambda { |attrs| attrs["street"].blank? }
+ accepts_nested_attributes_for :name, :update_only => true
+ accepts_nested_attributes_for :pet, :allow_destroy => true
+ accepts_nested_attributes_for :game, :allow_destroy => true
+ accepts_nested_attributes_for :favorites, :allow_destroy => true, :limit => 5
+
+ references_one :game, :dependent => :destroy do
+ def extension
+ "Testing"
+ end
+ end
+
+ references_many :posts, :dependent => :delete do
+ def extension
+ "Testing"
+ end
+ end
+ references_many :paranoid_posts
+ references_many :preferences, :stored_as => :array, :inverse_of => :people, :index => true
+ references_many :user_accounts, :stored_as => :array, :inverse_of => :person
+
+ def score_with_rescoring=(score)
+ @rescored = score.to_i + 20
+ self.score_without_rescoring = score
+ end
+
+ alias_method_chain :score=, :rescoring
+
+ def update_addresses
+ addresses.each do |address|
+ address.street = "Updated Address"
+ end
+ end
+
+ def employer=(emp)
+ self.employer_id = emp.id
+ end
+
+ class << self
+ def accepted
+ criteria.where(:terms => true)
+ end
+ def knight
+ criteria.where(:title => "Sir")
+ end
+ def old
+ criteria.where(:age => { "$gt" => 50 })
+ end
+ end
+
+end
+
+class Doctor < Person
+ field :specialty
+end
View
7 spec/models/pet.rb
@@ -0,0 +1,7 @@
+class Pet
+ include Mongoid::Document
+ field :name
+ field :weight, :type => Float, :default => 0.0
+ embeds_many :vet_visits
+ embedded_in :pet_owner, :inverse_of => :pet
+end
View
6 spec/models/pet_owner.rb
@@ -0,0 +1,6 @@
+class PetOwner
+ include Mongoid::Document
+ field :title
+ embeds_one :pet
+ embeds_one :address
+end
View
7 spec/models/phone.rb
@@ -0,0 +1,7 @@
+class Phone
+ include Mongoid::Document
+ field :number
+ key :number
+ embeds_one :country_code
+ embedded_in :person, :inverse_of => :phone_numbers
+end
View
25 spec/models/post.rb
@@ -0,0 +1,25 @@
+class Tag
+ include Mongoid::Document
+ field :text
+ referenced_in :post, :stored_as => :array
+end
+
+class Post
+ include Mongoid::Document
+ include Mongoid::Versioning
+ include Mongoid::Timestamps
+ field :title
+ referenced_in :person
+ referenced_in :author, :foreign_key => :author_id, :class_name => "User"
+ referenced_in :poster, :foreign_key => :poster_id, :class_name => "Agent"
+
+ references_many :tags, :stored_as => :array
+
+ named_scope :recent, where(:created_at => { "$lt" => Time.now, "$gt" => 30.days.ago })
+
+ class << self
+ def old
+ where(:created_at => { "$lt" => 30.days.ago })
+ end
+ end
+end
View
7 spec/models/preference.rb
@@ -0,0 +1,7 @@
+class Preference
+ include Mongoid::Document
+ field :name
+ field :value
+ references_many :people, :stored_as => :array, :inverse_of => :preferences
+ validates_length_of :name, :minimum => 2, :allow_nil => true
+end
View
8 spec/models/question.rb
@@ -0,0 +1,8 @@
+class Question
+ include Mongoid::Document
+ field :content
+ embedded_in :survey, :inverse_of => :questions
+ embeds_many :answers
+
+ accepts_nested_attributes_for :answers, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
+end
View
6 spec/models/survey.rb
@@ -0,0 +1,6 @@
+class Survey
+ include Mongoid::Document
+ embeds_many :questions
+
+ accepts_nested_attributes_for :questions, :reject_if => lambda{ |a| a[:content].blank? }, :allow_destroy => true
+end
View
5 spec/models/translation.rb
@@ -0,0 +1,5 @@
+class Translation
+ include Mongoid::Document
+ field :language
+ embedded_in :name, :inverse_of => :translations
+end
View
8 spec/models/user.rb
@@ -0,0 +1,8 @@
+class User
+ include Mongoid::Document
+ references_one :account, :foreign_key => :creator_id
+ references_many :posts, :foreign_key => :author_id, :inverse_of => :author
+ field :name
+
+ references_many :descriptions
+end
View
9 spec/models/user_account.rb
@@ -0,0 +1,9 @@
+class UserAccount
+ include Mongoid::Document
+ field :username
+ field :email
+ validates_uniqueness_of :username, :message => "is not unique"
+ validates_uniqueness_of :email, :message => "is not unique", :case_sensitive => false
+
+ referenced_in :person, :inverse_of => :user_accounts
+end
View
5 spec/models/vet_visit.rb
@@ -0,0 +1,5 @@
+class VetVisit
+ include Mongoid::Document
+ field :date, :type => Date
+ embedded_in :pet, :inverse_of => :vet_visits
+end
View
5 spec/models/video.rb
@@ -0,0 +1,5 @@
+class Video
+ include Mongoid::Document
+ field :title
+ embedded_in :person, :inverse_of => :videos
+end
View
28 spec/mongoid-eager-loading/mongoid/criteria_spec.rb
@@ -0,0 +1,28 @@
+require "spec_helper"
+
+describe Mongoid::Criteria do
+
+ describe "#each" do
+
+ before :each do
+ @person1 = Person.create(:title => "Sir", :age => 100, :aliases => ["D", "Durran"], :ssn => "666666666")
+ @person2 = Person.create(:title => "Madam", :age => 1, :ssn => "098-76-5434")
+ @person1.create_game(:score => 10)
+ @person2.create_game(:score => 20)
+ end
+
+ after :each do
+ Person.destroy_all
+ end
+
+ it "without includes" do
+ criteria = Person.all
+ criteria.collect(&:title).should == ["Sir", "Madam"]
+ end
+
+ it "with includes" do
+ criteria = Person.includes(:game)
+ criteria.collect(&:game).should == [@person1.game, @person2.game]
+ end
+ end
+end
View
103 spec/mongoid-eager-loading/mongoid/criterion/eager_loading_spec.rb
@@ -0,0 +1,103 @@
+require "spec_helper"
+
+describe Mongoid::Criterion::EagerLoading do
+
+ describe "#includes" do
+
+ it "should return self" do
+ criteria = Mongoid::Criteria.new(Person)
+ criteria.includes(:game, :posts).should == criteria
+ end
+
+ it "set eager loadings" do
+ criteria = Mongoid::Criteria.new(Person)
+ criteria.includes(:game, :posts)
+ criteria.eager_loadings.should == [:game, :posts]
+ end
+ end
+
+ describe "#preload" do
+
+ before do
+ person1 = Person.create(:title => "Sir", :age => 100, :aliases => ["D", "Durran"], :ssn => "666666666")
+ person2 = Person.create(:title => "Madam", :age => 1, :ssn => "098-76-5434")
+
+ person1.create_game(:score => 10)
+ person2.create_game(:score => 20)
+
+ person1.posts.create(:title => "post1")
+ person1.posts.create(:title => "post2")
+ person2.posts.create(:title => "post3")
+ person2.posts.create(:title => "post4")
+
+ person1.preferences.create(:name => "preference1")
+ person1.preferences.create(:name => "preference2")
+ person2.preferences.create(:name => "preference3")
+ person2.preferences.create(:name => "preference4")
+ end
+
+ it "preload references_one association" do
+ people = Person.all.to_a
+ games = Game.all.to_a
+
+ complex = stub(:key => :person_id, :operator => "in")
+ Mongoid::Criterion::Complex.expects(:new).with(:key => :person_id, :operator => "in").returns(complex)
+ Game.expects(:where).with(complex => people.collect(&:id)).returns(games)
+
+ criteria = Mongoid::Criteria.new(Person)
+ criteria.includes(:game)
+ criteria.preload(people)
+
+ people.first.game.should == games.first
+ people.last.game.should == games.last
+ end
+
+ it "preload references_many association" do
+ people = Person.all.to_a
+ posts = Post.all.to_a
+ person1_posts = Post.where(:person_id => people.first.id).to_a
+ person2_posts = Post.where(:person_id => people.last.id).to_a
+
+ complex = stub(:key => :person_id, :operator => "in")
+ Mongoid::Criterion::Complex.expects(:new).with(:key => :person_id, :operator => "in").returns(complex)
+ Post.expects(:where).with(complex => people.collect(&:id)).returns(posts)
+
+ criteria = Mongoid::Criteria.new(Person)
+ criteria.includes(:posts)
+ criteria.preload(people)
+
+ people.first.posts.should == person1_posts
+ people.last.posts.should == person2_posts
+ end
+
+ it "preload references_many_as_array association" do
+ people = Person.all.to_a
+ preferences = Preference.all.to_a
+ person1_preferences = Preference.find(people.first.preference_ids).to_a
+ person2_preferences = Preference.find(people.last.preference_ids).to_a
+
+ Preference.expects(:find).with(preferences.collect(&:id)).returns(preferences)
+
+ criteria = Mongoid::Criteria.new(Person)
+ criteria.includes(:preferences)
+ criteria.preload(people)
+
+ people.first.preferences.should == person1_preferences
+ people.last.preferences.should == person2_preferences
+ end
+
+ it "preload referenced_in association" do
+ people = Person.all.to_a
+ games = Game.all.to_a
+
+ Person.expects(:find).with(people.collect(&:id)).returns(people)
+
+ criteria = Mongoid::Criteria.new(Game)
+ criteria.includes(:person)
+ criteria.preload(games)
+
+ people.first.game.should == games.first
+ people.last.game.should == games.last
+ end
+ end
+end
View
29 spec/spec_helper.rb
@@ -0,0 +1,29 @@
+$LOAD_PATH.unshift(File.dirname(__FILE__))
+$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
+
+MODELS = File.join(File.dirname(__FILE__), "models")
+$LOAD_PATH.unshift(MODELS)
+
+require "mongoid"
+require "mongoid-eager-loading"
+require "mocha"
+require "rspec"
+
+Mongoid.configure do |config|
+ name = "mongoid_test"
+ host = "localhost"
+ config.master = Mongo::Connection.new.db(name)
+ config.logger = nil
+ # config.slaves = [
+ # Mongo::Connection.new(host, 27018, :slave_ok => true).db(name)
+ # ]
+end
+
+Dir[ File.join(MODELS, "*.rb") ].sort.each { |file| require File.basename(file) }
+
+Rspec.configure do |config|
+ config.mock_with :mocha
+ config.after :suite do
+ Mongoid.master.collections.select {|c| c.name !~ /system/ }.each(&:drop)
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.