mongoid 5.0.1 → 5.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CHANGELOG.md +2 -0
  5. data/README.md +0 -1
  6. data/lib/mongoid.rb +0 -7
  7. data/lib/mongoid/attributes.rb +2 -1
  8. data/lib/mongoid/attributes/nested.rb +3 -0
  9. data/lib/mongoid/clients.rb +0 -6
  10. data/lib/mongoid/clients/options.rb +0 -6
  11. data/lib/mongoid/clients/storage_options.rb +0 -3
  12. data/lib/mongoid/clients/thread_options.rb +0 -3
  13. data/lib/mongoid/config.rb +0 -7
  14. data/lib/mongoid/contextual/command.rb +0 -3
  15. data/lib/mongoid/contextual/mongo.rb +2 -2
  16. data/lib/mongoid/criteria.rb +6 -1
  17. data/lib/mongoid/extensions/hash.rb +1 -1
  18. data/lib/mongoid/indexable.rb +7 -5
  19. data/lib/mongoid/indexable/specification.rb +14 -0
  20. data/lib/mongoid/indexable/validators/options.rb +2 -1
  21. data/lib/mongoid/persistable/settable.rb +8 -1
  22. data/lib/mongoid/query_cache.rb +14 -4
  23. data/lib/mongoid/railtie.rb +1 -0
  24. data/lib/mongoid/relations/accessors.rb +3 -1
  25. data/lib/mongoid/relations/embedded/batchable.rb +5 -1
  26. data/lib/mongoid/relations/metadata.rb +3 -0
  27. data/lib/mongoid/tasks/database.rb +1 -1
  28. data/lib/mongoid/threaded.rb +0 -5
  29. data/lib/mongoid/version.rb +1 -1
  30. data/spec/app/models/bomb.rb +4 -0
  31. data/spec/app/models/building.rb +2 -1
  32. data/spec/app/models/building_address.rb +3 -1
  33. data/spec/app/models/courier_job.rb +4 -0
  34. data/spec/app/models/explosion.rb +4 -0
  35. data/spec/app/models/message.rb +3 -0
  36. data/spec/app/models/name.rb +1 -0
  37. data/spec/app/models/post.rb +3 -0
  38. data/spec/app/models/sandwich.rb +5 -0
  39. data/spec/app/models/shipment_address.rb +2 -0
  40. data/spec/mongoid/attributes/nested_spec.rb +77 -18
  41. data/spec/mongoid/attributes_spec.rb +13 -0
  42. data/spec/mongoid/criteria_spec.rb +52 -0
  43. data/spec/mongoid/document_spec.rb +37 -13
  44. data/spec/mongoid/indexable/specification_spec.rb +25 -0
  45. data/spec/mongoid/persistable_spec.rb +17 -0
  46. data/spec/mongoid/query_cache_spec.rb +51 -2
  47. data/spec/mongoid/relations/accessors_spec.rb +69 -0
  48. data/spec/mongoid/relations/embedded/many_spec.rb +63 -0
  49. data/spec/mongoid/relations/embedded/one_spec.rb +45 -0
  50. data/spec/mongoid/relations/metadata_spec.rb +16 -0
  51. data/spec/mongoid/relations/referenced/one_spec.rb +24 -0
  52. data/spec/mongoid/tasks/database_spec.rb +19 -0
  53. data/spec/spec_helper.rb +1 -8
  54. metadata +10 -2
  55. metadata.gz.sig +0 -0
@@ -47,7 +47,7 @@ module Mongoid
47
47
  # ignore default index
48
48
  unless index['name'] == '_id_'
49
49
  key = index['key'].symbolize_keys
50
- spec = model.index_specification(key)
50
+ spec = model.index_specification(key, index['name'])
51
51
  unless spec
52
52
  # index not specified
53
53
  undefined_by_model[model] ||= []
@@ -31,7 +31,6 @@ module Mongoid
31
31
  hash[key] = "[mongoid]:#{key}-stack"
32
32
  end
33
33
 
34
- extend Gem::Deprecate
35
34
  extend self
36
35
 
37
36
  # Begin entry into a named thread local stack.
@@ -175,8 +174,6 @@ module Mongoid
175
174
  def client_override
176
175
  Thread.current[CLIENT_OVERRIDE_KEY]
177
176
  end
178
- alias :session_override :client_override
179
- deprecate :session_override, :client_override, 2015, 12
180
177
 
181
178
  # Set the global client override.
182
179
  #
@@ -191,8 +188,6 @@ module Mongoid
191
188
  def client_override=(name)
192
189
  Thread.current[CLIENT_OVERRIDE_KEY] = name
193
190
  end
194
- alias :session_override= :client_override=
195
- deprecate :session_override=, :client_override=, 2015, 12
196
191
 
197
192
  # Get the current Mongoid scope.
198
193
  #
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid
3
- VERSION = "5.0.1"
3
+ VERSION = "5.0.2"
4
4
  end
@@ -0,0 +1,4 @@
1
+ class Bomb
2
+ include Mongoid::Document
3
+ has_one :explosion, dependent: :delete, autobuild: true
4
+ end
@@ -1,5 +1,6 @@
1
1
  class Building
2
2
  include Mongoid::Document
3
- embeds_one :building_address
3
+
4
+ embeds_one :building_address, validate: false
4
5
  embeds_many :contractors
5
6
  end
@@ -1,5 +1,7 @@
1
1
  class BuildingAddress
2
2
  include Mongoid::Document
3
- embedded_in :building
4
3
  field :city, type: String
4
+
5
+ embedded_in :building
6
+ validates_presence_of :city
5
7
  end
@@ -0,0 +1,4 @@
1
+ class CourierJob
2
+ include Mongoid::Document
3
+ embeds_one :drop_address, as: :addressable, autobuild: true, class_name: "ShipmentAddress"
4
+ end
@@ -0,0 +1,4 @@
1
+ class Explosion
2
+ include Mongoid::Document
3
+ belongs_to :bomb
4
+ end
@@ -2,7 +2,10 @@ class Message
2
2
  include Mongoid::Document
3
3
 
4
4
  field :body, type: String
5
+ field :priority, type: Integer
5
6
 
6
7
  embedded_in :person
7
8
  has_and_belongs_to_many :receviers, class_name: "Person", inverse_of: nil
9
+
10
+ has_one :post, as: :posteable
8
11
  end
@@ -14,6 +14,7 @@ class Name
14
14
  embeds_many :translations, validate: false
15
15
  embeds_one :language, as: :translatable, validate: false
16
16
  embedded_in :namable, polymorphic: true
17
+ embedded_in :person
17
18
 
18
19
  accepts_nested_attributes_for :language
19
20
 
@@ -15,6 +15,9 @@ class Post
15
15
  has_many :videos, validate: false
16
16
  has_many :roles, validate: false
17
17
 
18
+ belongs_to :posteable, polymorphic: true
19
+ accepts_nested_attributes_for :posteable, autosave: true
20
+
18
21
  scope :recent, ->{ where(created_at: { "$lt" => Time.now, "$gt" => 30.days.ago }) }
19
22
  scope :posting, ->{ where(:content.in => [ "Posting" ]) }
20
23
  scope :open, ->{ where(title: "open") }
@@ -1,4 +1,9 @@
1
1
  class Sandwich
2
2
  include Mongoid::Document
3
3
  has_and_belongs_to_many :meats
4
+
5
+ field :name, type: String
6
+
7
+ belongs_to :posteable, polymorphic: true
8
+ accepts_nested_attributes_for :posteable, autosave: true
4
9
  end
@@ -0,0 +1,2 @@
1
+ class ShipmentAddress < Address
2
+ end
@@ -102,6 +102,19 @@ describe Mongoid::Attributes::Nested do
102
102
  end
103
103
  end
104
104
 
105
+ context "when the association is referenced in and polymorphic" do
106
+
107
+ it "infers the class name of the polymorphic with the inverse type" do
108
+ expect {
109
+ Post.create!(
110
+ title: "Some title",
111
+ posteable_type: "Sandwich",
112
+ posteable_attributes: { name: 'Grilled Cheese' }
113
+ )
114
+ }.not_to raise_error
115
+ end
116
+ end
117
+
105
118
  context "when the relation is an embedded in" do
106
119
 
107
120
  before do
@@ -4788,38 +4801,84 @@ describe Mongoid::Attributes::Nested do
4788
4801
  league.divisions.create(name: "Old Name")
4789
4802
  end
4790
4803
 
4791
- let(:params) do
4792
- { divisions_attributes:
4793
- { "0" => { id: division.id.to_s, name: "New Name" }}
4794
- }
4795
- end
4804
+ context "when additional validation is set" do
4796
4805
 
4797
- before do
4798
- league.update_attributes(params)
4799
- end
4806
+ before do
4807
+ League.validates_presence_of(:divisions)
4808
+ end
4800
4809
 
4801
- it "sets the nested attributes" do
4802
- expect(league.reload.divisions.first.name).to eq("New Name")
4803
- end
4810
+ after do
4811
+ League.reset_callbacks(:validate)
4812
+ end
4804
4813
 
4805
- context "with corrupted data" do
4814
+ context "when validation fails" do
4806
4815
 
4807
- before do
4808
- league[:league] = params
4816
+ let(:division) do
4817
+ Division.new
4818
+ end
4819
+
4820
+ let(:league) do
4821
+ League.create!(divisions: [division])
4822
+ end
4823
+
4824
+ let(:error_raising_update) do
4825
+ league.update!(:divisions => nil)
4826
+ end
4827
+
4828
+ before do
4829
+ league.update(:divisions => nil)
4830
+ league.reload
4831
+ end
4832
+
4833
+ it "the update raises an error" do
4834
+ expect{ error_raising_update }.to raise_error
4835
+ end
4836
+
4837
+ it "the update does not occur" do
4838
+ expect(league.divisions.first).to eq(division)
4839
+ end
4840
+
4841
+ it "the document is inaccurately marked destroyed (you fixed the bug if you broke this!)" do
4842
+ expect(division).to be_destroyed
4843
+ end
4809
4844
  end
4845
+ end
4810
4846
 
4811
- let(:new_params) do
4847
+ context "when no additional validation is set" do
4848
+
4849
+ let(:params) do
4812
4850
  { divisions_attributes:
4813
- { "0" => { id: division.id.to_s, name: "Name" }}
4851
+ { "0" => { id: division.id.to_s, name: "New Name" }}
4814
4852
  }
4815
4853
  end
4816
4854
 
4817
4855
  before do
4818
- league.update_attributes(new_params)
4856
+ league.update_attributes(params)
4819
4857
  end
4820
4858
 
4821
4859
  it "sets the nested attributes" do
4822
- expect(league.reload.divisions.first.name).to eq("Name")
4860
+ expect(league.reload.divisions.first.name).to eq("New Name")
4861
+ end
4862
+
4863
+ context "with corrupted data" do
4864
+
4865
+ before do
4866
+ league[:league] = params
4867
+ end
4868
+
4869
+ let(:new_params) do
4870
+ { divisions_attributes:
4871
+ { "0" => { id: division.id.to_s, name: "Name" }}
4872
+ }
4873
+ end
4874
+
4875
+ before do
4876
+ league.update_attributes(new_params)
4877
+ end
4878
+
4879
+ it "sets the nested attributes" do
4880
+ expect(league.reload.divisions.first.name).to eq("Name")
4881
+ end
4823
4882
  end
4824
4883
  end
4825
4884
  end
@@ -1207,6 +1207,19 @@ describe Mongoid::Attributes do
1207
1207
  }.to raise_error(Mongoid::Errors::InvalidValue)
1208
1208
  end
1209
1209
  end
1210
+
1211
+ context "when attribute is localized and #attributes is a BSON::Document" do
1212
+ let(:dictionary) { Dictionary.new }
1213
+
1214
+ before do
1215
+ allow(dictionary).to receive(:attributes).and_return(BSON::Document.new)
1216
+ end
1217
+
1218
+ it "sets the value for the current locale" do
1219
+ dictionary.write_attribute(:description, 'foo')
1220
+ expect(dictionary.description).to eq('foo')
1221
+ end
1222
+ end
1210
1223
  end
1211
1224
 
1212
1225
  describe "#typed_value_for" do
@@ -3254,6 +3254,25 @@ describe Mongoid::Criteria do
3254
3254
  expect(criteria.selector).to eq({ "agent_ids" => [ id_one, id_two ]})
3255
3255
  end
3256
3256
  end
3257
+
3258
+ context "when querying on a big decimal" do
3259
+
3260
+ let(:sales) do
3261
+ BigDecimal.new('0.1')
3262
+ end
3263
+
3264
+ let!(:band) do
3265
+ Band.create(name: "Boards of Canada", sales: sales)
3266
+ end
3267
+
3268
+ let(:from_db) do
3269
+ Band.where(sales: sales).first
3270
+ end
3271
+
3272
+ it "finds the document by the big decimal value" do
3273
+ expect(from_db).to eq(band)
3274
+ end
3275
+ end
3257
3276
  end
3258
3277
  end
3259
3278
 
@@ -3468,4 +3487,37 @@ describe Mongoid::Criteria do
3468
3487
  end
3469
3488
  end
3470
3489
  end
3490
+
3491
+ describe "#type_selection" do
3492
+
3493
+ context "when only one subclass exists" do
3494
+
3495
+ let(:criteria) do
3496
+ described_class.new(Firefox)
3497
+ end
3498
+
3499
+ let(:selection) do
3500
+ criteria.send(:type_selection)
3501
+ end
3502
+
3503
+ it "does not use an $in query" do
3504
+ expect(selection).to eq({ _type: "Firefox" })
3505
+ end
3506
+ end
3507
+
3508
+ context "when more than one subclass exists" do
3509
+
3510
+ let(:criteria) do
3511
+ described_class.new(Browser)
3512
+ end
3513
+
3514
+ let(:selection) do
3515
+ criteria.send(:type_selection)
3516
+ end
3517
+
3518
+ it "does not use an $in query" do
3519
+ expect(selection).to eq({ _type: { "$in" => [ "Firefox", "Browser" ]}})
3520
+ end
3521
+ end
3522
+ end
3471
3523
  end
@@ -613,25 +613,49 @@ describe Mongoid::Document do
613
613
  Person.new
614
614
  end
615
615
 
616
- context "when not frozen" do
616
+ context "when freezing the model" do
617
617
 
618
- it "freezes attributes" do
619
- expect(person.freeze).to eq(person)
620
- expect { person.title = "something" }.to raise_error
618
+ context "when not frozen" do
619
+
620
+ it "freezes attributes" do
621
+ expect(person.freeze).to eq(person)
622
+ expect { person.title = "something" }.to raise_error
623
+ end
621
624
  end
622
- end
623
625
 
624
- context "when frozen" do
626
+ context "when frozen" do
625
627
 
626
- before do
627
- person.raw_attributes.freeze
628
+ before do
629
+ person.raw_attributes.freeze
630
+ end
631
+
632
+ it "keeps things frozen" do
633
+ person.freeze
634
+ expect {
635
+ person.title = "something"
636
+ }.to raise_error
637
+ end
628
638
  end
639
+ end
629
640
 
630
- it "keeps things frozen" do
631
- person.freeze
632
- expect {
633
- person.title = "something"
634
- }.to raise_error
641
+ context "when freezing attributes of the model" do
642
+
643
+ context "when assigning a frozen value" do
644
+
645
+ context "when the frozen value is a hash" do
646
+
647
+ let(:hash) do
648
+ {"foo" => {"bar" => {"baz" => [1,2,3]}}}
649
+ end
650
+
651
+ let(:assign_hash) do
652
+ person.map = hash.freeze
653
+ end
654
+
655
+ it "no mutation occurs during assignment" do
656
+ expect{ assign_hash }.not_to raise_error
657
+ end
658
+ end
635
659
  end
636
660
  end
637
661
  end
@@ -99,4 +99,29 @@ describe Mongoid::Indexable::Specification do
99
99
  expect(spec.options).to eq(background: true, drop_dups: true)
100
100
  end
101
101
  end
102
+
103
+ describe '#name' do
104
+
105
+ context 'when there is only one field' do
106
+
107
+ let(:spec) do
108
+ described_class.new(Band, { name: 1 })
109
+ end
110
+
111
+ it 'returns the key and direction separated by an underscore' do
112
+ expect(spec.name).to eq('name_1')
113
+ end
114
+ end
115
+
116
+ context 'when there are two fields' do
117
+
118
+ let(:spec) do
119
+ described_class.new(Band, { name: 1, title: -1 })
120
+ end
121
+
122
+ it 'returns the keys and directions separated by underscores' do
123
+ expect(spec.name).to eq('name_1_title_-1')
124
+ end
125
+ end
126
+ end
102
127
  end
@@ -203,4 +203,21 @@ describe Mongoid::Persistable do
203
203
  }.to raise_error(Mongoid::Errors::Callback)
204
204
  end
205
205
  end
206
+
207
+ example "able use set value using dot notation" do
208
+ class Customer
209
+ include Mongoid::Document
210
+
211
+ field :address, type: Hash, default: -> {{}}
212
+ end
213
+
214
+ customer = Customer.new
215
+ customer.save
216
+ customer.set 'address.country' => 'India'
217
+ expect(customer.address).to eql({ 'country' => 'India' })
218
+ customer.set 'address.country.state' => 'MH'
219
+ expect(customer.address).to eql({'country' => { 'state' => 'MH' }})
220
+ customer.set 'address' => { 'country' => 'India'}
221
+ expect(customer.address).to eql({ 'country' => 'India' })
222
+ end
206
223
  end