mongo 2.1.0.rc0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +5 -2
  3. data.tar.gz.sig +0 -0
  4. data/Rakefile +2 -2
  5. data/lib/mongo.rb +2 -1
  6. data/lib/mongo/address.rb +11 -5
  7. data/lib/mongo/address/ipv4.rb +6 -1
  8. data/lib/mongo/auth/cr/conversation.rb +1 -1
  9. data/lib/mongo/auth/ldap/conversation.rb +1 -1
  10. data/lib/mongo/auth/scram/conversation.rb +1 -1
  11. data/lib/mongo/auth/user/view.rb +2 -2
  12. data/lib/mongo/auth/x509/conversation.rb +1 -1
  13. data/lib/mongo/bulk_write.rb +12 -9
  14. data/lib/mongo/bulk_write/transformable.rb +20 -5
  15. data/lib/mongo/client.rb +11 -11
  16. data/lib/mongo/cluster.rb +2 -2
  17. data/lib/mongo/collection.rb +21 -8
  18. data/lib/mongo/collection/view.rb +1 -0
  19. data/lib/mongo/collection/view/aggregation.rb +11 -5
  20. data/lib/mongo/collection/view/iterable.rb +6 -2
  21. data/lib/mongo/collection/view/map_reduce.rb +39 -5
  22. data/lib/mongo/collection/view/readable.rb +35 -30
  23. data/lib/mongo/collection/view/writable.rb +26 -18
  24. data/lib/mongo/database.rb +12 -2
  25. data/lib/mongo/database/view.rb +4 -3
  26. data/lib/mongo/dbref.rb +4 -4
  27. data/lib/mongo/grid/fs_bucket.rb +8 -1
  28. data/lib/mongo/grid/stream/read.rb +1 -1
  29. data/lib/mongo/index.rb +5 -0
  30. data/lib/mongo/index/view.rb +2 -2
  31. data/lib/mongo/monitoring/command_log_subscriber.rb +9 -3
  32. data/lib/mongo/monitoring/event.rb +1 -0
  33. data/lib/mongo/monitoring/event/command_started.rb +2 -1
  34. data/lib/mongo/monitoring/event/command_succeeded.rb +6 -3
  35. data/lib/mongo/monitoring/event/secure.rb +58 -0
  36. data/lib/mongo/operation.rb +31 -1
  37. data/lib/mongo/operation/commands/collections_info.rb +2 -0
  38. data/lib/mongo/operation/commands/collections_info/result.rb +39 -0
  39. data/lib/mongo/operation/commands/list_indexes/result.rb +2 -1
  40. data/lib/mongo/operation/commands/map_reduce/result.rb +1 -1
  41. data/lib/mongo/operation/read/query.rb +2 -0
  42. data/lib/mongo/operation/read/query/result.rb +40 -0
  43. data/lib/mongo/operation/result.rb +13 -1
  44. data/lib/mongo/operation/write/bulk/delete.rb +2 -2
  45. data/lib/mongo/operation/write/bulk/update.rb +3 -3
  46. data/lib/mongo/operation/write/delete.rb +2 -2
  47. data/lib/mongo/operation/write/update.rb +9 -4
  48. data/lib/mongo/options.rb +1 -0
  49. data/lib/mongo/options/redacted.rb +156 -0
  50. data/lib/mongo/protocol/insert.rb +25 -6
  51. data/lib/mongo/protocol/query.rb +45 -31
  52. data/lib/mongo/protocol/reply.rb +29 -6
  53. data/lib/mongo/protocol/serializers.rb +1 -1
  54. data/lib/mongo/retryable.rb +83 -0
  55. data/lib/mongo/server.rb +16 -3
  56. data/lib/mongo/server/connectable.rb +21 -3
  57. data/lib/mongo/server/connection.rb +38 -4
  58. data/lib/mongo/server/connection_pool.rb +12 -0
  59. data/lib/mongo/server/connection_pool/queue.rb +15 -0
  60. data/lib/mongo/server/monitor/connection.rb +2 -2
  61. data/lib/mongo/server_selector.rb +5 -0
  62. data/lib/mongo/server_selector/selectable.rb +16 -9
  63. data/lib/mongo/socket.rb +6 -2
  64. data/lib/mongo/uri.rb +1 -1
  65. data/lib/mongo/version.rb +1 -1
  66. data/spec/mongo/bulk_write/ordered_combiner_spec.rb +11 -11
  67. data/spec/mongo/bulk_write/unordered_combiner_spec.rb +10 -10
  68. data/spec/mongo/client_spec.rb +101 -18
  69. data/spec/mongo/collection_spec.rb +44 -0
  70. data/spec/mongo/connection_string_spec.rb +36 -58
  71. data/spec/mongo/database_spec.rb +20 -0
  72. data/spec/mongo/grid/fs_bucket_spec.rb +1 -1
  73. data/spec/mongo/grid/stream/write_spec.rb +2 -2
  74. data/spec/mongo/monitoring/event/command_started_spec.rb +26 -0
  75. data/spec/mongo/monitoring/event/command_succeeded_spec.rb +26 -0
  76. data/spec/mongo/monitoring/event/secure_spec.rb +57 -0
  77. data/spec/mongo/operation/commands/aggregate_spec.rb +0 -16
  78. data/spec/mongo/operation/commands/command_spec.rb +0 -18
  79. data/spec/mongo/operation/kill_cursors_spec.rb +0 -16
  80. data/spec/mongo/operation/read/get_more_spec.rb +0 -16
  81. data/spec/mongo/operation/read/query_spec.rb +19 -16
  82. data/spec/mongo/operation/write/bulk/delete_spec.rb +16 -16
  83. data/spec/mongo/operation/write/bulk/update_spec.rb +6 -6
  84. data/spec/mongo/operation/write/command/delete_spec.rb +0 -16
  85. data/spec/mongo/operation/write/command/insert_spec.rb +0 -16
  86. data/spec/mongo/operation/write/command/update_spec.rb +0 -16
  87. data/spec/mongo/operation/write/delete_spec.rb +3 -3
  88. data/spec/mongo/operation/write/update_spec.rb +6 -6
  89. data/spec/mongo/options/redacted_spec.rb +350 -0
  90. data/spec/mongo/protocol/query_spec.rb +15 -1
  91. data/spec/mongo/retryable_spec.rb +147 -0
  92. data/spec/mongo/server/connection_pool/queue_spec.rb +16 -0
  93. data/spec/mongo/server/connection_pool_spec.rb +32 -0
  94. data/spec/mongo/server/connection_spec.rb +37 -0
  95. data/spec/mongo/server_discovery_and_monitoring_spec.rb +24 -59
  96. data/spec/mongo/server_selection_rtt_spec.rb +37 -57
  97. data/spec/mongo/server_selection_spec.rb +2 -0
  98. data/spec/mongo/server_selector/nearest_spec.rb +1 -0
  99. data/spec/mongo/server_selector/primary_preferred_spec.rb +1 -0
  100. data/spec/mongo/server_selector/primary_spec.rb +8 -2
  101. data/spec/mongo/server_selector/secondary_preferred_spec.rb +1 -0
  102. data/spec/mongo/server_selector/secondary_spec.rb +1 -0
  103. data/spec/mongo/server_spec.rb +68 -1
  104. data/spec/mongo/socket/ssl_spec.rb +29 -5
  105. data/spec/mongo/uri_spec.rb +20 -20
  106. data/spec/support/crud.rb +7 -1
  107. data/spec/support/matchers.rb +1 -1
  108. data/spec/support/shared/server_selector.rb +58 -2
  109. metadata +20 -5
  110. metadata.gz.sig +0 -0
@@ -21,6 +21,11 @@ module Mongo
21
21
  # @since 2.0.0
22
22
  module Index
23
23
 
24
+ # Wildcard constant for all.
25
+ #
26
+ # @since 2.1.0
27
+ ALL = '*'.freeze
28
+
24
29
  # Specify ascending order for an index.
25
30
  #
26
31
  # @since 2.0.0
@@ -76,7 +76,7 @@ module Mongo
76
76
  #
77
77
  # @since 2.0.0
78
78
  def drop_one(name)
79
- raise Error::MultiIndexDrop.new if name == '*'
79
+ raise Error::MultiIndexDrop.new if name == Index::ALL
80
80
  drop_by_name(name)
81
81
  end
82
82
 
@@ -89,7 +89,7 @@ module Mongo
89
89
  #
90
90
  # @since 2.0.0
91
91
  def drop_all
92
- drop_by_name('*')
92
+ drop_by_name(Index::ALL)
93
93
  end
94
94
 
95
95
  # Creates an index on the collection.
@@ -53,7 +53,9 @@ module Mongo
53
53
  #
54
54
  # @since 2.1.0
55
55
  def started(event)
56
- log_debug("#{prefix(event)} | STARTED | #{format_command(event.command)}")
56
+ if logger.debug?
57
+ log_debug("#{prefix(event)} | STARTED | #{format_command(event.command)}")
58
+ end
57
59
  end
58
60
 
59
61
  # Handle the command succeeded event.
@@ -65,7 +67,9 @@ module Mongo
65
67
  #
66
68
  # @since 2.1.0
67
69
  def succeeded(event)
68
- log_debug("#{prefix(event)} | SUCCEEDED | #{event.duration}s")
70
+ if logger.debug?
71
+ log_debug("#{prefix(event)} | SUCCEEDED | #{event.duration}s")
72
+ end
69
73
  end
70
74
 
71
75
  # Handle the command failed event.
@@ -77,7 +81,9 @@ module Mongo
77
81
  #
78
82
  # @since 2.1.0
79
83
  def failed(event)
80
- log_debug("#{prefix(event)} | FAILED | #{event.message} | #{event.duration}s")
84
+ if logger.debug?
85
+ log_debug("#{prefix(event)} | FAILED | #{event.message} | #{event.duration}s")
86
+ end
81
87
  end
82
88
 
83
89
  private
@@ -12,6 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ require 'mongo/monitoring/event/secure'
15
16
  require 'mongo/monitoring/event/command_started'
16
17
  require 'mongo/monitoring/event/command_succeeded'
17
18
  require 'mongo/monitoring/event/command_failed'
@@ -20,6 +20,7 @@ module Mongo
20
20
  #
21
21
  # @since 2.1.0
22
22
  class CommandStarted
23
+ include Secure
23
24
 
24
25
  # @return [ Server::Address ] address The server address.
25
26
  attr_reader :address
@@ -57,7 +58,7 @@ module Mongo
57
58
  @address = address
58
59
  @request_id = request_id
59
60
  @operation_id = operation_id
60
- @command = command
61
+ @command = redacted(command_name, command)
61
62
  end
62
63
 
63
64
  # Create the event from a wire protocol message payload.
@@ -20,6 +20,7 @@ module Mongo
20
20
  #
21
21
  # @since 2.1.0
22
22
  class CommandSucceeded
23
+ include Secure
23
24
 
24
25
  # @return [ Server::Address ] address The server address.
25
26
  attr_reader :address
@@ -61,7 +62,7 @@ module Mongo
61
62
  @address = address
62
63
  @request_id = request_id
63
64
  @operation_id = operation_id
64
- @reply = reply
65
+ @reply = redacted(command_name, reply)
65
66
  @duration = duration
66
67
  end
67
68
 
@@ -97,11 +98,13 @@ module Mongo
97
98
  if reply_payload
98
99
  reply = reply_payload[:reply]
99
100
  if cursor = reply[:cursor]
100
- reply = reply.merge(cursor: cursor.merge(ns: namespace(command_payload)))
101
+ if !cursor.key?(Collection::NS)
102
+ cursor.merge!(Collection::NS => namespace(command_payload))
103
+ end
101
104
  end
102
105
  reply
103
106
  else
104
- BSON::Document.new(ok: 1)
107
+ BSON::Document.new(Operation::Result::OK => 1)
105
108
  end
106
109
  end
107
110
 
@@ -0,0 +1,58 @@
1
+ # Copyright (C) 2015 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the 'License');
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an 'AS IS' BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ class Monitoring
17
+ module Event
18
+
19
+ # Provides behaviour to redact sensitive information from commands and
20
+ # replies.
21
+ #
22
+ # @since 2.1.0
23
+ module Secure
24
+
25
+ # The list of commands that has the data redacted for security.
26
+ #
27
+ # @since 2.1.0
28
+ REDACTED_COMMANDS = [
29
+ 'authenticate',
30
+ 'saslStart',
31
+ 'saslContinue',
32
+ 'getnonce',
33
+ 'createUser',
34
+ 'updateUser',
35
+ 'copydbgetnonce',
36
+ 'copydbsaslstart',
37
+ 'copydb'
38
+ ].freeze
39
+
40
+ # Redact secure information from the document if it's command is in the
41
+ # list.
42
+ #
43
+ # @example Get the redacted document.
44
+ # secure.redacted(command_name, document)
45
+ #
46
+ # @param [ String, Symbol ] command_name The command name.
47
+ # @param [ BSON::Document ] document The document.
48
+ #
49
+ # @return [ BSON::Document ] The redacted document.
50
+ #
51
+ # @since 2.1.0
52
+ def redacted(command_name, document)
53
+ REDACTED_COMMANDS.include?(command_name.to_s) ? BSON::Document.new : document
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -20,4 +20,34 @@ require 'mongo/operation/read_preference'
20
20
  require 'mongo/operation/read'
21
21
  require 'mongo/operation/write'
22
22
  require 'mongo/operation/commands'
23
- require 'mongo/operation/kill_cursors'
23
+ require 'mongo/operation/kill_cursors'
24
+
25
+ module Mongo
26
+ module Operation
27
+
28
+ # The q field constant.
29
+ #
30
+ # @since 2.1.0
31
+ Q = 'q'.freeze
32
+
33
+ # The u field constant.
34
+ #
35
+ # @since 2.1.0
36
+ U = 'u'.freeze
37
+
38
+ # The limit field constant.
39
+ #
40
+ # @since 2.1.0
41
+ LIMIT = 'limit'.freeze
42
+
43
+ # The multi field constant.
44
+ #
45
+ # @since 2.1.0
46
+ MULTI = 'multi'.freeze
47
+
48
+ # The upsert field constant.
49
+ #
50
+ # @since 2.1.0
51
+ UPSERT = 'upsert'.freeze
52
+ end
53
+ end
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ require 'mongo/operation/commands/collections_info/result'
16
+
15
17
  module Mongo
16
18
  module Operation
17
19
 
@@ -0,0 +1,39 @@
1
+ # Copyright (C) 2014-2015 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ module Operation
17
+ class CollectionsInfo
18
+
19
+ # Defines custom behaviour of results when query the system.namespaces
20
+ # collection.
21
+ #
22
+ # @since 2.1.0
23
+ class Result < Operation::Result
24
+
25
+ # Get the namespace for the cursor.
26
+ #
27
+ # @example Get the namespace.
28
+ # result.namespace
29
+ #
30
+ # @return [ String ] The namespace.
31
+ #
32
+ # @since 2.1.0
33
+ def namespace
34
+ Database::NAMESPACES
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -110,6 +110,7 @@ module Mongo
110
110
  def first_document
111
111
  @first_document ||= reply.documents[0]
112
112
  end
113
- end end
113
+ end
114
+ end
114
115
  end
115
116
  end
@@ -16,7 +16,7 @@ module Mongo
16
16
  module Operation
17
17
  class MapReduce
18
18
 
19
- # Defines custom behaviour of results in an aggregation context.
19
+ # Defines custom behaviour of results for a map reduce operation.
20
20
  #
21
21
  # @since 2.0.0
22
22
  class Result < Operation::Result
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ require 'mongo/operation/read/query/result'
16
+
15
17
  module Mongo
16
18
  module Operation
17
19
  module Read
@@ -0,0 +1,40 @@
1
+ # Copyright (C) 2014-2015 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ module Operation
17
+ module Read
18
+ class Query
19
+
20
+ # Defines custom behaviour of results for a query.
21
+ #
22
+ # @since 2.1.0
23
+ class Result < Operation::Result
24
+
25
+ # Determine if the query was a success.
26
+ #
27
+ # @example Was the query successful?
28
+ # result.successful?
29
+ #
30
+ # @return [ true, false ] If the query was successful.
31
+ #
32
+ # @since 2.0.0
33
+ def successful?
34
+ !query_failure?
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -190,12 +190,24 @@ module Mongo
190
190
  def successful?
191
191
  return true if !acknowledged?
192
192
  if first_document.has_key?(OK)
193
- first_document[OK] == 1 && parser.message.empty?
193
+ ok? && parser.message.empty?
194
194
  else
195
195
  !query_failure? && parser.message.empty?
196
196
  end
197
197
  end
198
198
 
199
+ # Check the first document's ok field.
200
+ #
201
+ # @example Check the ok field.
202
+ # result.ok?
203
+ #
204
+ # @return [ true, false ] If the command returned ok.
205
+ #
206
+ # @since 2.1.0
207
+ def ok?
208
+ first_document[OK] == 1
209
+ end
210
+
199
211
  # Validate the result by checking for any errors.
200
212
  #
201
213
  # @note This only checks for errors with writes since authentication is
@@ -60,8 +60,8 @@ module Mongo
60
60
 
61
61
  def messages
62
62
  deletes.collect do |del|
63
- opts = ( del[:limit] || 0 ) <= 0 ? {} : { :flags => [ :single_remove ] }
64
- Protocol::Delete.new(db_name, coll_name, del[:q], opts)
63
+ opts = ( del[Operation::LIMIT] || 0 ) <= 0 ? {} : { :flags => [ :single_remove ] }
64
+ Protocol::Delete.new(db_name, coll_name, del[Operation::Q], opts)
65
65
  end
66
66
  end
67
67
  end
@@ -69,9 +69,9 @@ module Mongo
69
69
  def messages
70
70
  updates.collect do |u|
71
71
  opts = { :flags => [] }
72
- opts[:flags] << :multi_update if !!u[:multi]
73
- opts[:flags] << :upsert if !!u[:upsert]
74
- Protocol::Update.new(db_name, coll_name, u[:q], u[:u], opts)
72
+ opts[:flags] << :multi_update if !!u[Operation::MULTI]
73
+ opts[:flags] << :upsert if !!u[Operation::UPSERT]
74
+ Protocol::Update.new(db_name, coll_name, u[Operation::Q], u[Operation::U], opts)
75
75
  end
76
76
  end
77
77
  end
@@ -61,8 +61,8 @@ module Mongo
61
61
  end
62
62
 
63
63
  def message
64
- selector = delete[:q]
65
- opts = (delete[:limit] || 0) <= 0 ? {} : { :flags => [ :single_remove ] }
64
+ selector = delete[Operation::Q]
65
+ opts = (delete[Operation::LIMIT] || 0) <= 0 ? {} : { :flags => [ :single_remove ] }
66
66
  Protocol::Delete.new(db_name, coll_name, selector, opts)
67
67
  end
68
68
  end
@@ -65,10 +65,15 @@ module Mongo
65
65
 
66
66
  def message
67
67
  flags = []
68
- flags << :multi_update if update[:multi]
69
- flags << :upsert if update[:upsert]
70
- Protocol::Update.new(db_name, coll_name, update[:q], update[:u],
71
- flags.empty? ? {} : { flags: flags })
68
+ flags << :multi_update if update[Operation::MULTI]
69
+ flags << :upsert if update[Operation::UPSERT]
70
+ Protocol::Update.new(
71
+ db_name,
72
+ coll_name,
73
+ update[Operation::Q],
74
+ update[Operation::U],
75
+ flags.empty? ? {} : { flags: flags }
76
+ )
72
77
  end
73
78
  end
74
79
  end
@@ -13,3 +13,4 @@
13
13
  # limitations under the License.
14
14
 
15
15
  require 'mongo/options/mapper'
16
+ require 'mongo/options/redacted'
@@ -0,0 +1,156 @@
1
+ # Copyright (C) 2015 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ module Options
17
+
18
+ # Class for wrapping options that could be sensitive.
19
+ # When printed, the sensitive values will be redacted.
20
+ #
21
+ # @since 2.1.0
22
+ class Redacted < BSON::Document
23
+
24
+ # The options whose values will be redacted.
25
+ #
26
+ # @since 2.1.0
27
+ SENSITIVE_OPTIONS = [ :password,
28
+ :pwd ].freeze
29
+
30
+ # The replacement string used in place of the value for sensitive keys.
31
+ #
32
+ # @since 2.1.0
33
+ STRING_REPLACEMENT = '<REDACTED>'.freeze
34
+
35
+ # Get a string representation of the options.
36
+ #
37
+ # @return [ String ] The string representation of the options.
38
+ #
39
+ # @since 2.1.0
40
+ def inspect
41
+ redacted_string(:inspect)
42
+ end
43
+
44
+ # Get a string representation of the options.
45
+ #
46
+ # @return [ String ] The string representation of the options.
47
+ #
48
+ # @since 2.1.0
49
+ def to_s
50
+ redacted_string(:to_s)
51
+ end
52
+
53
+ # Whether these options contain a given key.
54
+ #
55
+ # @example Determine if the options contain a given key.
56
+ # options.has_key?(:name)
57
+ #
58
+ # @param [ String, Symbol ] key The key to check for existence.
59
+ #
60
+ # @return [ true, false ] If the options contain the given key.
61
+ #
62
+ # @since 2.1.0
63
+ def has_key?(key)
64
+ super(convert_key(key))
65
+ end
66
+ alias_method :key?, :has_key?
67
+
68
+ # Returns a new options object consisting of pairs for which the block returns false.
69
+ #
70
+ # @example Get a new options object with pairs for which the block returns false.
71
+ # new_options = options.reject { |k, v| k == 'database' }
72
+ #
73
+ # @yieldparam [ String, Object ] The key as a string and its value.
74
+ #
75
+ # @return [ Options::Redacted ] A new options object.
76
+ #
77
+ # @since 2.1.0
78
+ def reject(&block)
79
+ new_options = dup
80
+ new_options.reject!(&block) || new_options
81
+ end
82
+
83
+ # Only keeps pairs for which the block returns false.
84
+ #
85
+ # @example Remove pairs from this object for which the block returns true.
86
+ # options.reject! { |k, v| k == 'database' }
87
+ #
88
+ # @yieldparam [ String, Object ] The key as a string and its value.
89
+ #
90
+ # @return [ Options::Redacted, nil ] This object or nil if no changes were made.
91
+ #
92
+ # @since 2.1.0
93
+ def reject!
94
+ if block_given?
95
+ n_keys = keys.size
96
+ keys.each do |key|
97
+ delete(key) if yield(key, self[key])
98
+ end
99
+ n_keys == keys.size ? nil : self
100
+ else
101
+ to_enum
102
+ end
103
+ end
104
+
105
+ # Returns a new options object consisting of pairs for which the block returns true.
106
+ #
107
+ # @example Get a new options object with pairs for which the block returns true.
108
+ # ssl_options = options.select { |k, v| k =~ /ssl/ }
109
+ #
110
+ # @yieldparam [ String, Object ] The key as a string and its value.
111
+ #
112
+ # @return [ Options::Redacted ] A new options object.
113
+ #
114
+ # @since 2.1.0
115
+ def select(&block)
116
+ new_options = dup
117
+ new_options.select!(&block) || new_options
118
+ end
119
+
120
+ # Only keeps pairs for which the block returns true.
121
+ #
122
+ # @example Remove pairs from this object for which the block does not return true.
123
+ # options.select! { |k, v| k =~ /ssl/ }
124
+ #
125
+ # @yieldparam [ String, Object ] The key as a string and its value.
126
+ #
127
+ # @return [ Options::Redacted, nil ] This object or nil if no changes were made.
128
+ #
129
+ # @since 2.1.0
130
+ def select!
131
+ if block_given?
132
+ n_keys = keys.size
133
+ keys.each do |key|
134
+ delete(key) unless yield(key, self[key])
135
+ end
136
+ n_keys == keys.size ? nil : self
137
+ else
138
+ to_enum
139
+ end
140
+ end
141
+
142
+ private
143
+
144
+ def redacted_string(method)
145
+ '{' + reduce([]) do |list, (k, v)|
146
+ list << "#{k.send(method)}=>#{redact(k, v, method)}"
147
+ end.join(', ') + '}'
148
+ end
149
+
150
+ def redact(k, v, method)
151
+ return STRING_REPLACEMENT if SENSITIVE_OPTIONS.include?(k.to_sym)
152
+ v.send(method)
153
+ end
154
+ end
155
+ end
156
+ end