diff --git a/.rubocop.yml b/.rubocop.yml index d38f97fdb..45db10559 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -142,9 +142,6 @@ Layout/EmptyLinesAroundClassBody: Layout/EmptyLinesAroundModuleBody: Enabled: false -Style/IfUnlessModifier: - Enabled: false - Performance/CollectionLiteralInLoop: Exclude: - 'spec/mongoid/association/embedded/embeds_many/proxy_spec.rb' @@ -153,6 +150,9 @@ Performance/CollectionLiteralInLoop: - 'spec/mongoid/criteria/queryable/selectable_spec.rb' - 'spec/mongoid/criteria/queryable/selector_spec.rb' +Style/IfUnlessModifier: + Enabled: false + # -------------------------------------------------- # These cops are intentionally disabled due to incompatibility. @@ -215,6 +215,9 @@ Naming/PredicateName: - has_attribute? - has_attribute_before_type_cast? +RSpec/IndexedLet: + Enabled: false + RSpec/NotToNot: EnforcedStyle: to_not diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 8b95d8ee4..af5d756b5 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config --exclude-limit 1000` -# on 2024-01-16 04:19:18 UTC using RuboCop version 1.60.0. +# on 2024-05-06 14:01:50 UTC using RuboCop version 1.63.4. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -21,7 +21,7 @@ Lint/SelfAssignment: - 'spec/integration/associations/has_one_spec.rb' - 'spec/mongoid/association/embedded/embeds_one/proxy_spec.rb' -# Offense count: 108 +# Offense count: 110 # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. Metrics/AbcSize: Max: 154 @@ -37,22 +37,22 @@ Metrics/BlockLength: Metrics/BlockNesting: Max: 6 -# Offense count: 17 +# Offense count: 18 # Configuration parameters: CountComments, CountAsOne. Metrics/ClassLength: Max: 337 -# Offense count: 51 +# Offense count: 52 # Configuration parameters: AllowedMethods, AllowedPatterns. Metrics/CyclomaticComplexity: Max: 33 -# Offense count: 184 +# Offense count: 185 # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. Metrics/MethodLength: Max: 87 -# Offense count: 22 +# Offense count: 21 # Configuration parameters: CountComments, CountAsOne. Metrics/ModuleLength: Max: 330 @@ -63,7 +63,7 @@ Metrics/ParameterLists: MaxOptionalParameters: 4 Max: 6 -# Offense count: 40 +# Offense count: 41 # Configuration parameters: AllowedMethods, AllowedPatterns. Metrics/PerceivedComplexity: Max: 20 @@ -262,7 +262,15 @@ RSpec/DescribeClass: - 'spec/mongoid/railties/console_sandbox_spec.rb' - 'spec/mongoid/tasks/database_rake_spec.rb' -# Offense count: 124 +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: CustomTransform, IgnoredWords, DisallowedExamples. +# DisallowedExamples: works +RSpec/ExampleWording: + Exclude: + - 'spec/mongoid/persistable/updatable_spec.rb' + +# Offense count: 120 RSpec/ExpectInHook: Exclude: - 'spec/integration/associations/embedded_spec.rb' @@ -301,7 +309,6 @@ RSpec/ExpectInHook: - 'spec/mongoid/serializable_spec.rb' - 'spec/mongoid/tasks/database_rake_spec.rb' - 'spec/mongoid/tasks/encryption_spec.rb' - - 'spec/mongoid/validatable/associated_spec.rb' - 'spec/mongoid/validatable/presence_spec.rb' - 'spec/support/immutable_ids.rb' @@ -335,13 +342,14 @@ RSpec/FilePath: - 'spec/mongoid/validatable/uniqueness_spec.rb' - 'spec/mongoid/version_spec.rb' -# Offense count: 18 +# Offense count: 21 RSpec/IteratedExpectation: Exclude: - 'spec/mongoid/association/referenced/belongs_to/eager_spec.rb' - 'spec/mongoid/association/referenced/has_many/eager_spec.rb' - 'spec/mongoid/association/referenced/has_many/enumerable_spec.rb' - 'spec/mongoid/association/referenced/has_one/eager_spec.rb' + - 'spec/mongoid/clients_spec.rb' - 'spec/mongoid/contextual/memory_spec.rb' - 'spec/mongoid/contextual/mongo_spec.rb' - 'spec/mongoid/criteria_spec.rb' @@ -481,7 +489,7 @@ RSpec/LetSetup: - 'spec/mongoid/touchable_spec.rb' - 'spec/mongoid/validatable/uniqueness_spec.rb' -# Offense count: 308 +# Offense count: 306 # Configuration parameters: . # SupportedStyles: have_received, receive RSpec/MessageSpies: @@ -516,7 +524,7 @@ RSpec/NamedSubject: RSpec/NestedGroups: Max: 13 -# Offense count: 31 +# Offense count: 32 # Configuration parameters: AllowedPatterns. # AllowedPatterns: ^expect_, ^assert_ RSpec/NoExpectationExample: @@ -531,6 +539,7 @@ RSpec/NoExpectationExample: - 'spec/mongoid/collection_configurable_spec.rb' - 'spec/mongoid/document_spec.rb' - 'spec/mongoid/errors/mongoid_error_spec.rb' + - 'spec/mongoid/inspectable_spec.rb' - 'spec/mongoid/persistence_context_spec.rb' - 'spec/mongoid/scopable_spec.rb' - 'spec/mongoid/tasks/database_rake_spec.rb' @@ -543,18 +552,52 @@ RSpec/OverwritingSetup: - 'spec/mongoid/interceptable_spec.rb' - 'spec/mongoid/serializable_spec.rb' -# Offense count: 17 +# Offense count: 3 RSpec/PendingWithoutReason: Exclude: + - 'spec/mongoid/criteria/queryable/aggregable_spec.rb' + - 'spec/mongoid/serializable_spec.rb' + +# Offense count: 8 +# This cop supports safe autocorrection (--autocorrect). +RSpec/RedundantPredicateMatcher: + Exclude: + - 'spec/mongoid/copyable_spec.rb' + - 'spec/mongoid/document_spec.rb' + - 'spec/mongoid/equality_spec.rb' + +# Offense count: 105 +RSpec/RemoveConst: + Exclude: + - 'spec/integration/discriminator_key_spec.rb' + - 'spec/mongoid/association/auto_save_spec.rb' - 'spec/mongoid/association/embedded/embedded_in_spec.rb' - - 'spec/mongoid/association/embedded/embeds_many_spec.rb' - - 'spec/mongoid/association/embedded/embeds_one_spec.rb' + - 'spec/mongoid/association/embedded/embeds_many/proxy_spec.rb' + - 'spec/mongoid/association/macros_spec.rb' + - 'spec/mongoid/association/options_spec.rb' + - 'spec/mongoid/association/referenced/belongs_to/proxy_spec.rb' - 'spec/mongoid/association/referenced/belongs_to_spec.rb' - 'spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb' - 'spec/mongoid/association/referenced/has_many_spec.rb' + - 'spec/mongoid/association/referenced/has_one/proxy_spec.rb' - 'spec/mongoid/association/referenced/has_one_spec.rb' - - 'spec/mongoid/criteria/queryable/aggregable_spec.rb' - - 'spec/mongoid/serializable_spec.rb' + - 'spec/mongoid/association/syncable_spec.rb' + - 'spec/mongoid/clients_spec.rb' + - 'spec/mongoid/collection_configurable_spec.rb' + - 'spec/mongoid/copyable_spec.rb' + - 'spec/mongoid/criteria/includable_spec.rb' + - 'spec/mongoid/criteria/queryable/options_spec.rb' + - 'spec/mongoid/criteria/queryable/selectable_spec.rb' + - 'spec/mongoid/criteria/queryable/selectable_where_spec.rb' + - 'spec/mongoid/criteria/queryable/selector_spec.rb' + - 'spec/mongoid/document_spec.rb' + - 'spec/mongoid/fields/standard_spec.rb' + - 'spec/mongoid/scopable_spec.rb' + - 'spec/mongoid/stateful_spec.rb' + - 'spec/mongoid/tasks/database_spec.rb' + - 'spec/mongoid/timestamps/timeless_spec.rb' + - 'spec/mongoid/validatable/numericality_spec.rb' + - 'spec/support/feature_sandbox.rb' # Offense count: 17 RSpec/RepeatedDescription: @@ -639,6 +682,7 @@ RSpec/ScatteredLet: - 'spec/mongoid/scopable_spec.rb' # Offense count: 67 +# This cop supports safe autocorrection (--autocorrect). RSpec/ScatteredSetup: Exclude: - 'spec/integration/stringified_symbol_field_spec.rb' @@ -650,7 +694,37 @@ RSpec/ScatteredSetup: - 'spec/mongoid/copyable_spec.rb' - 'spec/mongoid/persistable/deletable_spec.rb' -# Offense count: 12 +# Offense count: 24 +# Configuration parameters: Include, CustomTransform, IgnoreMethods, IgnoreMetadata. +# Include: **/*_spec.rb +RSpec/SpecFilePathFormat: + Exclude: + - 'spec/integration/atomic/modifiers_spec.rb' + - 'spec/integration/bson_regexp_raw_spec.rb' + - 'spec/integration/document_spec.rb' + - 'spec/mongoid/association/auto_save_spec.rb' + - 'spec/mongoid/association/counter_cache_spec.rb' + - 'spec/mongoid/association/eager_spec.rb' + - 'spec/mongoid/clients/transactions_spec.rb' + - 'spec/mongoid/criteria/queryable/extensions/boolean_spec.rb' + - 'spec/mongoid/criteria/queryable/extensions/numeric_spec.rb' + - 'spec/mongoid/criteria/queryable/extensions/regexp_raw_spec.rb' + - 'spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb' + - 'spec/mongoid/criteria/queryable/queryable_spec.rb' + - 'spec/mongoid/extensions/binary_spec.rb' + - 'spec/mongoid/extensions/boolean_spec.rb' + - 'spec/mongoid/extensions/raw_value_spec.rb' + - 'spec/mongoid/extensions/stringified_symbol_spec.rb' + - 'spec/mongoid/loading_spec.rb' + - 'spec/mongoid/validatable/associated_spec.rb' + - 'spec/mongoid/validatable/format_spec.rb' + - 'spec/mongoid/validatable/length_spec.rb' + - 'spec/mongoid/validatable/numericality_spec.rb' + - 'spec/mongoid/validatable/presence_spec.rb' + - 'spec/mongoid/validatable/uniqueness_spec.rb' + - 'spec/mongoid/version_spec.rb' + +# Offense count: 8 RSpec/StubbedMock: Exclude: - 'spec/mongoid/clients_spec.rb' @@ -658,7 +732,6 @@ RSpec/StubbedMock: - 'spec/mongoid/persistence_context_spec.rb' - 'spec/mongoid/tasks/database_spec.rb' - 'spec/mongoid/tasks/encryption_spec.rb' - - 'spec/mongoid/validatable/associated_spec.rb' # Offense count: 26 RSpec/SubjectDeclaration: @@ -668,7 +741,7 @@ RSpec/SubjectDeclaration: - 'spec/mongoid/collection_configurable_spec.rb' - 'spec/mongoid/contextual/mongo/documents_loader_spec.rb' -# Offense count: 27 +# Offense count: 23 # Configuration parameters: IgnoreNameless, IgnoreSymbolicNames. RSpec/VerifiedDoubles: Exclude: @@ -684,10 +757,10 @@ RSpec/VerifiedDoubles: - 'spec/mongoid/persistence_context_spec.rb' - 'spec/mongoid/tasks/database_spec.rb' - 'spec/mongoid/threaded_spec.rb' - - 'spec/mongoid/validatable/associated_spec.rb' - 'spec/rails/mongoid_spec.rb' # Offense count: 11 +# This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle, AllowToTime. # SupportedStyles: strict, flexible Rails/Date: @@ -718,6 +791,19 @@ Rails/Delegate: - 'lib/mongoid/findable.rb' - 'lib/mongoid/scopable.rb' +# Offense count: 11 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: AllowedMethods, AllowedPatterns. +# AllowedMethods: order, limit, select, lock +Rails/FindEach: + Exclude: + - 'spec/mongoid/association/referenced/belongs_to/eager_spec.rb' + - 'spec/mongoid/association/referenced/has_and_belongs_to_many/eager_spec.rb' + - 'spec/mongoid/association/referenced/has_many/eager_spec.rb' + - 'spec/mongoid/association/referenced/has_many/proxy_spec.rb' + - 'spec/mongoid/association/referenced/has_one/eager_spec.rb' + - 'spec/mongoid/criteria_projection_spec.rb' + # Offense count: 91 # Configuration parameters: Include. # Include: spec/**/*.rb, test/**/*.rb @@ -737,6 +823,24 @@ Rails/I18nLocaleAssignment: - 'spec/mongoid/validatable/uniqueness_spec.rb' - 'spec/support/macros.rb' +# Offense count: 28 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: AllowedReceivers. +# AllowedReceivers: ActionMailer::Preview, ActiveSupport::TimeZone +Rails/RedundantActiveRecordAllMethod: + Exclude: + - 'spec/integration/criteria/time_with_zone_spec.rb' + - 'spec/mongoid/association/referenced/belongs_to/eager_spec.rb' + - 'spec/mongoid/association/referenced/has_and_belongs_to_many/eager_spec.rb' + - 'spec/mongoid/association/referenced/has_many/eager_spec.rb' + - 'spec/mongoid/association/referenced/has_one/eager_spec.rb' + - 'spec/mongoid/contextual/aggregable/memory_spec.rb' + - 'spec/mongoid/contextual/memory_spec.rb' + - 'spec/mongoid/criteria/includable_spec.rb' + - 'spec/mongoid/criteria/queryable/selectable_logical_spec.rb' + - 'spec/mongoid/criteria_spec.rb' + - 'spec/mongoid/serializable_spec.rb' + # Offense count: 133 # Configuration parameters: ForbiddenMethods, AllowedMethods. # ForbiddenMethods: decrement!, decrement_counter, increment!, increment_counter, insert, insert!, insert_all, insert_all!, toggle!, touch, touch_all, update_all, update_attribute, update_column, update_columns, update_counters, upsert, upsert_all @@ -765,7 +869,7 @@ Rails/SkipsModelValidations: - 'spec/mongoid/touchable_spec.rb' - 'spec/support/models/server.rb' -# Offense count: 151 +# Offense count: 134 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle. # SupportedStyles: strict, flexible @@ -775,7 +879,6 @@ Rails/TimeZone: - 'lib/mongoid/extensions/date.rb' - 'lib/mongoid/extensions/string.rb' - 'lib/mongoid/extensions/time.rb' - - 'lib/mongoid/timestamps/updated.rb' - 'spec/integration/criteria/date_field_spec.rb' - 'spec/integration/criteria/raw_value_spec.rb' - 'spec/integration/persistence/range_field_spec.rb' @@ -804,7 +907,15 @@ Rails/TimeZone: - 'spec/mongoid/touchable_spec.rb' - 'spec/support/models/post.rb' -# Offense count: 4 +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: exists, where +Rails/WhereExists: + Exclude: + - 'lib/mongoid/association/referenced/has_many/enumerable.rb' + +# Offense count: 2 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowOnlyRestArgument, UseAnonymousForwarding, RedundantRestArgumentNames, RedundantKeywordRestArgumentNames, RedundantBlockArgumentNames. # RedundantRestArgumentNames: args, arguments @@ -812,7 +923,6 @@ Rails/TimeZone: # RedundantBlockArgumentNames: blk, block, proc Style/ArgumentsForwarding: Exclude: - - 'lib/mongoid/association/referenced/has_many/enumerable.rb' - 'lib/mongoid/association/referenced/has_many/proxy.rb' # Offense count: 5 diff --git a/docs/reference/configuration.txt b/docs/reference/configuration.txt index 852f32194..a66174de7 100644 --- a/docs/reference/configuration.txt +++ b/docs/reference/configuration.txt @@ -863,58 +863,57 @@ as the following example shows: Usage with Forking Servers ========================== -When using Mongoid with a forking web server such as Puma, Unicorn or -Passenger, it is recommended to not perform any operations on Mongoid models -in the parent process prior to the fork. - -When a process forks, Ruby threads are not transferred to the child processes -and the Ruby driver Client objects lose their background monitoring. The -application will typically seem to work just fine until the deployment -state changes (for example due to network errors, a maintenance event) at -which point the application is likely to start getting ``NoServerAvailable`` -exception when performing MongoDB operations. - -If the parent process needs to perform operations on the MongoDB database, -reset all clients in the workers after they forked. How to do so depends -on the web server being used. - -If the parent process does not need to perform operations on the MongoDB -database after child processes are forked, close the clients in the parent -prior to forking children. If the parent process performs operations on a Mongo -client and does not close it, the parent process will continue consuming a -connection slot in the cluster and will continue monitoring the cluster for -as long as the parent remains alive. - -.. note:: - - The close/reconnect pattern described here should be used with Ruby driver - version 2.6.2 or higher. Previous driver versions did not recreate - monitoring threads when reconnecting. +When using Mongoid with a forking web server such as Puma, or any application +that otherwise forks to spawn child processes, special considerations apply. + +If possible, we recommend to not perform any MongoDB operations in the parent +process prior to forking, which will avoid any forking-related pitfalls. + +A detailed technical explanation of how the Mongo Ruby Driver handles forking +is given in the `driver's "Usage with Forking Servers" documentation +`. +In a nutshell, to avoid various connection errors such as ``Mongo::Error::SocketError`` +and ``Mongo::Error::NoServerAvailable``, you must do the following: + +1. Disconnect MongoDB clients in the parent Ruby process immediately *before* + forking using ``Mongoid.disconnect_clients``. This ensures the parent and child + process do not accidentally reuse the same sockets and have I/O conflicts. + Note that ``Mongoid.disconnect_clients`` does not disrupt any in-flight + MongoDB operations, and will automatically reconnect when you perform new + operations. +2. Reconnect your MongoDB clients in the child Ruby process immediately *after* + forking using ``Mongoid.reconnect_clients``. This is required to respawn + the driver's monitoring threads in the child process. + +Most web servers provide hooks that can be used by applications to +perform actions when the worker processes are forked. The following +are configuration examples for several common Ruby web servers. Puma ---- Use the ``on_worker_boot`` hook to reconnect clients in the workers and -the ``before_fork`` hook to close clients in the parent process -(`Puma documentation `_): +the ``before_fork`` and ``on_refork`` hooks to close clients in the +parent process (`Puma documentation `_). .. code-block:: ruby - on_worker_boot do - if defined?(Mongoid) - Mongoid::Clients.clients.each do |name, client| - client.close - client.reconnect - end - else - raise "Mongoid is not loaded. You may have forgotten to enable app preloading." - end - end + # config/puma.rb + # Runs in the Puma master process before it forks a child worker. before_fork do - if defined?(Mongoid) - Mongoid.disconnect_clients - end + Mongoid.disconnect_clients + end + + # Required when using Puma's fork_worker option. Runs in the + # child worker 0 process before it forks grandchild workers. + on_refork do + Mongoid.disconnect_clients + end + + # Runs in each Puma child process after it forks from its parent. + on_worker_boot do + Mongoid.reconnect_clients end Unicorn @@ -926,21 +925,14 @@ the ``before_fork`` hook to close clients in the parent process .. code-block:: ruby - after_fork do |server, worker| - if defined?(Mongoid) - Mongoid::Clients.clients.each do |name, client| - client.close - client.reconnect - end - else - raise "Mongoid is not loaded. You may have forgotten to enable app preloading." - end + # config/unicorn.rb + + before_fork do |_server, _worker| + Mongoid.disconnect_clients end - before_fork do |server, worker| - if defined?(Mongoid) - Mongoid.disconnect_clients - end + after_fork do |_server, _worker| + Mongoid.reconnect_clients end Passenger @@ -956,12 +948,7 @@ before the workers are forked. if defined?(PhusionPassenger) PhusionPassenger.on_event(:starting_worker_process) do |forked| - if forked - Mongoid::Clients.clients.each do |name, client| - client.close - client.reconnect - end - end + Mongoid.reconnect_clients if forked end end diff --git a/gemfiles/standard.rb b/gemfiles/standard.rb index fed0abd5f..52b45aef8 100644 --- a/gemfiles/standard.rb +++ b/gemfiles/standard.rb @@ -8,11 +8,11 @@ def standard_dependencies end group :development, :test do - gem 'rubocop', '~> 1.60.0' - gem 'rubocop-performance', '~> 1.16.0' - gem 'rubocop-rails', '~> 2.17.4' + gem 'rubocop', '~> 1.63.4' + gem 'rubocop-performance', '~> 1.21.0' + gem 'rubocop-rails', '~> 2.24.1' gem 'rubocop-rake', '~> 0.6.0' - gem 'rubocop-rspec', '~> 2.19.0' + gem 'rubocop-rspec', '~> 2.29.2' end group :test do diff --git a/lib/mongoid.rb b/lib/mongoid.rb index 45e7261cc..491dbe471 100644 --- a/lib/mongoid.rb +++ b/lib/mongoid.rb @@ -99,6 +99,16 @@ def disconnect_clients Clients.disconnect end + # Reconnect all active clients. + # + # @example Reconnect all active clients. + # Mongoid.reconnect_clients + # + # @return [ true ] True. + def reconnect_clients + Clients.reconnect + end + # Convenience method for getting a named client. # # @example Get a named client. diff --git a/lib/mongoid/association.rb b/lib/mongoid/association.rb index d37757c24..ad1e6b177 100644 --- a/lib/mongoid/association.rb +++ b/lib/mongoid/association.rb @@ -129,10 +129,10 @@ def referenced_one? # @return [ Hash ] The association metadata. def reload_relations relations.each_pair do |name, _meta| - next unless instance_variable_defined?("@_#{name}") && - (_parent.nil? || instance_variable_get("@_#{name}") != _parent) + next unless instance_variable_defined?(:"@_#{name}") && + (_parent.nil? || instance_variable_get(:"@_#{name}") != _parent) - remove_instance_variable("@_#{name}") + remove_instance_variable(:"@_#{name}") end end end diff --git a/lib/mongoid/association/accessors.rb b/lib/mongoid/association/accessors.rb index 309b88d36..e585730b9 100644 --- a/lib/mongoid/association/accessors.rb +++ b/lib/mongoid/association/accessors.rb @@ -67,7 +67,7 @@ def create_relation(object, association, selected_fields = nil) # # @param [ Symbol ] name The name of the association. def reset_relation_criteria(name) - return unless instance_variable_defined?("@_#{name}") + return unless instance_variable_defined?(:"@_#{name}") send(name).reset_unloaded end @@ -83,7 +83,7 @@ def reset_relation_criteria(name) # # @return [ Mongoid::Association::Proxy ] The association. def set_relation(name, relation) - instance_variable_set("@_#{name}", relation) + instance_variable_set(:"@_#{name}", relation) end # Adds the existence check for associations. @@ -129,7 +129,7 @@ def self.define_getter!(association) klass.re_define_method(name) do |reload = false| value = get_relation(name, association, nil, reload) if value.nil? && association.autobuilding? && !without_autobuild? - value = send("build_#{name}") + value = send(:"build_#{name}") end value end @@ -222,7 +222,7 @@ def self.define_builder!(association) attributes, _options = parse_args(*args) document = Factory.build(association.relation_class, attributes) _building do - child = send("#{name}=", document) + child = send(:"#{name}=", document) child.run_callbacks(:build) child end @@ -247,7 +247,7 @@ def self.define_creator!(association) attributes, _options = parse_args(*args) document = Factory.build(association.klass, attributes) doc = _assigning do - send("#{name}=", document) + send(:"#{name}=", document) end doc.save save if new_record? && association.stores_foreign_key? diff --git a/lib/mongoid/association/builders.rb b/lib/mongoid/association/builders.rb index 56354b8d2..4eab3940b 100644 --- a/lib/mongoid/association/builders.rb +++ b/lib/mongoid/association/builders.rb @@ -33,7 +33,7 @@ def self.define_builder!(association) attributes, _options = parse_args(*args) document = Factory.execute_build(association.relation_class, attributes, execute_callbacks: false) _building do - child = send("#{association.name}=", document) + child = send(:"#{association.name}=", document) child.run_pending_callbacks child.run_callbacks(:build) child @@ -57,7 +57,7 @@ def self.define_creator!(association) attributes, _options = parse_args(*args) document = Factory.execute_build(association.relation_class, attributes, execute_callbacks: false) doc = _assigning do - send("#{association.name}=", document) + send(:"#{association.name}=", document) end doc.run_pending_callbacks doc.save diff --git a/lib/mongoid/association/depending.rb b/lib/mongoid/association/depending.rb index d96dd4465..9a9b490db 100644 --- a/lib/mongoid/association/depending.rb +++ b/lib/mongoid/association/depending.rb @@ -90,7 +90,7 @@ def self.validate!(association) def apply_destroy_dependencies! self.class._all_dependents.each do |association| if (dependent = association.try(:dependent)) - send("_dependent_#{dependent}!", association) + send(:"_dependent_#{dependent}!", association) end end end diff --git a/lib/mongoid/association/referenced/counter_cache.rb b/lib/mongoid/association/referenced/counter_cache.rb index af15089df..e5deb481e 100644 --- a/lib/mongoid/association/referenced/counter_cache.rb +++ b/lib/mongoid/association/referenced/counter_cache.rb @@ -103,8 +103,8 @@ def self.define_callbacks!(association) klass.after_update do foreign_key = association.foreign_key - if send("#{foreign_key}_previously_changed?") - original, current = send("#{foreign_key}_previous_change") + if send(:"#{foreign_key}_previously_changed?") + original, current = send(:"#{foreign_key}_previous_change") unless original.nil? association.klass.with(persistence_context.for_child(association.klass)) do |k| diff --git a/lib/mongoid/attributes.rb b/lib/mongoid/attributes.rb index 6e585acce..8ca238611 100644 --- a/lib/mongoid/attributes.rb +++ b/lib/mongoid/attributes.rb @@ -321,15 +321,15 @@ def alias_attribute(name, original) aliased_fields[name.to_s] = original.to_s alias_method name, original - alias_method "#{name}=", "#{original}=" - alias_method "#{name}?", "#{original}?" - alias_method "#{name}_change", "#{original}_change" - alias_method "#{name}_changed?", "#{original}_changed?" - alias_method "reset_#{name}!", "reset_#{original}!" - alias_method "reset_#{name}_to_default!", "reset_#{original}_to_default!" - alias_method "#{name}_was", "#{original}_was" - alias_method "#{name}_will_change!", "#{original}_will_change!" - alias_method "#{name}_before_type_cast", "#{original}_before_type_cast" + alias_method :"#{name}=", :"#{original}=" + alias_method :"#{name}?", :"#{original}?" + alias_method :"#{name}_change", :"#{original}_change" + alias_method :"#{name}_changed?", :"#{original}_changed?" + alias_method :"reset_#{name}!", :"reset_#{original}!" + alias_method :"reset_#{name}_to_default!", :"reset_#{original}_to_default!" + alias_method :"#{name}_was", :"#{original}_was" + alias_method :"#{name}_will_change!", :"#{original}_will_change!" + alias_method :"#{name}_before_type_cast", :"#{original}_before_type_cast" end # Removes a field alias. @@ -341,15 +341,15 @@ def unalias_attribute(name) end remove_method name - remove_method "#{name}=" - remove_method "#{name}?" - remove_method "#{name}_change" - remove_method "#{name}_changed?" - remove_method "reset_#{name}!" - remove_method "reset_#{name}_to_default!" - remove_method "#{name}_was" - remove_method "#{name}_will_change!" - remove_method "#{name}_before_type_cast" + remove_method :"#{name}=" + remove_method :"#{name}?" + remove_method :"#{name}_change" + remove_method :"#{name}_changed?" + remove_method :"reset_#{name}!" + remove_method :"reset_#{name}_to_default!" + remove_method :"#{name}_was" + remove_method :"#{name}_will_change!" + remove_method :"#{name}_before_type_cast" end end diff --git a/lib/mongoid/attributes/dynamic.rb b/lib/mongoid/attributes/dynamic.rb index 43b6b0354..f4179c766 100644 --- a/lib/mongoid/attributes/dynamic.rb +++ b/lib/mongoid/attributes/dynamic.rb @@ -49,7 +49,7 @@ def define_dynamic_reader(name) # @param [ String ] name The name of the field. def define_dynamic_before_type_cast_reader(name) class_eval do - define_method("#{name}_before_type_cast") do + define_method(:"#{name}_before_type_cast") do attribute_will_change!(name) read_attribute_before_type_cast(name) end @@ -68,7 +68,7 @@ def define_dynamic_writer(name) return unless name.valid_method_name? class_eval do - define_method("#{name}=") do |value| + define_method(:"#{name}=") do |value| write_attribute(name, value) end end @@ -83,9 +83,9 @@ def define_dynamic_writer(name) # @param [ Symbol ] name The name of the field. # @param [ Object ] value The value of the field. def process_attribute(name, value) - responds = respond_to?("#{name}=") + responds = respond_to?(:"#{name}=") if responds - send("#{name}=", value) + send(:"#{name}=", value) else write_attribute(name, value) end diff --git a/lib/mongoid/attributes/processing.rb b/lib/mongoid/attributes/processing.rb index f936a17d3..fb4e76e0a 100644 --- a/lib/mongoid/attributes/processing.rb +++ b/lib/mongoid/attributes/processing.rb @@ -119,13 +119,13 @@ def pending_nested # @param [ Symbol ] name The name of the field. # @param [ Object ] value The value of the field. def process_attribute(name, value) - if !respond_to?("#{name}=", true) && (store_as = aliased_fields.invert[name.to_s]) + if !respond_to?(:"#{name}=", true) && (store_as = aliased_fields.invert[name.to_s]) name = store_as end - responds = respond_to?("#{name}=", true) + responds = respond_to?(:"#{name}=", true) raise Errors::UnknownAttribute.new(self.class, name) unless responds - send("#{name}=", value) + send(:"#{name}=", value) end # Process all the pending nested attributes that needed to wait until @@ -135,7 +135,7 @@ def process_attribute(name, value) # document.process_nested def process_nested pending_nested.each_pair do |name, value| - send("#{name}=", value) + send(:"#{name}=", value) end end @@ -160,7 +160,7 @@ def process_relations if value.is_a?(Hash) association.nested_builder(value, {}).build(self) else - send("#{name}=", value) + send(:"#{name}=", value) end end end diff --git a/lib/mongoid/changeable.rb b/lib/mongoid/changeable.rb index bf5bfff1e..d24b04777 100644 --- a/lib/mongoid/changeable.rb +++ b/lib/mongoid/changeable.rb @@ -336,9 +336,9 @@ def reset_attribute!(attr) def reset_attribute_to_default!(attr) attr = database_field_name(attr) if (field = fields[attr]) - __send__("#{attr}=", field.eval_default(self)) + __send__(:"#{attr}=", field.eval_default(self)) else - __send__("#{attr}=", nil) + __send__(:"#{attr}=", nil) end end diff --git a/lib/mongoid/clients.rb b/lib/mongoid/clients.rb index ca6866ab3..90040ef69 100644 --- a/lib/mongoid/clients.rb +++ b/lib/mongoid/clients.rb @@ -49,6 +49,18 @@ def default # @return [ true ] True. def disconnect clients.each_value(&:close) + true + end + + # Reconnect all active clients. + # + # @example Reconnect all active clients. + # Mongoid::Clients.reconnect + # + # @return [ true ] True. + def reconnect + clients.each_value(&:reconnect) + true end # Get a stored client with the provided name. If no client exists diff --git a/lib/mongoid/config.rb b/lib/mongoid/config.rb index 7864e0c24..7c5c3be2f 100644 --- a/lib/mongoid/config.rb +++ b/lib/mongoid/config.rb @@ -337,7 +337,7 @@ def options=(options) Validators::AsyncQueryExecutor.validate(options) options.each_pair do |option, value| Validators::Option.validate(option) - send("#{option}=", value) + send(:"#{option}=", value) end end @@ -367,10 +367,14 @@ def time_zone # config.running_with_passenger? # # @return [ true | false ] If the app is deployed on Passenger. + # + # @deprecated def running_with_passenger? @running_with_passenger ||= defined?(PhusionPassenger) end + Mongoid.deprecate(self, :running_with_passenger?) + private def set_log_levels diff --git a/lib/mongoid/config/defaults.rb b/lib/mongoid/config/defaults.rb index 9b4ea50b0..2857931ea 100644 --- a/lib/mongoid/config/defaults.rb +++ b/lib/mongoid/config/defaults.rb @@ -24,6 +24,8 @@ def load_defaults(version) when '8.1' self.immutable_ids = false self.legacy_persistence_context_behavior = true + self.around_callbacks_for_embeds = true + self.prevent_multiple_calls_of_embedded_callbacks = false load_defaults '9.0' when '9.0' diff --git a/lib/mongoid/config/options.rb b/lib/mongoid/config/options.rb index befb6e108..a0a606b82 100644 --- a/lib/mongoid/config/options.rb +++ b/lib/mongoid/config/options.rb @@ -38,12 +38,12 @@ def option(name, options = {}) end end - define_method("#{name}=") do |value| + define_method(:"#{name}=") do |value| settings[name] = value options[:on_change]&.call(value) end - define_method("#{name}?") do + define_method(:"#{name}?") do !!send(name) end end diff --git a/lib/mongoid/contextual/memory.rb b/lib/mongoid/contextual/memory.rb index 18593f540..c748704b3 100644 --- a/lib/mongoid/contextual/memory.rb +++ b/lib/mongoid/contextual/memory.rb @@ -746,7 +746,7 @@ def retrieve_value_at_path(document, field_path) # If this is a localized field, and there are remaining, get the # _translations hash so that we can get the specified translation in # the remaining - document.send("#{segment}_translations") if field&.localized? + document.send(:"#{segment}_translations") if field&.localized? end meth = klass.aliased_associations[segment] || segment res.nil? ? document.try(meth) : res diff --git a/lib/mongoid/copyable.rb b/lib/mongoid/copyable.rb index 12c4b1a79..6ce3982e8 100644 --- a/lib/mongoid/copyable.rb +++ b/lib/mongoid/copyable.rb @@ -52,12 +52,12 @@ def self.clone_with_hash(klass, attrs) dynamic_attrs.each do |attr_name, value| assoc = object.embedded_relations[attr_name] if assoc&.one? && value.is_a?(Hash) - object.send("#{attr_name}=", clone_with_hash(assoc.klass, value)) + object.send(:"#{attr_name}=", clone_with_hash(assoc.klass, value)) elsif assoc&.many? && value.is_a?(Array) docs = value.map { |h| clone_with_hash(assoc.klass, h) } - object.send("#{attr_name}=", docs) - elsif object.respond_to?("#{attr_name}=") - object.send("#{attr_name}=", value) + object.send(:"#{attr_name}=", docs) + elsif object.respond_to?(:"#{attr_name}=") + object.send(:"#{attr_name}=", value) else object.attributes[attr_name] = value end diff --git a/lib/mongoid/extensions/date.rb b/lib/mongoid/extensions/date.rb index 6dc80bde6..4708891ac 100644 --- a/lib/mongoid/extensions/date.rb +++ b/lib/mongoid/extensions/date.rb @@ -68,13 +68,13 @@ def demongoize(object) def mongoize(object) return if object.blank? - begin - time = if object.is_a?(String) - # https://jira.mongodb.org/browse/MONGOID-4460 - ::Time.parse(object) - else - object.__mongoize_time__ - end + time = begin + if object.is_a?(String) + # https://jira.mongodb.org/browse/MONGOID-4460 + ::Time.parse(object) + else + object.try(:__mongoize_time__) + end rescue ArgumentError nil end diff --git a/lib/mongoid/extensions/object.rb b/lib/mongoid/extensions/object.rb index 91e9c42d6..e5987306b 100644 --- a/lib/mongoid/extensions/object.rb +++ b/lib/mongoid/extensions/object.rb @@ -31,22 +31,6 @@ def __find_args__ end Mongoid.deprecate(self, :__find_args__) - # Mongoize a plain object into a time. - # - # @note This method should not be used, because it does not - # return correct results for non-Time objects. Override - # __mongoize_time__ in classes that are time-like to return an - # instance of Time or ActiveSupport::TimeWithZone. - # - # @example Mongoize the object. - # object.__mongoize_time__ - # - # @return [ Object ] self. - # @deprecated - def __mongoize_time__ - self - end - # Try to form a setter from this object. # # @example Try to form a setter. @@ -158,8 +142,8 @@ def numeric? # # @return [ true | false ] If the variable was defined. def remove_ivar(name) - if instance_variable_defined?("@_#{name}") - remove_instance_variable("@_#{name}") + if instance_variable_defined?(:"@_#{name}") + remove_instance_variable(:"@_#{name}") else false end diff --git a/lib/mongoid/extensions/time.rb b/lib/mongoid/extensions/time.rb index 3c88c0fe1..56607238d 100644 --- a/lib/mongoid/extensions/time.rb +++ b/lib/mongoid/extensions/time.rb @@ -72,7 +72,7 @@ def mongoize(object) return if object.blank? begin - time = object.__mongoize_time__ + time = object.try(:__mongoize_time__) rescue ArgumentError return end diff --git a/lib/mongoid/inspectable.rb b/lib/mongoid/inspectable.rb index 80cfa129c..d83cded92 100644 --- a/lib/mongoid/inspectable.rb +++ b/lib/mongoid/inspectable.rb @@ -18,6 +18,37 @@ def inspect "#<#{self.class.name} _id: #{_id}, #{inspection * ', '}>" end + # This pretty prints the same information as the inspect method. This is + # meant to be called by the standard 'pp' library. + # + # @param [ PP ] pretty_printer The pretty printer. + # + # @example Pretty print the document. + # person.pretty_inspect + # + # @api private + def pretty_print(pretty_printer) + keys = fields.keys | attributes.keys + pretty_printer.group(1, "#<#{self.class.name}", '>') do + sep = -> { pretty_printer.text(',') } + pretty_printer.seplist(keys, sep) do |key| + pretty_printer.breakable + field = fields[key] + as = "(#{field.options[:as]})" if field && field.options[:as] + pretty_printer.text("#{key}#{as}") + pretty_printer.text(':') + pretty_printer.group(1) do + pretty_printer.breakable + if key == '_id' + pretty_printer.text(_id.to_s) + else + pretty_printer.pp(@attributes[key]) + end + end + end + end + end + private # Get an array of inspected fields for the document. diff --git a/lib/mongoid/interceptable.rb b/lib/mongoid/interceptable.rb index d598c37bc..956a5c298 100644 --- a/lib/mongoid/interceptable.rb +++ b/lib/mongoid/interceptable.rb @@ -64,7 +64,7 @@ module Interceptable # # @return [ true | false ] If the callback can be executed. def callback_executable?(kind) - respond_to?("_#{kind}_callbacks") + respond_to?(:"_#{kind}_callbacks") end # Is the document currently in a state that could potentially require @@ -401,7 +401,7 @@ def run_targeted_callbacks(place, kind) name = "_run__#{place}__#{kind}__callbacks" unless respond_to?(name) chain = ActiveSupport::Callbacks::CallbackChain.new(name, {}) - send("_#{kind}_callbacks").each do |callback| + send(:"_#{kind}_callbacks").each do |callback| chain.append(callback) if callback.kind == place end self.class.send :define_method, name do diff --git a/lib/mongoid/scopable.rb b/lib/mongoid/scopable.rb index a6ae5b939..c18922fe2 100644 --- a/lib/mongoid/scopable.rb +++ b/lib/mongoid/scopable.rb @@ -288,17 +288,15 @@ def check_scope_validity(value) # @return [ Method ] The defined method. def define_scope_method(name) singleton_class.class_eval do - ruby2_keywords( - define_method(name) do |*args, **kwargs| - scoping = _declared_scopes[name] - scope = instance_exec(*args, **kwargs, &scoping[:scope]) - extension = scoping[:extension] - to_merge = scope || queryable - criteria = to_merge.empty_and_chainable? ? to_merge : with_default_scope.merge(to_merge) - criteria.extend(extension) - criteria - end - ) + define_method(name) do |*args, **kwargs| + scoping = _declared_scopes[name] + scope = instance_exec(*args, **kwargs, &scoping[:scope]) + extension = scoping[:extension] + to_merge = scope || queryable + criteria = to_merge.empty_and_chainable? ? to_merge : with_default_scope.merge(to_merge) + criteria.extend(extension) + criteria + end end end diff --git a/lib/mongoid/version.rb b/lib/mongoid/version.rb index ef36d090c..781b777e5 100644 --- a/lib/mongoid/version.rb +++ b/lib/mongoid/version.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Mongoid - VERSION = '9.0.0.0.alpha1' + VERSION = '10.0.0.0.alpha1' GEM_NAME = 'mongoid-ultra' diff --git a/lib/mongoid/warnings.rb b/lib/mongoid/warnings.rb index 67cee0cc6..8ef08d22b 100644 --- a/lib/mongoid/warnings.rb +++ b/lib/mongoid/warnings.rb @@ -18,11 +18,11 @@ class << self # @api private def warning(id, message) singleton_class.class_eval do - define_method("warn_#{id}") do - return if instance_variable_get("@#{id}") + define_method(:"warn_#{id}") do + return if instance_variable_get(:"@#{id}") Mongoid.logger.warn(message) - instance_variable_set("@#{id}", true) + instance_variable_set(:"@#{id}", true) end end end diff --git a/spec/mongoid/association/referenced/has_many/proxy_spec.rb b/spec/mongoid/association/referenced/has_many/proxy_spec.rb index b7265d873..d190bd12f 100644 --- a/spec/mongoid/association/referenced/has_many/proxy_spec.rb +++ b/spec/mongoid/association/referenced/has_many/proxy_spec.rb @@ -735,7 +735,7 @@ def initialize(*args) let(:child) { parent.children.send(method) } it 'calls #initialize' do - expect(child.name).to be == 'default' + expect(child.name).to eq 'default' end end diff --git a/spec/mongoid/attributes/dynamic_spec.rb b/spec/mongoid/attributes/dynamic_spec.rb index 2530177a3..a4d922aec 100644 --- a/spec/mongoid/attributes/dynamic_spec.rb +++ b/spec/mongoid/attributes/dynamic_spec.rb @@ -112,7 +112,7 @@ it 'cannot be written' do expect do - bar.send("#{attr_name}=", 'foo bar') + bar.send(:"#{attr_name}=", 'foo bar') bar.save! end.to raise_error(NoMethodError) end @@ -122,7 +122,7 @@ let(:bar) { Bar.new(attr_name => 'foo bar') } it 'can be written' do - bar.send("#{attr_name}=", 'new foo bar') + bar.send(:"#{attr_name}=", 'new foo bar') bar.save! bar_found = Bar.find(bar.id) @@ -161,7 +161,7 @@ end it 'responds to writer method' do - expect(bar.respond_to?("#{attr_name}=")).to be true + expect(bar.respond_to?(:"#{attr_name}=")).to be true end end @@ -173,7 +173,7 @@ end it 'does not respond to writer method' do - expect(bar.respond_to?("#{attr_name}=")).to be false + expect(bar.respond_to?(:"#{attr_name}=")).to be false end end end diff --git a/spec/mongoid/attributes_spec.rb b/spec/mongoid/attributes_spec.rb index d84a2934f..d16ab9d24 100644 --- a/spec/mongoid/attributes_spec.rb +++ b/spec/mongoid/attributes_spec.rb @@ -2650,7 +2650,7 @@ let(:doc) { NestedBook.create! } before do - doc.send("#{meth}_cover", attrs) + doc.send(:"#{meth}_cover", attrs) end it 'updates the attributes' do diff --git a/spec/mongoid/clients_spec.rb b/spec/mongoid/clients_spec.rb index fa87dac6a..1091b7c1b 100644 --- a/spec/mongoid/clients_spec.rb +++ b/spec/mongoid/clients_spec.rb @@ -1194,4 +1194,48 @@ class StoreChild2 < StoreParent end end end + + describe '#disconnect' do + + let(:clients) do + described_class.clients.values + end + + before do + Band.all.entries + end + + it 'disconnects from all active clients' do + clients.each do |client| + expect(client).to receive(:close).and_call_original + end + described_class.disconnect + end + + it 'returns true' do + expect(described_class.disconnect).to be(true) + end + end + + describe '#reconnect' do + + let(:clients) do + described_class.clients.values + end + + before do + Band.all.entries + end + + it 'reconnects all active clients' do + clients.each do |client| + expect(client).to receive(:reconnect).and_call_original + end + described_class.reconnect + end + + it 'returns true' do + expect(described_class.reconnect).to be(true) + end + end end diff --git a/spec/mongoid/config/defaults_spec.rb b/spec/mongoid/config/defaults_spec.rb index 2b9624672..54e597b66 100644 --- a/spec/mongoid/config/defaults_spec.rb +++ b/spec/mongoid/config/defaults_spec.rb @@ -26,6 +26,8 @@ it 'uses settings for 8.1' do expect(Mongoid.immutable_ids).to be false expect(Mongoid.legacy_persistence_context_behavior).to be true + expect(Mongoid.around_callbacks_for_embeds).to be true + expect(Mongoid.prevent_multiple_calls_of_embedded_callbacks).to be false end end @@ -33,6 +35,8 @@ it 'does not use settings for 8.1' do expect(Mongoid.immutable_ids).to be true expect(Mongoid.legacy_persistence_context_behavior).to be false + expect(Mongoid.around_callbacks_for_embeds).to be false + expect(Mongoid.prevent_multiple_calls_of_embedded_callbacks).to be true end end diff --git a/spec/mongoid/contextual/none_spec.rb b/spec/mongoid/contextual/none_spec.rb index ef8990de2..ef733ca39 100644 --- a/spec/mongoid/contextual/none_spec.rb +++ b/spec/mongoid/contextual/none_spec.rb @@ -188,7 +188,7 @@ describe "##{meth}!" do it 'raises an error' do expect do - context.send("#{meth}!") + context.send(:"#{meth}!") end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Band./) end end diff --git a/spec/mongoid/criteria/queryable/selectable_logical_spec.rb b/spec/mongoid/criteria/queryable/selectable_logical_spec.rb index 4833c08bd..a0a1dea18 100644 --- a/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +++ b/spec/mongoid/criteria/queryable/selectable_logical_spec.rb @@ -1664,7 +1664,7 @@ # Date instance is converted to a Time instance in local time, # because we are querying on a Time field and dates are interpreted # in local time when assigning to Time fields - { 'published' => { '$gt' => Time.local(2020, 2, 3) } } + { 'published' => { '$gt' => Time.zone.local(2020, 2, 3) } } ] }) end @@ -2531,7 +2531,7 @@ # Date instance is converted to a Time instance in local time, # because we are querying on a Time field and dates are interpreted # in local time when assigning to Time fields - { 'published' => { '$gt' => Time.local(2020, 2, 3) } } + { 'published' => { '$gt' => Time.zone.local(2020, 2, 3) } } ] }) end diff --git a/spec/mongoid/document_persistence_context_spec.rb b/spec/mongoid/document_persistence_context_spec.rb index baf2e2fe6..fcff8ee18 100644 --- a/spec/mongoid/document_persistence_context_spec.rb +++ b/spec/mongoid/document_persistence_context_spec.rb @@ -39,28 +39,28 @@ config_override :legacy_persistence_context_behavior, false it 'remembers its persistence context when created' do - expect(person.collection_name).to be == :extra_people + expect(person.collection_name).to eq :extra_people end it 'remembers its context when queried specifically' do person_by_id = Person.with(options) { Person.find(_id: person._id) } - expect(person_by_id.collection_name).to be == :extra_people + expect(person_by_id.collection_name).to eq :extra_people end it 'remembers its context when queried generally' do person # force the person to be created person_generally = Person.with(options) { Person.all[0] } - expect(person_generally.collection_name).to be == :extra_people + expect(person_generally.collection_name).to eq :extra_people end it 'can be reloaded without specifying the context' do expect { person.reload }.to_not raise_error - expect(person.collection_name).to be == :extra_people + expect(person.collection_name).to eq :extra_people end it 'can be updated without specifying the context' do person.update username: 'zyg15' - expect(Person.with(options) { Person.first.username }).to be == 'zyg15' + expect(Person.with(options) { Person.first.username }).to eq 'zyg15' end it 'an explicit context takes precedence over a remembered context when persisting' do @@ -81,18 +81,18 @@ config_override :legacy_persistence_context_behavior, true it 'does not remember its persistence context when created' do - expect(person.collection_name).to be == :people + expect(person.collection_name).to eq :people end it 'does not remember its context when queried specifically' do person_by_id = Person.with(options) { Person.find(_id: person._id) } - expect(person_by_id.collection_name).to be == :people + expect(person_by_id.collection_name).to eq :people end it 'does not remember its context when queried generally' do person # force the person to be created person_generally = Person.with(options) { Person.all[0] } - expect(person_generally.collection_name).to be == :people + expect(person_generally.collection_name).to eq :people end it 'cannot be reloaded without specifying the context' do @@ -101,7 +101,7 @@ it 'cannot be updated without specifying the context' do person.update username: 'zyg15' - expect(Person.with(options) { Person.first.username }).to be == 'zyg14' + expect(Person.with(options) { Person.first.username }).to eq 'zyg14' end end end diff --git a/spec/mongoid/extensions/object_spec.rb b/spec/mongoid/extensions/object_spec.rb index 3855117d0..6b37bb48e 100644 --- a/spec/mongoid/extensions/object_spec.rb +++ b/spec/mongoid/extensions/object_spec.rb @@ -22,13 +22,6 @@ end end - describe '#__mongoize_time__' do - - it 'returns self' do - expect(object.__mongoize_time__).to eq(object) - end - end - describe '.demongoize' do let(:object) do diff --git a/spec/mongoid/extensions/time_spec.rb b/spec/mongoid/extensions/time_spec.rb index 48da3a422..82393ce79 100644 --- a/spec/mongoid/extensions/time_spec.rb +++ b/spec/mongoid/extensions/time_spec.rb @@ -7,7 +7,7 @@ describe '.demongoize' do let!(:time) do - Time.local(2010, 11, 19) + Time.zone.local(2010, 11, 19) end context 'when the time zone is not defined' do @@ -21,7 +21,7 @@ it 'returns the local time' do expect(Time.demongoize(time).utc_offset).to eq( - Time.local(2010, 11, 19).utc_offset + Time.zone.local(2010, 11, 19).utc_offset ) end end @@ -40,7 +40,7 @@ context 'when we have a time close to midnight' do let(:time) do - Time.local(2010, 11, 19, 0, 30).utc + Time.zone.local(2010, 11, 19, 0, 30).utc end it 'changes it back to the equivalent local time' do @@ -321,7 +321,7 @@ describe '.mongoize' do let!(:time) do - Time.local(2010, 11, 19) + Time.zone.local(2010, 11, 19) end context 'when given nil' do @@ -607,7 +607,7 @@ end it 'converts to a utc time' do - expect(Time.mongoize(date)).to eq(Time.local(date.year, date.month, date.day)) + expect(Time.mongoize(date)).to eq(Time.zone.local(date.year, date.month, date.day)) end it 'has a zero utc offset' do @@ -634,7 +634,7 @@ end it 'returns a time' do - expect(Time.mongoize(array)).to eq(Time.local(*array)) + expect(Time.mongoize(array)).to eq(Time.zone.local(*array)) end context 'when setting ActiveSupport time zone' do @@ -652,11 +652,11 @@ describe '#mongoize' do let!(:time) do - Time.local(2010, 11, 19) + Time.zone.local(2010, 11, 19) end let!(:eom_time) do - Time.local(2012, 11, 30, 23, 59, 59, 999999.999) + Time.zone.local(2012, 11, 30, 23, 59, 59, 999999.999) end let!(:eom_time_mongoized) do diff --git a/spec/mongoid/extensions/time_with_zone_spec.rb b/spec/mongoid/extensions/time_with_zone_spec.rb index b54f7d6a2..1f5b6d418 100644 --- a/spec/mongoid/extensions/time_with_zone_spec.rb +++ b/spec/mongoid/extensions/time_with_zone_spec.rb @@ -7,7 +7,7 @@ describe '.demongoize' do let!(:time) do - Time.local(2010, 11, 19) + Time.zone.local(2010, 11, 19) end context 'when the time zone is not defined' do @@ -21,7 +21,7 @@ it 'returns the local time' do expect(ActiveSupport::TimeWithZone.demongoize(time).utc_offset).to eq( - Time.local(2010, 11, 19).utc_offset + Time.zone.local(2010, 11, 19).utc_offset ) end end @@ -40,7 +40,7 @@ context 'when we have a time close to midnight' do let(:time) do - Time.local(2010, 11, 19, 0, 30).utc + Time.zone.local(2010, 11, 19, 0, 30).utc end it 'changes it back to the equivalent local time' do @@ -135,7 +135,7 @@ describe '.mongoize' do let!(:time) do - Time.local(2010, 11, 19) + Time.zone.local(2010, 11, 19) end context 'when given nil' do @@ -170,7 +170,7 @@ it 'returns a local date from the string' do expect(ActiveSupport::TimeWithZone.mongoize(time.to_s)).to eq( - Time.local(time.year, time.month, time.day, time.hour, time.min, time.sec) + Time.zone.local(time.year, time.month, time.day, time.hour, time.min, time.sec) ) end end @@ -274,7 +274,7 @@ end it 'converts to a utc time' do - expect(ActiveSupport::TimeWithZone.mongoize(date)).to eq(Time.local(date.year, date.month, date.day)) + expect(ActiveSupport::TimeWithZone.mongoize(date)).to eq(Time.zone.local(date.year, date.month, date.day)) end it 'has a zero utc offset' do @@ -301,7 +301,7 @@ end it 'returns a time' do - expect(ActiveSupport::TimeWithZone.mongoize(array)).to eq(Time.local(*array)) + expect(ActiveSupport::TimeWithZone.mongoize(array)).to eq(Time.zone.local(*array)) end context 'when setting ActiveSupport time zone' do @@ -319,7 +319,7 @@ describe '#mongoize' do let!(:time) do - Time.local(2010, 11, 19) + Time.zone.local(2010, 11, 19) end it 'converts to a utc time' do diff --git a/spec/mongoid/fields_spec.rb b/spec/mongoid/fields_spec.rb index 5c0158ac6..07fb36b25 100644 --- a/spec/mongoid/fields_spec.rb +++ b/spec/mongoid/fields_spec.rb @@ -575,7 +575,7 @@ end it 'is declared as BSON::Decimal128' do - expect(Mop.fields['decimal128_field'].type).to be == BSON::Decimal128 + expect(Mop.fields['decimal128_field'].type).to eq BSON::Decimal128 end context 'when BSON version <= 4' do diff --git a/spec/mongoid/inspectable_spec.rb b/spec/mongoid/inspectable_spec.rb index d9306555e..b166998cb 100644 --- a/spec/mongoid/inspectable_spec.rb +++ b/spec/mongoid/inspectable_spec.rb @@ -83,4 +83,84 @@ end end end + + describe '#pretty_inspect' do + + context 'when not allowing dynamic fields' do + + let(:person) do + Person.new(title: 'CEO') + end + + let(:pretty_inspected) do + person.pretty_inspect + end + + it 'includes the model type' do + expect(pretty_inspected).to include('#\n" + end + end + end end diff --git a/spec/mongoid/interceptable_spec_models.rb b/spec/mongoid/interceptable_spec_models.rb index 7bad8f01b..9276c55f3 100644 --- a/spec/mongoid/interceptable_spec_models.rb +++ b/spec/mongoid/interceptable_spec_models.rb @@ -20,15 +20,15 @@ module CallbackTracking whens = %i[before after] %i[validation save create update].each do |what| whens.each do |whn| - send("#{whn}_#{what}", :"#{whn}_#{what}_stub") - define_method("#{whn}_#{what}_stub") do + send(:"#{whn}_#{what}", :"#{whn}_#{what}_stub") + define_method(:"#{whn}_#{what}_stub") do callback_registry&.record_call(self.class, :"#{whn}_#{what}") end end next if what == :validation - send("around_#{what}", :"around_#{what}_stub") - define_method("around_#{what}_stub") do |&block| + send(:"around_#{what}", :"around_#{what}_stub") + define_method(:"around_#{what}_stub") do |&block| callback_registry&.record_call(self.class, :"around_#{what}_open") block.call callback_registry&.record_call(self.class, :"around_#{what}_close") diff --git a/spec/mongoid/monkey_patches_spec.rb b/spec/mongoid/monkey_patches_spec.rb index 883be9c41..47aee17ca 100644 --- a/spec/mongoid/monkey_patches_spec.rb +++ b/spec/mongoid/monkey_patches_spec.rb @@ -45,7 +45,6 @@ __intersect_from_array__ __intersect_from_object__ __mongoize_object_id__ - __mongoize_time__ __union__ __union_from_object__ ivar @@ -58,6 +57,7 @@ Array => %i[ __evolve_date__ __evolve_time__ + __mongoize_time__ __sort_option__ __sort_pair__ delete_one @@ -69,15 +69,18 @@ Date => %i[ __evolve_date__ __evolve_time__ + __mongoize_time__ ], DateTime => %i[ __evolve_date__ __evolve_time__ + __mongoize_time__ ], FalseClass => %i[is_a?], Float => %i[ __evolve_date__ __evolve_time__ + __mongoize_time__ ], Hash => %i[ __sort_option__ @@ -85,6 +88,7 @@ Integer => %i[ __evolve_date__ __evolve_time__ + __mongoize_time__ ], Module => %i[ re_define_method @@ -106,6 +110,7 @@ __evolve_time__ __expr_part__ __mongo_expression__ + __mongoize_time__ __sort_option__ before_type_cast? collectionize @@ -154,10 +159,12 @@ Time => %i[ __evolve_date__ __evolve_time__ + __mongoize_time__ ], ActiveSupport::TimeWithZone => %i[ __evolve_date__ __evolve_time__ + __mongoize_time__ _bson_to_i ], BSON::Decimal128 => %i[ diff --git a/spec/mongoid/search_indexable_spec.rb b/spec/mongoid/search_indexable_spec.rb index d86db9fd0..69e86d249 100644 --- a/spec/mongoid/search_indexable_spec.rb +++ b/spec/mongoid/search_indexable_spec.rb @@ -85,7 +85,7 @@ def filter_results(result, names) context 'when search indexes have been defined' do it 'has search index specs' do - expect(model.search_index_specs).to be == [ + expect(model.search_index_specs).to eq [ { definition: { mappings: { dynamic: false } } }, { name: 'with_dynamic_mappings', definition: { mappings: { dynamic: true } } } ] @@ -101,7 +101,7 @@ def filter_results(result, names) describe '.create_search_indexes' do it 'creates the indexes' do - expect(actual_definitions).to be == requested_definitions + expect(actual_definitions).to eq requested_definitions end end @@ -111,7 +111,7 @@ def filter_results(result, names) let(:queried_definitions) { model.search_indexes.pluck('latestDefinition') } it 'queries the available search indexes' do - expect(queried_definitions).to be == requested_definitions + expect(queried_definitions).to eq requested_definitions end end diff --git a/spec/mongoid/warnings_spec.rb b/spec/mongoid/warnings_spec.rb index 1735d1bbb..85dd62923 100644 --- a/spec/mongoid/warnings_spec.rb +++ b/spec/mongoid/warnings_spec.rb @@ -16,19 +16,19 @@ before do warn_id = id described_class.class_eval do - instance_variable_set("@#{warn_id}", false) + instance_variable_set(:"@#{warn_id}", false) end end it 'logs the warning' do expect_any_instance_of(Logger).to receive(:warn).once.with(message) - described_class.send("warn_#{id}") + described_class.send(:"warn_#{id}") end it 'logs the warning only once' do expect_any_instance_of(Logger).to receive(:warn).once.with(message) - described_class.send("warn_#{id}") - described_class.send("warn_#{id}") + described_class.send(:"warn_#{id}") + described_class.send(:"warn_#{id}") end end end diff --git a/spec/mongoid_spec.rb b/spec/mongoid_spec.rb index cc469b2d4..0fde18879 100644 --- a/spec/mongoid_spec.rb +++ b/spec/mongoid_spec.rb @@ -80,6 +80,32 @@ end described_class.disconnect_clients end + + it 'returns true' do + expect(described_class.disconnect_clients).to be(true) + end + end + + describe '.reconnect_clients' do + + let(:clients) do + Mongoid::Clients.clients.values + end + + before do + Band.all.entries + end + + it 'reconnects all active clients' do + clients.each do |client| + expect(client).to receive(:reconnect).and_call_original + end + described_class.reconnect_clients + end + + it 'returns true' do + expect(described_class.reconnect_clients).to be(true) + end end describe '.client' do diff --git a/spec/support/immutable_ids.rb b/spec/support/immutable_ids.rb index b35379c67..5cd072593 100644 --- a/spec/support/immutable_ids.rb +++ b/spec/support/immutable_ids.rb @@ -43,7 +43,7 @@ def immutable_id_examples_as(name) it 'allows _id to be updated' do invoke_operation! expect(object.new_record?).to be false - expect(object.reload._id).to be == new_id_value + expect(object.reload._id).to eq new_id_value end end @@ -66,7 +66,7 @@ def immutable_id_examples_as(name) it 'allows _id to be updated' do invoke_operation! expect(object.new_record?).to be false - expect(parent.reload.favorites.first._id).to be == new_id_value + expect(parent.reload.favorites.first._id).to eq new_id_value end end @@ -92,7 +92,7 @@ def immutable_id_examples_as(name) new_id = BSON::ObjectId.new expect { parent.update(pet: { _id: new_id }) }.to_not raise_error - expect(parent.reload.pet._id.to_s).to be == original_id.to_s + expect(parent.reload.pet._id.to_s).to eq original_id.to_s end end diff --git a/spec/support/macros.rb b/spec/support/macros.rb index a99b331ef..fb615cad6 100644 --- a/spec/support/macros.rb +++ b/spec/support/macros.rb @@ -22,11 +22,11 @@ def config_override(key, value) around do |example| existing = Mongoid.send(key) - Mongoid.send("#{key}=", value) + Mongoid.send(:"#{key}=", value) example.run - Mongoid.send("#{key}=", existing) + Mongoid.send(:"#{key}=", existing) end end @@ -44,11 +44,11 @@ def driver_config_override(key, value) around do |example| existing = Mongo.send(key) - Mongo.send("#{key}=", value) + Mongo.send(:"#{key}=", value) example.run - Mongo.send("#{key}=", existing) + Mongo.send(:"#{key}=", existing) end end @@ -96,9 +96,9 @@ def persistence_context_override(component, value) around do |example| meth = "#{component}_override" old_value = Mongoid::Threaded.send(meth) - Mongoid::Threaded.send("#{meth}=", value) + Mongoid::Threaded.send(:"#{meth}=", value) example.run - Mongoid::Threaded.send("#{meth}=", old_value) + Mongoid::Threaded.send(:"#{meth}=", old_value) end end