mongoid_includes 1.0.5
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +17 -0
- data/LICENSE.txt +20 -0
- data/README.md +49 -0
- data/Rakefile +31 -0
- data/lib/config/locales/en.yml +19 -0
- data/lib/mongoid/includes.rb +4 -0
- data/lib/mongoid/includes/criteria.rb +67 -0
- data/lib/mongoid/includes/eager_load.rb +50 -0
- data/lib/mongoid/includes/errors.rb +2 -0
- data/lib/mongoid/includes/errors/invalid_includes.rb +30 -0
- data/lib/mongoid/includes/errors/invalid_polymorphic_includes.rb +16 -0
- data/lib/mongoid/includes/inclusion.rb +64 -0
- data/lib/mongoid/includes/inclusions.rb +40 -0
- data/lib/mongoid/includes/relations/eager.rb +19 -0
- data/lib/mongoid/includes/version.rb +10 -0
- data/lib/mongoid_includes.rb +12 -0
- data/spec/mongoid/includes/criteria_spec.rb +25 -0
- data/spec/mongoid/includes/errors/invalid_includes_spec.rb +29 -0
- data/spec/mongoid/includes/errors/invalid_polymorphic_includes_spec.rb +29 -0
- data/spec/mongoid/includes/inclusions_spec.rb +23 -0
- data/spec/mongoid/includes/nested_inclusions_spec.rb +52 -0
- data/spec/mongoid/includes/simple_inclusions_spec.rb +1010 -0
- data/spec/spec_helper.rb +60 -0
- data/spec/support/config/mongoid.yml +27 -0
- data/spec/support/helpers.rb +47 -0
- data/spec/support/models/address.rb +69 -0
- data/spec/support/models/album.rb +9 -0
- data/spec/support/models/artist.rb +8 -0
- data/spec/support/models/band.rb +25 -0
- data/spec/support/models/game.rb +18 -0
- data/spec/support/models/musician.rb +10 -0
- data/spec/support/models/person.rb +72 -0
- data/spec/support/models/post.rb +11 -0
- data/spec/support/models/preference.rb +11 -0
- data/spec/support/models/record.rb +50 -0
- data/spec/support/models/song.rb +7 -0
- metadata +123 -0
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
if ENV['CODECLIMATE_REPO_TOKEN']
|
2
|
+
require 'codeclimate-test-reporter'
|
3
|
+
CodeClimate::TestReporter.start
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'rspec/given'
|
7
|
+
require 'pry'
|
8
|
+
require 'mongoid_includes'
|
9
|
+
|
10
|
+
# Load Support files
|
11
|
+
Dir['./spec/support/**/*.rb'].map do |f|
|
12
|
+
require f
|
13
|
+
end
|
14
|
+
|
15
|
+
def mongodb_version
|
16
|
+
session = Mongoid::Sessions.default
|
17
|
+
session.command(buildinfo: 1)[version]
|
18
|
+
end
|
19
|
+
|
20
|
+
I18n.config.enforce_available_locales = false
|
21
|
+
|
22
|
+
# These are used when creating any connection in the test suite.
|
23
|
+
HOST = ENV['MONGOID_SPEC_HOST'] ||= 'localhost'
|
24
|
+
PORT = ENV['MONGOID_SPEC_PORT'] ||= '27017'
|
25
|
+
DATABASE = ENV['MONGOID_DATABASE'] ||= 'mongoid_test'
|
26
|
+
|
27
|
+
# Set the database that the spec suite connects to.
|
28
|
+
Mongoid.configure do |config|
|
29
|
+
config.load_configuration(
|
30
|
+
clients: {
|
31
|
+
default: {
|
32
|
+
database: DATABASE,
|
33
|
+
hosts: [ "#{HOST}:#{PORT.to_i}" ],
|
34
|
+
options: {
|
35
|
+
max_pool_size: 1,
|
36
|
+
}
|
37
|
+
}
|
38
|
+
},
|
39
|
+
sessions: {
|
40
|
+
default: {
|
41
|
+
database: DATABASE,
|
42
|
+
hosts: [ "#{HOST}:#{PORT.to_i}" ]
|
43
|
+
}
|
44
|
+
}
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
if defined?(Mongo)
|
49
|
+
Mongo::Logger.logger = Logger.new("./spec/mongo.log")
|
50
|
+
end
|
51
|
+
|
52
|
+
RSpec.configure do |config|
|
53
|
+
config.include Mongoid::SpecHelpers
|
54
|
+
config.raise_errors_for_deprecations!
|
55
|
+
|
56
|
+
# Drop all collections and clear the identity map before each spec.
|
57
|
+
config.before(:each) do
|
58
|
+
Mongoid.purge!
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
test:
|
2
|
+
clients:
|
3
|
+
default:
|
4
|
+
database: mongoid_test
|
5
|
+
hosts:
|
6
|
+
- <%=ENV["MONGOID_SPEC_HOST"]%>:<%=ENV["MONGOID_SPEC_PORT"]%>
|
7
|
+
options:
|
8
|
+
read:
|
9
|
+
mode: :primary
|
10
|
+
max_pool_size: 1
|
11
|
+
|
12
|
+
sessions:
|
13
|
+
default:
|
14
|
+
database: mongoid_test
|
15
|
+
hosts:
|
16
|
+
- <%=ENV["MONGOID_SPEC_HOST"]%>:<%=ENV["MONGOID_SPEC_PORT"]%>
|
17
|
+
options:
|
18
|
+
read: primary
|
19
|
+
|
20
|
+
options:
|
21
|
+
include_root_in_json: false
|
22
|
+
include_type_for_serialization: false
|
23
|
+
preload_models: false
|
24
|
+
scope_overwrite_exception: false
|
25
|
+
raise_not_found_error: true
|
26
|
+
use_activesupport_time_zone: true
|
27
|
+
use_utc: false
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Mongoid
|
2
|
+
class QueryCounter
|
3
|
+
attr_reader :events
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@events = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def instrument
|
10
|
+
subscriber = ActiveSupport::Notifications.subscribe('query.moped') do |*args|
|
11
|
+
@events << ActiveSupport::Notifications::Event.new(*args)
|
12
|
+
end
|
13
|
+
yield
|
14
|
+
ensure
|
15
|
+
ActiveSupport::Notifications.unsubscribe(subscriber)
|
16
|
+
end
|
17
|
+
|
18
|
+
def inspect
|
19
|
+
@events.map { |e| e.payload[:ops].map(&:log_inspect) }.join("\n")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
module Mongoid
|
25
|
+
module SpecHelpers
|
26
|
+
if defined?(Mongo::Logger.logger)
|
27
|
+
def expect_query(number)
|
28
|
+
# There are both start and complete events for each query.
|
29
|
+
expect(Mongo::Logger.logger).to receive(:debug?).exactly(number * 4).times.and_call_original
|
30
|
+
yield
|
31
|
+
end
|
32
|
+
else
|
33
|
+
def expect_query(number, &block)
|
34
|
+
query_counter = Mongoid::QueryCounter.new
|
35
|
+
query_counter.instrument(&block)
|
36
|
+
expect(query_counter.events.size).to(eq(number), %[
|
37
|
+
Expected to receive #{number} queries, it received #{query_counter.events.size}
|
38
|
+
#{query_counter.inspect}
|
39
|
+
])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def expect_no_queries(&block)
|
44
|
+
expect_query(0, &block)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
class Address
|
2
|
+
include Mongoid::Document
|
3
|
+
|
4
|
+
field :_id, type: String, overwrite: true, default: ->{ street.try(:parameterize) }
|
5
|
+
|
6
|
+
attr_accessor :mode
|
7
|
+
|
8
|
+
field :address_type
|
9
|
+
field :number, type: Integer
|
10
|
+
field :no, type: Integer
|
11
|
+
field :h, as: :house, type: Integer
|
12
|
+
field :street
|
13
|
+
field :city
|
14
|
+
field :state
|
15
|
+
field :post_code
|
16
|
+
field :parent_title
|
17
|
+
field :services, type: Array
|
18
|
+
field :aliases, as: :a, type: Array
|
19
|
+
field :test, type: Array
|
20
|
+
field :latlng, type: Array
|
21
|
+
field :map, type: Hash
|
22
|
+
field :move_in, type: DateTime
|
23
|
+
field :end_date, type: Date
|
24
|
+
field :s, type: String, as: :suite
|
25
|
+
field :name, localize: true
|
26
|
+
|
27
|
+
belongs_to :band
|
28
|
+
|
29
|
+
embedded_in :addressable, polymorphic: true do
|
30
|
+
def extension
|
31
|
+
"Testing"
|
32
|
+
end
|
33
|
+
def doctor?
|
34
|
+
title == "Dr"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
scope :without_postcode, ->{ where(postcode: nil) }
|
39
|
+
scope :rodeo, ->{ where(street: "Rodeo Dr") } do
|
40
|
+
def mansion?
|
41
|
+
all? { |address| address.street == "Rodeo Dr" }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
validates_presence_of :street, on: :update
|
46
|
+
validates_format_of :street, with: /\D/, allow_nil: true
|
47
|
+
|
48
|
+
def set_parent=(set = false)
|
49
|
+
self.parent_title = addressable.title if set
|
50
|
+
end
|
51
|
+
|
52
|
+
def <=>(other)
|
53
|
+
street <=> other.street
|
54
|
+
end
|
55
|
+
|
56
|
+
class << self
|
57
|
+
def california
|
58
|
+
where(state: "CA")
|
59
|
+
end
|
60
|
+
|
61
|
+
def homes
|
62
|
+
where(address_type: "Home")
|
63
|
+
end
|
64
|
+
|
65
|
+
def streets
|
66
|
+
all.map(&:street)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class Band
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::Attributes::Dynamic
|
4
|
+
|
5
|
+
field :name, type: String
|
6
|
+
field :active, type: Mongoid::Boolean, default: true
|
7
|
+
field :origin, type: String
|
8
|
+
field :genres, type: Array
|
9
|
+
field :member_count, type: Integer
|
10
|
+
field :mems, as: :members, type: Array
|
11
|
+
field :likes, type: Integer
|
12
|
+
field :views, type: Integer
|
13
|
+
field :rating, type: Float
|
14
|
+
field :upserted, type: Mongoid::Boolean, default: false
|
15
|
+
field :created, type: DateTime
|
16
|
+
field :sales, type: BigDecimal
|
17
|
+
field :y, as: :years, type: Integer
|
18
|
+
field :founded, type: Date
|
19
|
+
|
20
|
+
|
21
|
+
has_many :albums, as: :owner
|
22
|
+
has_and_belongs_to_many :musicians
|
23
|
+
|
24
|
+
embeds_many :records, cascade_callbacks: true
|
25
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Game
|
2
|
+
include Mongoid::Document
|
3
|
+
|
4
|
+
field :high_score, type: Integer, default: 500
|
5
|
+
field :score, type: Integer, default: 0
|
6
|
+
field :name
|
7
|
+
|
8
|
+
belongs_to :person, index: true, validate: true
|
9
|
+
belongs_to :parent, class_name: "Game", foreign_key: "parent-id"
|
10
|
+
|
11
|
+
accepts_nested_attributes_for :person
|
12
|
+
|
13
|
+
validates_format_of :name, without: /\$\$\$/
|
14
|
+
|
15
|
+
set_callback(:initialize, :after) do |document|
|
16
|
+
write_attribute("name", "Testing") unless name
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
class Person
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::Attributes::Dynamic
|
4
|
+
attr_accessor :mode
|
5
|
+
|
6
|
+
class_attribute :somebody_elses_important_class_options
|
7
|
+
self.somebody_elses_important_class_options = { keep_me_around: true }
|
8
|
+
|
9
|
+
field :username, default: -> { "arthurnn#{rand(0..10)}" }
|
10
|
+
field :title
|
11
|
+
field :terms, type: Mongoid::Boolean
|
12
|
+
field :pets, type: Mongoid::Boolean, default: false
|
13
|
+
field :age, type: Integer, default: "100"
|
14
|
+
field :dob, type: Date
|
15
|
+
field :employer_id
|
16
|
+
field :lunch_time, type: Time
|
17
|
+
field :aliases, type: Array
|
18
|
+
field :map, type: Hash
|
19
|
+
field :map_with_default, type: Hash, default: {}
|
20
|
+
field :score, type: Integer
|
21
|
+
field :blood_alcohol_content, type: Float, default: ->{ 0.0 }
|
22
|
+
field :last_drink_taken_at, type: Date, default: ->{ 1.day.ago.in_time_zone("Alaska") }
|
23
|
+
field :ssn
|
24
|
+
field :owner_id, type: Integer
|
25
|
+
field :security_code
|
26
|
+
field :reading, type: Object
|
27
|
+
field :bson_id, type: BSON::ObjectId
|
28
|
+
field :pattern, type: Regexp
|
29
|
+
field :override_me, type: Integer
|
30
|
+
field :at, as: :aliased_timestamp, type: Time
|
31
|
+
field :t, as: :test, type: String
|
32
|
+
field :i, as: :inte, type: Integer
|
33
|
+
field :a, as: :array, type: Array
|
34
|
+
field :desc, localize: true
|
35
|
+
field :test_array, type: Array
|
36
|
+
field :overridden_setter, type: String
|
37
|
+
field :arrays, type: Array
|
38
|
+
field :range, type: Range
|
39
|
+
|
40
|
+
index age: 1
|
41
|
+
index addresses: 1
|
42
|
+
index dob: 1
|
43
|
+
index name: 1
|
44
|
+
index title: 1
|
45
|
+
|
46
|
+
index({ ssn: 1 }, { unique: true })
|
47
|
+
|
48
|
+
attr_reader :rescored
|
49
|
+
|
50
|
+
embeds_many :addresses, as: :addressable, validate: false do
|
51
|
+
def extension
|
52
|
+
"Testing"
|
53
|
+
end
|
54
|
+
def find_by_street(street)
|
55
|
+
where(street: street).first
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
has_one :game, dependent: :destroy, validate: false do
|
60
|
+
def extension
|
61
|
+
"Testing"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
has_many :posts, dependent: :delete, validate: false do
|
66
|
+
def extension
|
67
|
+
"Testing"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
has_and_belongs_to_many :preferences, index: true, dependent: :nullify, validate: false
|
72
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Post
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::Attributes::Dynamic
|
4
|
+
|
5
|
+
field :title, type: String
|
6
|
+
field :content, type: String
|
7
|
+
field :rating, type: Integer
|
8
|
+
field :person_title, type: String, default: ->{ person.title if ivar(:person) }
|
9
|
+
|
10
|
+
belongs_to :person, counter_cache: true
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Preference
|
2
|
+
include Mongoid::Document
|
3
|
+
|
4
|
+
field :name, type: String
|
5
|
+
field :value, type: String
|
6
|
+
field :ranking, type: Integer
|
7
|
+
|
8
|
+
has_and_belongs_to_many :people, validate: false
|
9
|
+
validates_length_of :name, minimum: 2, allow_nil: true
|
10
|
+
scope :posting, ->{ where(:value.in => [ "Posting" ]) }
|
11
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class Record
|
2
|
+
include Mongoid::Document
|
3
|
+
|
4
|
+
field :name, type: String
|
5
|
+
|
6
|
+
field :before_create_called, type: Mongoid::Boolean, default: false
|
7
|
+
field :before_save_called, type: Mongoid::Boolean, default: false
|
8
|
+
field :before_update_called, type: Mongoid::Boolean, default: false
|
9
|
+
field :before_validation_called, type: Mongoid::Boolean, default: false
|
10
|
+
field :before_destroy_called, type: Mongoid::Boolean, default: false
|
11
|
+
|
12
|
+
embedded_in :band
|
13
|
+
|
14
|
+
before_create :before_create_stub
|
15
|
+
before_save :before_save_stub
|
16
|
+
before_update :before_update_stub
|
17
|
+
before_validation :before_validation_stub
|
18
|
+
before_destroy :before_destroy_stub
|
19
|
+
|
20
|
+
after_destroy :access_band
|
21
|
+
|
22
|
+
def before_create_stub
|
23
|
+
self.before_create_called = true
|
24
|
+
end
|
25
|
+
|
26
|
+
def before_save_stub
|
27
|
+
self.before_save_called = true
|
28
|
+
end
|
29
|
+
|
30
|
+
def before_update_stub
|
31
|
+
self.before_update_called = true
|
32
|
+
end
|
33
|
+
|
34
|
+
def before_validation_stub
|
35
|
+
self.before_validation_called = true
|
36
|
+
end
|
37
|
+
|
38
|
+
def before_destroy_stub
|
39
|
+
self.before_destroy_called = true
|
40
|
+
end
|
41
|
+
|
42
|
+
def access_band
|
43
|
+
band.name
|
44
|
+
end
|
45
|
+
|
46
|
+
def dont_call_me_twice
|
47
|
+
end
|
48
|
+
|
49
|
+
validate { dont_call_me_twice }
|
50
|
+
end
|