mongoid 7.0.4 → 7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 97ae228df96e11fe59977a8d1af1bb0e86597fe5ee31d8cbe257a077d6e87d4f
4
- data.tar.gz: b8face8e682359ca47c26c0dc168ab1a99762769176fd2f8796ae472a341cd76
3
+ metadata.gz: 1d4a5f733ce016f190a456b5801a1e3a1efbe89a30d99a20cd4c73e5696e7004
4
+ data.tar.gz: a40c8e747c7eeff97d8259bd6b11d35bf25de5434674c24f1c5ebe71ed5d6f3e
5
5
  SHA512:
6
- metadata.gz: 1aafc53e49a0576a7bfb081bca208629ba7323c1a52468e0279644b0b9c2a9d4015c63d35cdf1f16b0967056ed976d015638fab512bce7a221acfeda75c867ed
7
- data.tar.gz: 0c3e7557c424ccd5a95d3e5c4249e4a45a31f74577be2ba7cfac70d67d3226cd00b0b655e7f9d576086a0fc18c7b9d7bf37c57e8a06fb07131a3bec99e85fe8a
6
+ metadata.gz: 121ace21edf0fec13546294a101b4bb383eed7d7b7ead0d6bd3624ccfad5601a70a9e4b0363e710e687ba237835ea4a61da8d17ebab00a2537751a7fcbf5410f
7
+ data.tar.gz: d39854dd3981a7c517e6ba00c0d85feb1e9bb6e928dabf233f603bf35f8299706c0981ed3cb9ba3c121e2af58ae42bc0e0e876a3a45f0264ac344d48469e9401
Binary file
data.tar.gz.sig CHANGED
Binary file
data/Rakefile CHANGED
@@ -33,3 +33,15 @@ RSpec::Core::RakeTask.new('spec:progress') do |spec|
33
33
  end
34
34
 
35
35
  task :default => :spec
36
+
37
+ desc "Generate all documentation"
38
+ task :docs => 'docs:yard'
39
+
40
+ namespace :docs do
41
+ desc "Generate yard documention"
42
+ task :yard do
43
+ out = File.join('yard-docs', Mongoid::VERSION)
44
+ FileUtils.rm_rf(out)
45
+ system "yardoc -o #{out} --title mongoid-#{Mongoid::VERSION}"
46
+ end
47
+ end
@@ -20,7 +20,7 @@ module Mongoid
20
20
  #
21
21
  # @since 2.1.0
22
22
  def path
23
- @path ||= position.sub(/\.\d+$/, "")
23
+ @path ||= position.sub(/\.\d+\z/, "")
24
24
  end
25
25
  end
26
26
  end
@@ -3,6 +3,10 @@ module Mongoid
3
3
  class Criteria
4
4
  module Modifiable
5
5
 
6
+ # @attribute [r] create_attrs Additional attributes to add to the Document upon creation.
7
+ # @api private
8
+ attr_reader :create_attrs
9
+
6
10
  # Build a document given the selector and return it.
7
11
  # Complex criteria, such as $in and $or operations will get ignored.
8
12
  #
@@ -57,6 +61,9 @@ module Mongoid
57
61
 
58
62
  # Define attributes with which new documents will be created.
59
63
  #
64
+ # Note that if `find_or_create_by` is called after this in a method chain, the attributes in
65
+ # the query will override those from this method.
66
+ #
60
67
  # @example Define attributes to be used when a new document is created.
61
68
  # Person.create_with(job: 'Engineer').find_or_create_by(employer: 'MongoDB')
62
69
  #
@@ -64,7 +71,9 @@ module Mongoid
64
71
  #
65
72
  # @since 5.1.0
66
73
  def create_with(attrs = {})
67
- where(selector.merge(attrs))
74
+ tap do
75
+ (@create_attrs ||= {}).merge!(attrs)
76
+ end
68
77
  end
69
78
 
70
79
  # Find the first +Document+ given the conditions, or creates a new document
@@ -172,7 +181,8 @@ module Mongoid
172
181
  #
173
182
  # @since 3.0.0
174
183
  def create_document(method, attrs = nil, &block)
175
- attributes = selector.reduce(attrs ? attrs.dup : {}) do |hash, (key, value)|
184
+ attrs = (create_attrs || {}).merge(attrs || {})
185
+ attributes = selector.reduce(attrs) do |hash, (key, value)|
176
186
  unless invalid_key?(hash, key) || invalid_embedded_doc?(value)
177
187
  hash[key] = value
178
188
  end
@@ -3,16 +3,75 @@ module Mongoid
3
3
  class Criteria
4
4
  module Queryable
5
5
 
6
- # The key is a representation of a field in a queryable, that can be
7
- # expanded to special MongoDB selectors.
6
+ # Key objects represent specifications for building query expressions
7
+ # utilizing MongoDB selectors.
8
+ #
9
+ # Simple key-value conditions are translated directly into expression
10
+ # hashes by Mongoid without utilizing Key objects. For example, the
11
+ # following condition:
12
+ #
13
+ # Foo.where(price: 1)
14
+ #
15
+ # ... is translated to the following simple expression:
16
+ #
17
+ # {price: 1}
18
+ #
19
+ # More complex conditions would start involving Key objects. For example:
20
+ #
21
+ # Foo.where(:price.gt => 1)
22
+ #
23
+ # ... causes a Key instance to be created thusly:
24
+ #
25
+ # Key.new(:price, :__override__, '$gt')
26
+ #
27
+ # This Key instance utilizes +operator+ but not +expanded+ nor +block+.
28
+ # The corresponding MongoDB query expression is:
29
+ #
30
+ # {price: {'$gt' => 1}}
31
+ #
32
+ # A yet more more complex example is the following condition:
33
+ #
34
+ # Foo.geo_spacial(:boundary.intersects_point => [1, 10])
35
+ #
36
+ # Processing this condition will cause a Key instance to be created as
37
+ # follows:
38
+ #
39
+ # Key.new(:location, :__override__, '$geoIntersects', '$geometry') do |value|
40
+ # { "type" => POINT, "coordinates" => value }
41
+ # end
42
+ #
43
+ # ... eventually producing the following MongoDB query expression:
44
+ #
45
+ # {
46
+ # boundary: {
47
+ # '$geoIntersects' => {
48
+ # '$geometry' => {
49
+ # type: "Point" ,
50
+ # coordinates: [ 1, 10 ]
51
+ # }
52
+ # }
53
+ # }
54
+ # }
55
+ #
56
+ # Key instances can be thought of as procs that map a value to the
57
+ # MongoDB query expression required to obtain the key's condition,
58
+ # given the value.
8
59
  class Key
9
60
 
10
- # @attribute [r] name The name of the field.
11
- # @attribute [r] block The optional block to transform values.
12
- # @attribute [r] operator The MongoDB query operator.
13
- # @attribute [r] expanded The MongoDB expanded query operator.
14
- # @attribute [r] strategy The name of the merge strategy.
15
- attr_reader :block, :name, :operator, :expanded, :strategy
61
+ # @return [ String | Symbol ] The name of the field.
62
+ attr_reader :name
63
+
64
+ # @return [ String ] The MongoDB query operator.
65
+ attr_reader :operator
66
+
67
+ # @return [ String ] The MongoDB expanded query operator.
68
+ attr_reader :expanded
69
+
70
+ # @return [ Symbol ] The name of the merge strategy.
71
+ attr_reader :strategy
72
+
73
+ # @return [ Proc ] The optional block to transform values.
74
+ attr_reader :block
16
75
 
17
76
  # Does the key equal another object?
18
77
  #
@@ -24,7 +24,7 @@ module Mongoid
24
24
  # @since 2.0.0
25
25
  POLYGON = "Polygon"
26
26
 
27
- # @attribute [rw] negating If the next spression is negated.
27
+ # @attribute [rw] negating If the next expression is negated.
28
28
  # @attribute [rw] selector The query selector.
29
29
  attr_accessor :negating, :selector
30
30
 
@@ -21,9 +21,10 @@ module Mongoid
21
21
  other.each_pair do |key, value|
22
22
  if value.is_a?(Hash) && self[key.to_s].is_a?(Hash)
23
23
  value = self[key.to_s].merge(value) do |_key, old_val, new_val|
24
- if in?(_key)
24
+ case _key
25
+ when '$in'
25
26
  new_val & old_val
26
- elsif nin?(_key)
27
+ when '$nin'
27
28
  (old_val + new_val).uniq
28
29
  else
29
30
  new_val
@@ -52,10 +53,13 @@ module Mongoid
52
53
  def store(key, value)
53
54
  name, serializer = storage_pair(key)
54
55
  if multi_selection?(name)
55
- super(name, evolve_multi(value))
56
+ store_name = name
57
+ store_value = evolve_multi(value)
56
58
  else
57
- super(localized_key(name, serializer), evolve(serializer, value))
59
+ store_name = localized_key(name, serializer)
60
+ store_value = evolve(serializer, value)
58
61
  end
62
+ super(store_name, store_value)
59
63
  end
60
64
  alias :[]= :store
61
65
 
@@ -178,33 +182,7 @@ module Mongoid
178
182
  #
179
183
  # @since 1.0.0
180
184
  def multi_selection?(key)
181
- key =~ /\$and|\$or|\$nor/
182
- end
183
-
184
- # Determines if the selection operator takes a list. Returns true for $in and $nin.
185
- #
186
- # @api private
187
- #
188
- # @example Does the selection operator take multiple values?
189
- # selector.multi_value?("$nin")
190
- #
191
- # @param [ String ] key The key to check.
192
- #
193
- # @return [ true, false ] If the key is $in or $nin.
194
- #
195
- # @since 2.1.1
196
- def multi_value?(key)
197
- key =~ /\$nin|\$in/
198
- end
199
-
200
- private
201
-
202
- def in?(key)
203
- key =~ /\$in/
204
- end
205
-
206
- def nin?(key)
207
- key =~ /\$nin/
185
+ %w($and $or $nor).include?(key)
208
186
  end
209
187
  end
210
188
  end
@@ -69,7 +69,7 @@ module Mongoid
69
69
  #
70
70
  # @since 2.3.1
71
71
  def mongoid_id?
72
- self =~ /\A(|_)id$/
72
+ self =~ /\A(|_)id\z/
73
73
  end
74
74
 
75
75
  # Is the string a number? The literals "NaN", "Infinity", and "-Infinity"
@@ -96,7 +96,7 @@ module Mongoid
96
96
  #
97
97
  # @since 1.0.0
98
98
  def reader
99
- delete("=").sub(/\_before\_type\_cast$/, '')
99
+ delete("=").sub(/\_before\_type\_cast\z/, '')
100
100
  end
101
101
 
102
102
  # Is this string a writer?
@@ -64,7 +64,7 @@ module Mongoid
64
64
  matches = position.scan(/\.\d+\./)
65
65
  if matches.size == 1
66
66
  keys.each do |kk|
67
- if position =~ /^#{kk}\.\d+\.(.*)/
67
+ if position =~ /\A#{kk}\.\d+\.(.*)\z/
68
68
  return "#{kk}.$.#{$1}"
69
69
  end
70
70
  end
@@ -258,7 +258,7 @@ module Mongoid
258
258
  end
259
259
 
260
260
  def system_collection?
261
- collection.namespace =~ /^system./
261
+ collection.namespace =~ /\Asystem./
262
262
  end
263
263
  end
264
264
 
@@ -48,7 +48,7 @@ module Mongoid
48
48
  # include Mongoid::Document
49
49
  # field :title
50
50
  #
51
- # validates_format_of :title, with: /^[a-z0-9 \-_]*$/i
51
+ # validates_format_of :title, with: /\A[a-z0-9 \-_]*\z/i
52
52
  # end
53
53
  #
54
54
  # @param [ Array ] args The names of the fields to validate.
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid
3
- VERSION = "7.0.4"
3
+ VERSION = "7.0.5"
4
4
  end
@@ -0,0 +1,18 @@
1
+ # Running Mongoid Tests
2
+
3
+ ## Overview
4
+ ### Quick Start
5
+ Spin up a MongoDB deployment against which to run the Mongoid specs. Mongoid specs support a variety of MongoDB topologies, but the simplest is a single MongoDB instance:
6
+
7
+ # Launch mongod in one terminal
8
+ mkdir /tmp/mdb
9
+ mongod --dbpath /tmp/mdb
10
+
11
+ Run the test suite in a separate terminal:
12
+
13
+ rake
14
+
15
+
16
+ ## Caveats
17
+ ### "Too many open files" error
18
+ On MacOS, you may encounter a "Too many open files" error on the MongoDB server when running the tests. If this happens, stop the server, run the command `ulimit -n 10000` in the same terminal session as the server, and restart the server. This will increase the number of files that can be opened. Then, re-run the tests.
@@ -132,8 +132,8 @@ describe Mongoid::Clients::Factory do
132
132
 
133
133
  let(:config) do
134
134
  {
135
- default: { hosts: [ "127.0.0.1:1234" ], database: database_id },
136
- secondary: { uri: "mongodb://127.0.0.1:1234,127.0.0.1:5678/mongoid_test" }
135
+ default: { hosts: [ "127.0.0.1:1234" ], database: database_id, server_selection_timeout: 1 },
136
+ secondary: { uri: "mongodb://127.0.0.1:1234,127.0.0.1:5678/mongoid_test?serverSelectionTimeoutMS=1000" }
137
137
  }
138
138
  end
139
139
 
@@ -16,17 +16,26 @@ describe Mongoid::Clients::Sessions do
16
16
  end
17
17
 
18
18
  let(:subscriber) do
19
- Mongoid::Clients.with_name(:other).send(:monitoring).subscribers['Command'].find do |s|
19
+ client = Mongoid::Clients.with_name(:other)
20
+ monitoring = if client.respond_to?(:monitoring, true)
21
+ client.send(:monitoring)
22
+ else
23
+ # driver 2.5
24
+ client.instance_variable_get('@monitoring')
25
+ end
26
+ monitoring.subscribers['Command'].find do |s|
20
27
  s.is_a?(EventSubscriber)
21
28
  end
22
29
  end
23
30
 
24
31
  let(:insert_events) do
25
- subscriber.started_events.select { |event| event.command_name == 'insert' }
32
+ # Driver 2.5 sends command_name as a symbol
33
+ subscriber.started_events.select { |event| event.command_name.to_s == 'insert' }
26
34
  end
27
35
 
28
36
  let(:update_events) do
29
- subscriber.started_events.select { |event| event.command_name == 'update' }
37
+ # Driver 2.5 sends command_name as a symbol
38
+ subscriber.started_events.select { |event| event.command_name.to_s == 'update' }
30
39
  end
31
40
 
32
41
  context 'when a session is used on a model class' do
@@ -1,18 +1,27 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe Mongoid::Clients::Sessions do
4
+ before(:all) do
5
+ unless Mongo::VERSION >= '2.6'
6
+ skip 'Driver does not support transactions'
7
+ end
8
+ end
4
9
 
5
10
  before(:all) do
6
- CONFIG[:clients][:other] = CONFIG[:clients][:default].dup
7
- CONFIG[:clients][:other][:database] = 'other'
8
- Mongoid::Clients.clients.values.each(&:close)
9
- Mongoid::Config.send(:clients=, CONFIG[:clients])
10
- Mongoid::Clients.with_name(:other).subscribe(Mongo::Monitoring::COMMAND, EventSubscriber.new)
11
+ if Mongo::VERSION >= '2.6'
12
+ CONFIG[:clients][:other] = CONFIG[:clients][:default].dup
13
+ CONFIG[:clients][:other][:database] = 'other'
14
+ Mongoid::Clients.clients.values.each(&:close)
15
+ Mongoid::Config.send(:clients=, CONFIG[:clients])
16
+ Mongoid::Clients.with_name(:other).subscribe(Mongo::Monitoring::COMMAND, EventSubscriber.new)
17
+ end
11
18
  end
12
19
 
13
20
  after(:all) do
14
- Mongoid::Clients.with_name(:other).close
15
- Mongoid::Clients.clients.delete(:other)
21
+ if Mongo::VERSION >= '2.6'
22
+ Mongoid::Clients.with_name(:other).close
23
+ Mongoid::Clients.clients.delete(:other)
24
+ end
16
25
  end
17
26
 
18
27
  let(:subscriber) do
@@ -1,6 +1,7 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe Mongoid::Contextual::GeoNear do
4
+ max_server_version '4.0'
4
5
 
5
6
  describe "#average_distance" do
6
7
 
@@ -1643,11 +1643,15 @@ describe Mongoid::Criteria::Modifiable do
1643
1643
  { 'username' => 'Turnip' }
1644
1644
  end
1645
1645
 
1646
- it 'returns a criteria with the defined attributes' do
1647
- expect(Person.create_with(attrs).selector).to eq(attrs)
1646
+ it 'does not modify the selector' do
1647
+ expect(Person.create_with(attrs).selector[:username]).to be_nil
1648
1648
  end
1649
1649
 
1650
- context 'when a method is chained' do
1650
+ it 'create_attrs is modified' do
1651
+ expect(Person.create_with(attrs).create_attrs).to eq(attrs)
1652
+ end
1653
+
1654
+ context 'when a create is chained' do
1651
1655
 
1652
1656
  context 'when a write method is chained' do
1653
1657
 
@@ -1671,6 +1675,25 @@ describe Mongoid::Criteria::Modifiable do
1671
1675
  expect(new_person.age).to eq(50)
1672
1676
  end
1673
1677
 
1678
+ context 'when a matching document is already in the collection' do
1679
+ let(:query) do
1680
+ { 'username' => 'foo', 'age' => 12 }
1681
+ end
1682
+
1683
+ let(:person) do
1684
+ Person.create!(query)
1685
+ end
1686
+
1687
+ let(:found_person) do
1688
+ Person.create_with(attrs).find_or_create_by(query)
1689
+ end
1690
+
1691
+ it 'finds the matching document' do
1692
+ person
1693
+ expect(found_person.id).to eq(person.id)
1694
+ end
1695
+ end
1696
+
1674
1697
  context 'when the attributes are shared with the write method args' do
1675
1698
 
1676
1699
  let(:query) do
@@ -1681,7 +1704,7 @@ describe Mongoid::Criteria::Modifiable do
1681
1704
  Person.create_with(attrs).find_or_create_by(query)
1682
1705
  end
1683
1706
 
1684
- it 'gives the write method args precedence' do
1707
+ it 'gives the find method args precedence' do
1685
1708
  expect(new_person.username).to eq('Beet')
1686
1709
  expect(new_person.age).to eq(50)
1687
1710
  end
@@ -1708,8 +1731,12 @@ describe Mongoid::Criteria::Modifiable do
1708
1731
  { 'username' => 'Beet', 'age' => 50 }
1709
1732
  end
1710
1733
 
1734
+ it 'does not modify the selector' do
1735
+ expect(criteria.create_with(attrs).selector).to eq(criteria_selector)
1736
+ end
1737
+
1711
1738
  it 'overwrites all the original attributes' do
1712
- expect(criteria.create_with(attrs).selector).to eq(attrs)
1739
+ expect(criteria.create_with(attrs).create_attrs).to eq(attrs)
1713
1740
  end
1714
1741
  end
1715
1742
  end
@@ -1720,8 +1747,12 @@ describe Mongoid::Criteria::Modifiable do
1720
1747
  { 'username' => 'Beet' }
1721
1748
  end
1722
1749
 
1750
+ it 'does not modify the selector' do
1751
+ expect(criteria.create_with(attrs).selector).to eq(criteria_selector)
1752
+ end
1753
+
1723
1754
  it 'only overwrites the shared attributes' do
1724
- expect(criteria.create_with(attrs).selector).to eq(criteria_selector.merge!(attrs))
1755
+ expect(criteria.create_with(attrs).create_attrs).to eq(attrs)
1725
1756
  end
1726
1757
  end
1727
1758
 
@@ -1730,12 +1761,11 @@ describe Mongoid::Criteria::Modifiable do
1730
1761
  let(:attrs) do
1731
1762
  { 'username' => 'Turnip' }
1732
1763
  end
1733
-
1734
1764
  let(:query) do
1735
1765
  { 'username' => 'Beet', 'age' => 50 }
1736
1766
  end
1737
1767
 
1738
- context 'when a write method is chained' do
1768
+ context 'when a create method is chained' do
1739
1769
 
1740
1770
  it 'executes the method' do
1741
1771
  expect(criteria.create_with(attrs).new.username).to eq('Turnip')
@@ -1749,9 +1779,28 @@ describe Mongoid::Criteria::Modifiable do
1749
1779
  criteria.create_with(attrs).find_or_create_by(query)
1750
1780
  end
1751
1781
 
1752
- it 'executes the query' do
1782
+ it 'gives the find method arg precedence' do
1753
1783
  expect(new_person.username).to eq('Beet')
1754
- expect(new_person.age).to eq(50)
1784
+ expect(new_person.age).to be(50)
1785
+ end
1786
+
1787
+ context 'when a matching document is already in the collection' do
1788
+ let(:query) do
1789
+ { 'username' => 'foo', 'age' => 12 }
1790
+ end
1791
+
1792
+ let(:person) do
1793
+ Person.create!(query)
1794
+ end
1795
+
1796
+ let(:found_person) do
1797
+ criteria.create_with(attrs).find_or_create_by(query)
1798
+ end
1799
+
1800
+ it 'finds the matching document' do
1801
+ person
1802
+ expect(found_person.id).to eq(person.id)
1803
+ end
1755
1804
  end
1756
1805
  end
1757
1806
  end