From 128f2a9ecad3e8743aae4536b9d79f788e148f45 Mon Sep 17 00:00:00 2001 From: Johnny Shields Date: Sat, 24 Jul 2021 17:41:25 +0900 Subject: [PATCH] Add rubocop + add Github Actions (#67) * Add rubocop and fix rubocop items * Replace Travis CI with Github Actions * Fix specs * Fix specs + more rubies * Enforce mongoid less than 7.3 --- .github/workflows/test.yml | 49 ++++++++++++++++++++ .rubocop.yml | 48 ++++++++++++++++++++ .rubocop_todo.yml | 20 ++++++++ .travis.yml | 20 -------- Gemfile | 2 + Rakefile | 16 ++++--- lib/mongoid-paranoia.rb | 4 +- lib/mongoid/paranoia.rb | 63 ++++++++++++++------------ lib/mongoid/paranoia/configuration.rb | 2 + lib/mongoid/paranoia/monkey_patches.rb | 7 +-- lib/mongoid/paranoia/version.rb | 4 +- lib/mongoid_paranoia.rb | 4 +- mongoid_paranoia.gemspec | 15 +++--- perf/scope.rb | 41 +++++++++-------- spec/spec_helper.rb | 46 +++---------------- 15 files changed, 213 insertions(+), 128 deletions(-) create mode 100644 .github/workflows/test.yml create mode 100644 .rubocop.yml create mode 100644 .rubocop_todo.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..6fe2244 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,49 @@ +name: CI RSpec Test + +on: [push, pull_request] + +jobs: + build: + name: >- + ${{ matrix.ruby }} + env: + CI: true + TESTOPTS: -v + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental }} + strategy: + fail-fast: true + matrix: + ruby: [2.4, 2.5, 2.6, 2.7, 3.0, jruby, truffleruby] + experimental: [false] + include: + - ruby: head + experimental: true + - ruby: jruby-head + experimental: true + - ruby: truffleruby-head + experimental: true + + steps: + - name: repo checkout + uses: actions/checkout@v2 + + - name: start mongodb + uses: supercharge/mongodb-github-action@1.6.0 + with: + mongodb-version: 4.4 + mongodb-replica-set: rs0 + + - name: load ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler: 2 + + - name: bundle install + run: bundle install --jobs 4 --retry 3 + + - name: test + timeout-minutes: 10 + run: bundle exec rake spec + continue-on-error: ${{ matrix.experimental }} diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..655a681 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,48 @@ +inherit_from: .rubocop_todo.yml + +AllCops: + NewCops: enable + SuggestExtensions: false + TargetRubyVersion: 2.6 + Exclude: + - spec/**/* + - vendor/**/* + +Bundler/DuplicatedGem: + Exclude: + - 'Gemfile' + +Gemspec/RequiredRubyVersion: + Enabled: false + +Layout/EmptyLineAfterGuardClause: + Enabled: false + +Layout/IndentationWidth: + IgnoredPatterns: + - '^\s*module' + +Layout/LineLength: + Max: 120 + +Layout/SpaceInsideBlockBraces: + SpaceBeforeBlockParameters: false + +Naming/FileName: + Exclude: + - 'lib/mongoid-paranoia.rb' + +Style/Documentation: + Enabled: false + +Style/DocumentDynamicEvalDefinition: + Enabled: false + +Style/DoubleNegation: + Enabled: false + +Style/OptionalBooleanParameter: + Enabled: false + +Style/RaiseArgs: + EnforcedStyle: compact diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 0000000..2d6db8f --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,20 @@ +Metrics/AbcSize: + Enabled: false + +Metrics/BlockLength: + Enabled: false + +Metrics/ClassLength: + Enabled: false + +Metrics/CyclomaticComplexity: + Enabled: false + +Metrics/MethodLength: + Enabled: false + +Metrics/ModuleLength: + Enabled: false + +Metrics/PerceivedComplexity: + Enabled: false diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index d7b5426..0000000 --- a/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -language: ruby -sudo: false -rvm: - - 2.3.8 - - 2.4.6 - - 2.5.5 - - 2.6.2 - - jruby-9.2.6.0 - -env: - global: - # --dev improves JRuby startup time - # See https://github.com/jruby/jruby/wiki/Improving-startup-time - - JRUBY_OPTS="--dev" - -gemfile: - - Gemfile - -services: -- mongodb diff --git a/Gemfile b/Gemfile index 24ab869..14a03ed 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + source 'https://rubygems.org' gemspec name: 'mongoid_paranoia' diff --git a/Rakefile b/Rakefile index b14e2b4..92e9c5c 100644 --- a/Rakefile +++ b/Rakefile @@ -1,14 +1,16 @@ -require "bundler" +# frozen_string_literal: true + +require 'bundler' Bundler.setup Bundler::GemHelper.install_tasks -require "rspec/core/rake_task" -require "rake" +require 'rspec/core/rake_task' +require 'rake' -$LOAD_PATH.unshift File.expand_path("../lib", __FILE__) +$LOAD_PATH.unshift File.expand_path('lib', __dir__) -RSpec::Core::RakeTask.new("spec") do |spec| - spec.pattern = "spec/**/*_spec.rb" +RSpec::Core::RakeTask.new('spec') do |spec| + spec.pattern = 'spec/**/*_spec.rb' end -task :default => :spec +task default: :spec diff --git a/lib/mongoid-paranoia.rb b/lib/mongoid-paranoia.rb index 9e172c9..b8d3c3d 100644 --- a/lib/mongoid-paranoia.rb +++ b/lib/mongoid-paranoia.rb @@ -1 +1,3 @@ -require "mongoid/paranoia" +# frozen_string_literal: true + +require 'mongoid/paranoia' diff --git a/lib/mongoid/paranoia.rb b/lib/mongoid/paranoia.rb index 2dc51e5..7a5aa8e 100644 --- a/lib/mongoid/paranoia.rb +++ b/lib/mongoid/paranoia.rb @@ -1,11 +1,11 @@ -# encoding: utf-8 +# frozen_string_literal: true + require 'mongoid/paranoia/monkey_patches' require 'mongoid/paranoia/configuration' require 'active_support' require 'active_support/deprecation' module Mongoid - # Include this module to get soft deletion of root level documents. # This will add a deleted_at field to the +Document+, managed automatically. # Potentially incompatible with unique indices. (if collisions with deleted items) @@ -20,25 +20,23 @@ module Paranoia extend ActiveSupport::Concern class << self - attr_accessor :configuration - end - - def self.configuration - @configuration ||= Configuration.new - end + def configuration + @configuration ||= Configuration.new + end - def self.reset - @configuration = Configuration.new - end + def reset + @configuration = Configuration.new + end - # Allow the paranoid +Document+ to use an alternate field name for deleted_at. - # - # @example - # Mongoid::Paranoia.configure do |c| - # c.paranoid_field = :myFieldName - # end - def self.configure - yield(configuration) + # Allow the paranoid +Document+ to use an alternate field name for deleted_at. + # + # @example + # Mongoid::Paranoia.configure do |c| + # c.paranoid_field = :myFieldName + # end + def configure + yield(configuration) + end end included do @@ -97,7 +95,13 @@ def persisted? alias orig_remove :remove def remove(_ = {}) - return false unless catch(:abort) { apply_delete_dependencies! } + return false unless catch(:abort) do + if respond_to?(:apply_destroy_dependencies!) + apply_destroy_dependencies! + else + apply_delete_dependencies! + end + end time = self.deleted_at = Time.now _paranoia_update('$set' => { paranoid_field => time }) @destroyed = true @@ -129,7 +133,7 @@ def delete! def destroyed? (@destroyed ||= false) || !!deleted_at end - alias :deleted? :destroyed? + alias deleted? destroyed? # Restores a previously soft-deleted document. Handles this by removing the # deleted_at flag. @@ -146,8 +150,8 @@ def destroyed? # @since 1.0.0 def restore(opts = {}) run_callbacks(:restore) do - _paranoia_update("$unset" => { paranoid_field => true }) - attributes.delete("deleted_at") + _paranoia_update('$unset' => { paranoid_field => true }) + attributes.delete('deleted_at') @destroyed = false restore_relations if opts[:recursive] true @@ -160,13 +164,12 @@ def to_param end def restore_relations - self.relations.each_pair do |name, association| + relations.each_pair do |name, association| next unless association.dependent == :destroy - relation = self.send(name) - if relation.present? && relation.paranoid? - Array.wrap(relation).each do |doc| - doc.restore(:recursive => true) - end + relation = send(name) + next unless relation.present? && relation.paranoid? + Array.wrap(relation).each do |doc| + doc.restore(recursive: true) end end end @@ -180,7 +183,7 @@ def restore_relations # # @return [ Collection ] The root collection. def paranoid_collection - embedded? ? _root.collection : self.collection + embedded? ? _root.collection : collection end # Get the field to be used for paranoid operations. diff --git a/lib/mongoid/paranoia/configuration.rb b/lib/mongoid/paranoia/configuration.rb index abc8628..9c57c3e 100644 --- a/lib/mongoid/paranoia/configuration.rb +++ b/lib/mongoid/paranoia/configuration.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Mongoid module Paranoia class Configuration diff --git a/lib/mongoid/paranoia/monkey_patches.rb b/lib/mongoid/paranoia/monkey_patches.rb index 731b7b0..76163c3 100644 --- a/lib/mongoid/paranoia/monkey_patches.rb +++ b/lib/mongoid/paranoia/monkey_patches.rb @@ -1,4 +1,5 @@ -# encoding: utf-8 +# frozen_string_literal: true + module Mongoid module Paranoia module Document @@ -14,7 +15,7 @@ module Document end end -Mongoid::Document.send(:include, Mongoid::Paranoia::Document) +Mongoid::Document.include Mongoid::Paranoia::Document module Mongoid module Association @@ -38,7 +39,7 @@ def destroy(parent, relation, doc) if !doc.embedded? || parent.new_record? || doc.paranoid? destroy_document(relation, doc) else - parent.flagged_destroys.push(->{ destroy_document(relation, doc) }) + parent.flagged_destroys.push(-> { destroy_document(relation, doc) }) end end end diff --git a/lib/mongoid/paranoia/version.rb b/lib/mongoid/paranoia/version.rb index eaa8304..9a7bcde 100644 --- a/lib/mongoid/paranoia/version.rb +++ b/lib/mongoid/paranoia/version.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + module Mongoid module Paranoia - VERSION = '0.4.0'.freeze + VERSION = '0.4.0' end end diff --git a/lib/mongoid_paranoia.rb b/lib/mongoid_paranoia.rb index 9e172c9..b8d3c3d 100644 --- a/lib/mongoid_paranoia.rb +++ b/lib/mongoid_paranoia.rb @@ -1 +1,3 @@ -require "mongoid/paranoia" +# frozen_string_literal: true + +require 'mongoid/paranoia' diff --git a/mongoid_paranoia.gemspec b/mongoid_paranoia.gemspec index 49bd15d..41e39a4 100644 --- a/mongoid_paranoia.gemspec +++ b/mongoid_paranoia.gemspec @@ -1,5 +1,6 @@ -# -*- encoding: utf-8 -*- -$:.push File.expand_path('../lib', __FILE__) +# frozen_string_literal: true + +$LOAD_PATH.push File.expand_path('lib', __dir__) require 'mongoid/paranoia/version' Gem::Specification.new do |gem| @@ -7,14 +8,16 @@ Gem::Specification.new do |gem| gem.version = Mongoid::Paranoia::VERSION gem.authors = ['Durran Jordan', 'Josef Šimánek'] gem.email = ['durran@gmail.com', 'retro@ballgag.cz'] - gem.description = %q{There may be times when you don't want documents to actually get deleted from the database, but "flagged" as deleted. Mongoid provides a Paranoia module to give you just that.} - gem.summary = %q{Paranoid documents} + gem.description = 'Provides a Paranoia module documents which soft-deletes documents.' + gem.summary = 'Paranoid documents' gem.homepage = 'https://github.com/simi/mongoid-paranoia' gem.license = 'MIT' - gem.files = Dir.glob('lib/**/*') + %w(LICENSE README.md) + gem.files = Dir.glob('lib/**/*') + %w[LICENSE README.md] gem.test_files = Dir.glob('{perf,spec}/**/*') gem.require_paths = ['lib'] - gem.add_dependency 'mongoid', '~> 7.0' + gem.add_dependency 'mongoid', '>= 7.0', '< 7.3' + + gem.add_development_dependency 'rubocop', '>= 1.8.1' end diff --git a/perf/scope.rb b/perf/scope.rb index 0c0b94d..4f369a6 100644 --- a/perf/scope.rb +++ b/perf/scope.rb @@ -1,9 +1,10 @@ +# frozen_string_literal: true + require 'bundler/setup' require 'mongoid' require 'mongoid/paranoia' require 'benchmark' - Mongoid.configure do |config| config.connect_to('my_little_test') end @@ -12,7 +13,7 @@ class Model include Mongoid::Document field :text, type: String - index({ text: "text" }) + index({ text: 'text' }) end class ParanoidModel @@ -20,7 +21,7 @@ class ParanoidModel include Mongoid::Paranoia field :text, type: String - index({ text: "text" }) + index({ text: 'text' }) end class MetaParanoidModel @@ -29,7 +30,7 @@ class MetaParanoidModel field :deleted_at, type: Time default_scope -> { where(deleted_at: nil) } - index({ text: "text" }) + index({ text: 'text' }) end if ENV['FORCE'] @@ -37,28 +38,28 @@ class MetaParanoidModel ::Mongoid::Tasks::Database.create_indexes n = 50_000 - n.times {|i| Model.create(text: "text #{i}")} - n.times {|i| ParanoidModel.create(text: "text #{i}")} - n.times {|i| MetaParanoidModel.create(text: "text #{i}")} + n.times {|i| Model.create(text: "text #{i}") } + n.times {|i| ParanoidModel.create(text: "text #{i}") } + n.times {|i| MetaParanoidModel.create(text: "text #{i}") } end n = 100 -puts "text_search benchmark ***" +puts 'text_search benchmark ***' Benchmark.bm(20) do |x| - x.report("without") { n.times { Model.text_search("text").execute } } - x.report("with") { n.times { ParanoidModel.text_search("text").execute } } - x.report("meta") { n.times { MetaParanoidModel.text_search("text").execute } } - x.report("unscoped meta") { n.times { MetaParanoidModel.unscoped.text_search("text").execute } } - x.report("unscoped paranoid") { n.times { ParanoidModel.unscoped.text_search("text").execute } } + x.report('without') { n.times { Model.text_search('text').execute } } + x.report('with') { n.times { ParanoidModel.text_search('text').execute } } + x.report('meta') { n.times { MetaParanoidModel.text_search('text').execute } } + x.report('unscoped meta') { n.times { MetaParanoidModel.unscoped.text_search('text').execute } } + x.report('unscoped paranoid') { n.times { ParanoidModel.unscoped.text_search('text').execute } } end -puts "" -puts "Pluck all ids benchmark ***" +puts '' +puts 'Pluck all ids benchmark ***' Benchmark.bm(20) do |x| - x.report("without") { n.times { Model.all.pluck(:id) } } - x.report("with") { n.times { ParanoidModel.all.pluck(:id) } } - x.report("meta") { n.times { MetaParanoidModel.all.pluck(:id) } } - x.report("unscoped meta") { n.times { MetaParanoidModel.unscoped.all.pluck(:id) } } - x.report("unscoped paranoid") { n.times { ParanoidModel.unscoped.all.pluck(:id) } } + x.report('without') { n.times { Model.all.pluck(:id) } } + x.report('with') { n.times { ParanoidModel.all.pluck(:id) } } + x.report('meta') { n.times { MetaParanoidModel.all.pluck(:id) } } + x.report('unscoped meta') { n.times { MetaParanoidModel.unscoped.all.pluck(:id) } } + x.report('unscoped paranoid') { n.times { ParanoidModel.unscoped.all.pluck(:id) } } end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 75c1232..766ed66 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,33 +1,16 @@ $LOAD_PATH.unshift(File.dirname(__FILE__)) -$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib")) +$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) -require "mongoid" -require "mongoid/paranoia" -require "rspec" - -# These environment variables can be set if wanting to test against a database -# that is not on the local machine. -ENV["MONGOID_SPEC_HOST"] ||= "localhost" -ENV["MONGOID_SPEC_PORT"] ||= "27017" - -# These are used when creating any connection in the test suite. -HOST = ENV["MONGOID_SPEC_HOST"] -PORT = ENV["MONGOID_SPEC_PORT"].to_i - -# Moped.logger.level = Logger::DEBUG -# Mongoid.logger.level = Logger::DEBUG +require 'mongoid' +require 'mongoid/paranoia' +require 'rspec' # When testing locally we use the database named mongoid_test. However when # tests are running in parallel on Travis we need to use different database # names for each process running since we do not have transactions and want a # clean slate before each spec run. def database_id - "mongoid_test" -end - -# Can we connect to MongoHQ from this box? -def mongohq_connectable? - ENV["MONGOHQ_REPL_PASS"].present? + 'mongoid_paranoia_test' end # Set the database that the spec suite connects to. @@ -36,16 +19,6 @@ def mongohq_connectable? config.connect_to(database_id) end -module Rails - class Application - end -end - -module MyApp - class Application < Rails::Application - end -end - RSpec.configure do |config| # Drop all collections @@ -61,15 +34,10 @@ class Application < Rails::Application config.after(:all) do Mongoid.purge! end - - # Filter out MongoHQ specs if we can't connect to it. - config.filter_run_excluding(config: ->(value){ - return true if value == :mongohq && !mongohq_connectable? - }) end ActiveSupport::Inflector.inflections do |inflect| - inflect.singular("address_components", "address_component") + inflect.singular('address_components', 'address_component') end -Dir[File.join(File.dirname(__FILE__), "app/models/*.rb")].each{ |f| require f } +Dir[File.join(File.dirname(__FILE__), 'app/models/*.rb')].each{ |f| require f }