diff --git a/.codeclimate.yml b/.codeclimate.yml deleted file mode 100644 index dc2ef1a..0000000 --- a/.codeclimate.yml +++ /dev/null @@ -1,4 +0,0 @@ -plugins: - rubocop: - enabled: true - channel: rubocop-0-64 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5143295..0e0e8df 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,20 +11,22 @@ jobs: runs-on: ubuntu-latest strategy: + fail-fast: false + matrix: include: - - ruby: '2.7' - gemfile: rails61 - ruby: '3.0' gemfile: rails70 - ruby: '3.4' gemfile: rails80 + - ruby: '4.0' + gemfile: rails81 - ruby: '4.0' gemfile: railsmaster services: postgres: - image: postgres:9.6 + image: postgres env: POSTGRES_USER: root POSTGRES_DB: database_validations_test @@ -38,7 +40,7 @@ jobs: - 5432:5432 mysql: - image: mysql:5.6 + image: mysql env: MYSQL_ROOT_HOST: '%' MYSQL_ROOT_PASSWORD: test @@ -61,16 +63,14 @@ jobs: BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} bundler-cache: true - - - name: Use ${{ matrix.gemfile }} as the Gemfile - run: bundle config --global gemfile ${{ matrix.gemfile }} + bundler: latest - name: Run tests run: bundle exec rspec diff --git a/.github/workflows/rubocop.yml b/.github/workflows/rubocop.yml new file mode 100644 index 0000000..a48588c --- /dev/null +++ b/.github/workflows/rubocop.yml @@ -0,0 +1,26 @@ +name: Rubocop + +on: + push: + branches: [master, main] + pull_request: + +jobs: + rubocop: + runs-on: ubuntu-latest + + permissions: + contents: read + id-token: write + + steps: + - uses: actions/checkout@v6 + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + bundler-cache: true + + - name: Lint Ruby code with RuboCop + run: | + bundle exec rubocop diff --git a/.gitignore b/.gitignore index 3fbb65f..dd63538 100644 --- a/.gitignore +++ b/.gitignore @@ -22,5 +22,4 @@ example/log example/Gemfile.lock example/config/database.yml -.ruby-version .ruby-gemset diff --git a/.rubocop-todo.yml b/.rubocop-todo.yml index 0dbec72..c0e1f14 100644 --- a/.rubocop-todo.yml +++ b/.rubocop-todo.yml @@ -1,15 +1,18 @@ -Metrics/LineLength: +Layout/LineLength: Max: 140 Exclude: - 'benchmarks/*.rb' Metrics/MethodLength: Max: 15 + Exclude: + - Rakefile Metrics/BlockLength: Exclude: - 'spec/**/*_spec.rb' - 'benchmarks/*.rb' + - Rakefile Style/Documentation: Enabled: false @@ -30,3 +33,11 @@ Style/Semicolon: Style/NumericPredicate: Exclude: - 'benchmarks/*.rb' + +Style/MixinUsage: + Exclude: + - Rakefile + +RSpec/SpecFilePathFormat: + Exclude: + - spec/rubocop/**/*.rb diff --git a/.rubocop.yml b/.rubocop.yml index fc11137..6e40760 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,10 +1,12 @@ inherit_from: .rubocop-todo.yml -require: +plugins: - rubocop-rspec AllCops: + NewCops: disable + SuggestExtensions: false DisplayCopNames: true - TargetRubyVersion: 2.5 + TargetRubyVersion: 3.0 Include: - '**/*.rb' - 'Gemfile' @@ -24,3 +26,14 @@ Style/FrozenStringLiteralComment: RSpec/MultipleExpectations: Enabled: false + +Naming/VariableNumber: + Enabled: false + +RSpec/ExampleWording: + Enabled: false + + +Lint/ConstantDefinitionInBlock: + Exclude: + - 'benchmarks/*.rb' diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..2f4b607 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +3.4 diff --git a/CHANGELOG.md b/CHANGELOG.md index 1728425..9051f58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,14 @@ # Changelog -## [1.2.0] - 07-02-2025 +## [x.x.x] - DD-MM-YYY ### Improvements +- Add Rails 8.1 support +- Set minimum Ruby version to 3.0 +- Loosen gemspec development dependency version constraints +- Modernize CI configuration and add dedicated RuboCop workflow +- Consolidate database configuration into `config/database.yml` +- Add local development database setup with Docker Compose - Fix RuboCop integration. Thank to [Evgeny Matveyev](https://github.com/evgeny-matveev) for fixing it. ## [1.1.1] - 14-03-2022 @@ -38,7 +44,7 @@ ## [0.9.2] - 16-09-20 ### Improvements -- Fix a warning message from newest Ruby version +- Fix a warning message from newest Ruby version ## [0.9.1] - 24-06-20 ### Improvements @@ -56,14 +62,14 @@ ## [0.8.10] - 21-02-19 ### Improvements -- Internal improvements +- Internal improvements - We raise an error if `scope` or `where` options are missed for the `validates_db_uniqueness_of` ## [0.8.9] - 13-02-19 ### Bugs - Hot-fix for `validate_db_uniqueness_of` RSpec matcher -## (removed) [0.8.8] - 13-02-19 +## (removed) [0.8.8] - 13-02-19 ### Bugs - Hot-fix for `validates_db_uniqueness_of` @@ -89,7 +95,7 @@ ## [0.8.2] - 10-01-18 ### Bugs -- Fix RuboCop cop for `validates_db_uniqueness_of` to catch `validates_uniqueness_of` definition too. +- Fix RuboCop cop for `validates_db_uniqueness_of` to catch `validates_uniqueness_of` definition too. ## [0.8.1] - 09-01-18 ### Features @@ -97,7 +103,7 @@ ## [0.8.0] - 30-11-18 ### Features -- Add `db_belongs_to` +- Add `db_belongs_to` ## [0.7.3] - 2018-10-18 ### Features diff --git a/README.md b/README.md index b051f24..fdf00d9 100644 --- a/README.md +++ b/README.md @@ -214,7 +214,7 @@ if you want to skip it in some cases. (For example, when you run migrations.) _N The validation has an option `:rescue` with two values: - `:default` (default option) that follows default ActiveRecord behavior. It respects `validate: false` option for `save/save!` (for example, this is being used for nested associations) -- `:always` that catches database constraint errors and turns them to ActiveRecord validations filling `.errors` properly. +- `:always` that catches database constraint errors and turns them to ActiveRecord validations filling `.errors` properly. You may want to use `rescue: :always` in case you save nested associations with `accepts_nested_attributes_for` helper and you want the validation to happen automatically when a user provides duplicated data in the same request. @@ -270,10 +270,25 @@ require: ## Development -You need to have installed and running `postgresql` and `mysql`. -And for each adapter manually create a database called `database_validations_test` accessible by your local user. +The easiest way to get started is with Docker. A `docker-compose.yaml` is +included that runs PostgreSQL and MySQL with preconfigured test databases: -Then, run `rake spec` to run the tests. +```bash +docker compose up -d +``` + +Then create the test databases and run the specs: + +```bash +rake db:all:create +rake spec +``` + +To drop the test databases: + +```bash +rake db:all:drop +``` To check the conformance with the style guides, run: diff --git a/Rakefile b/Rakefile index 4c774a2..64a5939 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,59 @@ require 'bundler/gem_tasks' require 'rspec/core/rake_task' +require 'active_record' +require_relative 'config/database_config' RSpec::Core::RakeTask.new(:spec) task default: :spec + +DATABASE_CONFIGURATIONS = DatabaseConfig.load + +include ActiveRecord::Tasks + +DatabaseTasks.database_configuration = DATABASE_CONFIGURATIONS +DatabaseTasks.db_dir = 'db' +DatabaseTasks.migrations_paths = [] +DatabaseTasks.root = File.dirname(__FILE__) +DatabaseTasks.env = ENV.fetch('DB', 'postgresql') + +task :environment do + ActiveRecord::Base.configurations = DATABASE_CONFIGURATIONS + ActiveRecord::Base.establish_connection(DatabaseTasks.env.to_sym) +end + +load 'active_record/railties/databases.rake' + +namespace :db do + namespace :all do + desc 'Create both PostgreSQL and MySQL test databases' + task :create do + failures = [] + DATABASE_CONFIGURATIONS.each do |name, config| + next if config['adapter'] == 'sqlite3' + + puts "Creating #{name} database..." + ActiveRecord::Tasks::DatabaseTasks.create(config) + rescue StandardError => e + failures << name + warn " Failed to create #{name}: #{e.message}" + end + abort "Failed to create: #{failures.join(', ')}" if failures.any? + end + + desc 'Drop both PostgreSQL and MySQL test databases' + task :drop do + failures = [] + DATABASE_CONFIGURATIONS.each do |name, config| + next if config['adapter'] == 'sqlite3' + + puts "Dropping #{name} database..." + ActiveRecord::Tasks::DatabaseTasks.drop(config) + rescue StandardError => e + failures << name + warn " Failed to drop #{name}: #{e.message}" + end + abort "Failed to drop: #{failures.join(', ')}" if failures.any? + end + end +end diff --git a/config/database.yml b/config/database.yml new file mode 100644 index 0000000..bb258bb --- /dev/null +++ b/config/database.yml @@ -0,0 +1,17 @@ +postgresql: + adapter: postgresql + database: database_validations_test + host: <%= ENV['DB_HOST'] || '127.0.0.1' %> + username: <%= ENV['DB_USER'] || 'database_validations' %> + password: <%= ENV['DB_PASSWORD'] || 'database_validations' %> + +mysql: + adapter: mysql2 + database: database_validations_test + host: <%= ENV['DB_HOST'] || '127.0.0.1' %> + username: <%= ENV['DB_USER'] || 'root' %> + password: <%= ENV['DB_PASSWORD'] || 'database_validations' %> + +sqlite: + adapter: sqlite3 + database: ':memory:' diff --git a/config/database_config.rb b/config/database_config.rb new file mode 100644 index 0000000..fb0715e --- /dev/null +++ b/config/database_config.rb @@ -0,0 +1,12 @@ +require 'erb' +require 'yaml' + +module DatabaseConfig + def self.load(symbolize_keys: false) + yaml_path = File.expand_path('database.yml', __dir__) + yaml_content = ERB.new(File.read(yaml_path)).result + configs = YAML.safe_load(yaml_content) + configs = configs.transform_values { |v| v.transform_keys(&:to_sym) } if symbolize_keys + configs + end +end diff --git a/database_validations.gemspec b/database_validations.gemspec index b49f6e5..634dcf9 100644 --- a/database_validations.gemspec +++ b/database_validations.gemspec @@ -2,7 +2,7 @@ lib = File.expand_path('lib', __dir__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'database_validations/version' -Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength +Gem::Specification.new do |spec| spec.name = 'database_validations' spec.version = DatabaseValidations::VERSION spec.authors = ['Evgeniy Demin'] @@ -19,17 +19,18 @@ and ActiveRecord validations with better performance and consistency." spec.license = 'MIT' spec.files = Dir['lib/**/*'] spec.require_paths = ['lib'] + spec.required_ruby_version = '>= 3.0.0' - spec.add_dependency 'activerecord', '>= 4.2.0' + spec.add_dependency 'activerecord', '>= 7.0.0' - spec.add_development_dependency 'benchmark-ips', '~> 2.7' - spec.add_development_dependency 'bundler', '>= 2.0' - spec.add_development_dependency 'db-query-matchers', '>= 0.9' + spec.add_development_dependency 'benchmark-ips' + spec.add_development_dependency 'bundler' + spec.add_development_dependency 'db-query-matchers' spec.add_development_dependency 'mysql2' spec.add_development_dependency 'pg' - spec.add_development_dependency 'rake', '~> 13.0' - spec.add_development_dependency 'rspec', '~> 3.0' - spec.add_development_dependency 'rubocop', '~> 1.80' - spec.add_development_dependency 'rubocop-rspec', '~> 3.8' + spec.add_development_dependency 'rake' + spec.add_development_dependency 'rspec' + spec.add_development_dependency 'rubocop' + spec.add_development_dependency 'rubocop-rspec' spec.add_development_dependency 'sqlite3' end diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..a255387 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,27 @@ +services: + postgresql: + container_name: "database_validations_postgresql" + image: postgres + environment: + POSTGRES_USER: database_validations + POSTGRES_PASSWORD: database_validations + POSTGRES_DB: database_validations_test + ports: + - 5432:5432 + volumes: + - pgdata:/var/lib/postgresql + + mysql: + container_name: "database_validations_mysql" + image: mysql + environment: + MYSQL_ROOT_PASSWORD: database_validations + MYSQL_DATABASE: database_validations_test + ports: + - 3306:3306 + volumes: + - mysqldata:/var/lib/mysql + +volumes: + pgdata: + mysqldata: diff --git a/example/config/environments/production.rb b/example/config/environments/production.rb index 21f5d4e..69f124e 100644 --- a/example/config/environments/production.rb +++ b/example/config/environments/production.rb @@ -84,7 +84,7 @@ # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') if ENV['RAILS_LOG_TO_STDOUT'].present? - logger = ActiveSupport::Logger.new(STDOUT) + logger = ActiveSupport::Logger.new($stdout) logger.formatter = config.log_formatter config.logger = ActiveSupport::TaggedLogging.new(logger) end diff --git a/example/config/puma.rb b/example/config/puma.rb index f123039..7707dd9 100644 --- a/example/config/puma.rb +++ b/example/config/puma.rb @@ -4,12 +4,12 @@ # the maximum value specified for Puma. Default is set to 5 threads for minimum # and maximum; this matches the default thread size of Active Record. # -threads_count = ENV.fetch('RAILS_MAX_THREADS') { 5 } +threads_count = ENV.fetch('RAILS_MAX_THREADS', 5) threads threads_count, threads_count # Specifies the `port` that Puma will listen on to receive requests; default is 3000. # -port ENV.fetch('PORT') { 3000 } +port ENV.fetch('PORT', 3000) # Specifies the `environment` that Puma will run in. # diff --git a/example/db/schema.rb b/example/db/schema.rb index 50e3079..29881c1 100644 --- a/example/db/schema.rb +++ b/example/db/schema.rb @@ -10,35 +10,34 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2018_11_29_192039) do - +ActiveRecord::Schema.define(version: 20_181_129_192_039) do # These are extensions that must be enabled in order to support this database - enable_extension "plpgsql" + enable_extension 'plpgsql' - create_table "companies", force: :cascade do |t| - t.string "email" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table 'companies', force: :cascade do |t| + t.string 'email' + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false end - create_table "countries", force: :cascade do |t| - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table 'countries', force: :cascade do |t| + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false end - create_table "users", force: :cascade do |t| - t.string "email" - t.string "full_name" - t.bigint "company_id" - t.bigint "country_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["company_id"], name: "index_users_on_company_id" - t.index ["country_id"], name: "index_users_on_country_id" - t.index ["email"], name: "index_users_on_email", unique: true - t.index ["full_name"], name: "index_users_on_full_name", unique: true + create_table 'users', force: :cascade do |t| + t.string 'email' + t.string 'full_name' + t.bigint 'company_id' + t.bigint 'country_id' + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.index ['company_id'], name: 'index_users_on_company_id' + t.index ['country_id'], name: 'index_users_on_country_id' + t.index ['email'], name: 'index_users_on_email', unique: true + t.index ['full_name'], name: 'index_users_on_full_name', unique: true end - add_foreign_key "users", "companies" - add_foreign_key "users", "countries" + add_foreign_key 'users', 'companies' + add_foreign_key 'users', 'countries' end diff --git a/gemfiles/rails70.gemfile b/gemfiles/rails70.gemfile index fa49f4f..cc15713 100644 --- a/gemfiles/rails70.gemfile +++ b/gemfiles/rails70.gemfile @@ -1,5 +1,6 @@ source 'https://rubygems.org' -gem 'activerecord', '>= 7.0' +gem 'activerecord', '~> 7.0.0' +gem 'sqlite3', '~> 1.4' gemspec path: '../' diff --git a/gemfiles/rails80.gemfile b/gemfiles/rails80.gemfile index d204def..2e06186 100644 --- a/gemfiles/rails80.gemfile +++ b/gemfiles/rails80.gemfile @@ -1,5 +1,5 @@ source 'https://rubygems.org' -gem 'activerecord', '>= 8.0' +gem 'activerecord', '~> 8.0.0' gemspec path: '../' diff --git a/gemfiles/rails61.gemfile b/gemfiles/rails81.gemfile similarity index 62% rename from gemfiles/rails61.gemfile rename to gemfiles/rails81.gemfile index 33c1f97..30be048 100644 --- a/gemfiles/rails61.gemfile +++ b/gemfiles/rails81.gemfile @@ -1,5 +1,5 @@ source 'https://rubygems.org' -gem 'activerecord', '>= 6.1' +gem 'activerecord', '~> 8.1.0' gemspec path: '../' diff --git a/lib/database_validations/lib/checkers/db_uniqueness_validator.rb b/lib/database_validations/lib/checkers/db_uniqueness_validator.rb index 4f73c6e..702002c 100644 --- a/lib/database_validations/lib/checkers/db_uniqueness_validator.rb +++ b/lib/database_validations/lib/checkers/db_uniqueness_validator.rb @@ -40,8 +40,8 @@ def validate_indexes!(klass) # rubocop:disable Metrics/AbcSize validator.attributes.map do |attribute| columns = KeyGenerator.unify_columns(attribute, validator.options[:scope]) - index = validator.index_name ? adapter.find_unique_index_by_name(validator.index_name.to_s) : adapter.find_unique_index(columns, validator.where) # rubocop:disable Metrics/LineLength - raise Errors::IndexNotFound.new(columns, validator.where, validator.index_name, adapter.unique_indexes, adapter.table_name) unless index && valid_index?(columns, index) # rubocop:disable Metrics/LineLength + index = validator.index_name ? adapter.find_unique_index_by_name(validator.index_name.to_s) : adapter.find_unique_index(columns, validator.where) # rubocop:disable Layout/LineLength + raise Errors::IndexNotFound.new(columns, validator.where, validator.index_name, adapter.unique_indexes, adapter.table_name) unless index && valid_index?(columns, index) # rubocop:disable Layout/LineLength end end end diff --git a/lib/database_validations/lib/validators/db_presence_validator.rb b/lib/database_validations/lib/validators/db_presence_validator.rb index 1d177e8..cf939c0 100644 --- a/lib/database_validations/lib/validators/db_presence_validator.rb +++ b/lib/database_validations/lib/validators/db_presence_validator.rb @@ -61,7 +61,7 @@ def db_belongs_to(name, scope = nil, **options) belongs_to(name, scope, **options) - validates_with DatabaseValidations::DbPresenceValidator, _merge_attributes([name, message: DatabaseValidations::DbPresenceValidator::REFLECTION_MESSAGE]) # rubocop:disable Metrics/LineLength + validates_with DatabaseValidations::DbPresenceValidator, _merge_attributes([name, { message: DatabaseValidations::DbPresenceValidator::REFLECTION_MESSAGE }]) # rubocop:disable Layout/LineLength end end end diff --git a/spec/database_validations_spec.rb b/spec/database_validations_spec.rb index e35cedc..20378f3 100644 --- a/spec/database_validations_spec.rb +++ b/spec/database_validations_spec.rb @@ -1,5 +1,5 @@ RSpec.describe DatabaseValidations do it 'has a version number' do - expect(DatabaseValidations::VERSION).not_to be nil + expect(DatabaseValidations::VERSION).not_to be_nil end end diff --git a/spec/rubocop/cop/belongs_to_spec.rb b/spec/rubocop/cop/belongs_to_spec.rb index f9ec262..80b824b 100644 --- a/spec/rubocop/cop/belongs_to_spec.rb +++ b/spec/rubocop/cop/belongs_to_spec.rb @@ -1,6 +1,6 @@ require 'rubocop/spec_helper' -RSpec.describe RuboCop::Cop::DatabaseValidations::BelongsTo do # rubocop:disable RSpec/FilePath +RSpec.describe RuboCop::Cop::DatabaseValidations::BelongsTo do subject(:cop) { described_class.new } it 'detects `belongs_to`: true``' do diff --git a/spec/rubocop/cop/uniqueness_of_spec.rb b/spec/rubocop/cop/uniqueness_of_spec.rb index 39d147d..a1f2d3d 100644 --- a/spec/rubocop/cop/uniqueness_of_spec.rb +++ b/spec/rubocop/cop/uniqueness_of_spec.rb @@ -1,6 +1,6 @@ require 'rubocop/spec_helper' -RSpec.describe RuboCop::Cop::DatabaseValidations::UniquenessOf do # rubocop:disable RSpec/FilePath +RSpec.describe RuboCop::Cop::DatabaseValidations::UniquenessOf do subject(:cop) { described_class.new } it 'detects `uniqueness: true`' do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 35094b8..43975ac 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -2,6 +2,7 @@ require 'database_validations' require 'shared/raise_index_not_found' require 'db-query-matchers' +require_relative '../config/database_config' # Use this constant to enable Rails 5+ compatible specs RAILS_5 = ActiveRecord::VERSION::MAJOR >= 5 @@ -49,8 +50,12 @@ def define_class(parent = ActiveRecord::Base, table_name = :entities, &block) Class.new(parent) do |klass| self.table_name = table_name + def self.name + 'Temp' + end + def self.model_name - ActiveModel::Name.new(self, nil, 'temp') + ActiveModel::Name.new(self, nil, 'Temp') end reset_column_information @@ -65,29 +70,16 @@ def rescue_error e.message end +DATABASE_CONFIGURATIONS = DatabaseConfig.load(symbolize_keys: true) + def postgresql_configuration - { - adapter: 'postgresql', - database: 'database_validations_test', - host: ENV['DB_HOST'] || '127.0.0.1', - username: ENV['DB_USER'], - password: ENV['DB_PASSWORD'] - } + DATABASE_CONFIGURATIONS['postgresql'] end def mysql_configuration - { - adapter: 'mysql2', - database: 'database_validations_test', - host: ENV['DB_HOST'] || '127.0.0.1', - username: ENV['DB_USER'], - password: ENV['DB_PASSWORD'] - } + DATABASE_CONFIGURATIONS['mysql'] end def sqlite_configuration - { - adapter: 'sqlite3', - database: ':memory:' - } + DATABASE_CONFIGURATIONS['sqlite'] end diff --git a/spec/validations/db_belongs_to_spec.rb b/spec/validations/db_belongs_to_spec.rb index c5deaa1..2f3672b 100644 --- a/spec/validations/db_belongs_to_spec.rb +++ b/spec/validations/db_belongs_to_spec.rb @@ -1,7 +1,11 @@ RSpec.describe 'db_belongs_to' do - class Company < ActiveRecord::Base; end # rubocop:disable RSpec/LeakyConstantDeclaration - class BelongsUser < ActiveRecord::Base; end # rubocop:disable RSpec/LeakyConstantDeclaration - class DbBelongsUser < ActiveRecord::Base; end # rubocop:disable RSpec/LeakyConstantDeclaration + # rubocop:disable RSpec/LeakyConstantDeclaration + # rubocop:disable Lint/ConstantDefinitionInBlock + class Company < ActiveRecord::Base; end + class BelongsUser < ActiveRecord::Base; end + class DbBelongsUser < ActiveRecord::Base; end + # rubocop:enable RSpec/LeakyConstantDeclaration + # rubocop:enable Lint/ConstantDefinitionInBlock let(:company_klass) { define_class(Company, :companies) } @@ -59,7 +63,7 @@ def define_tables shared_examples 'works as belongs_to' do shared_examples 'with company_id provided' do |method, field, company_id| - context "#{method} on #{field} with #{company_id.inspect}" do + context "when '#{method}' on '#{field}' with '#{company_id.inspect}'" do specify do # Hack validate_db_queries = !(method == :valid? && [:existing_id, -1].include?(company_id)) diff --git a/spec/validations/validates_db_uniqueness_of_spec.rb b/spec/validations/validates_db_uniqueness_of_spec.rb index cf280b8..f0316d2 100644 --- a/spec/validations/validates_db_uniqueness_of_spec.rb +++ b/spec/validations/validates_db_uniqueness_of_spec.rb @@ -17,8 +17,8 @@ end it 'returns false' do - expect(db_uniqueness.new(persisted_attrs).valid?).to eq(false) - expect(app_uniqueness.new(persisted_attrs).valid?).to eq(false) + expect(db_uniqueness.new(persisted_attrs).valid?).to be(false) + expect(app_uniqueness.new(persisted_attrs).valid?).to be(false) end it 'has exactly the same errors' do @@ -233,7 +233,7 @@ def catch_error_message context 'when proc returns false' do let(:klass) do define_class do - validates_db_uniqueness_of :field, if: ->(entity) { entity.nil? } + validates_db_uniqueness_of :field, if: ->(entity) { entity.nil? } # rubocop:disable Style/SymbolProc end end @@ -315,7 +315,7 @@ def catch_error_message context 'when proc returns false' do let(:klass) do define_class do - validates_db_uniqueness_of :field, unless: ->(entity) { entity.nil? } + validates_db_uniqueness_of :field, unless: ->(entity) { entity.nil? } # rubocop:disable Style/SymbolProc end end @@ -390,8 +390,8 @@ def catch_error_message nil end expect(parent_class.count).to eq(0) - expect(new.persisted?).to eq(false) - expect(old.persisted?).to eq(false) + expect(new.persisted?).to be(false) + expect(old.persisted?).to be(false) end end @@ -466,13 +466,13 @@ def catch_error_message it_behaves_like 'ActiveRecord::Validation' - context do + context do # rubocop:disable RSpec/MissingExampleGroupArgument define_negated_matcher :not_change, :change before { parent_class.create!(persisted_attrs) } it "doesn't rescue from the constraint violation" do - expect_any_instance_of(ActiveRecord::Validations::UniquenessValidator) + expect_any_instance_of(ActiveRecord::Validations::UniquenessValidator) # rubocop:disable RSpec/AnyInstance .to receive(:scope_relation).twice.and_return(RAILS_5 ? app_uniqueness.none : '1=0') expect { app_uniqueness.create(persisted_attrs) } @@ -502,7 +502,7 @@ def catch_error_message it_behaves_like 'ActiveRecord::Validation' end - context 'when parent class set validation of flow' do + context 'when parent class set validation of flow' do # rubocop:disable RSpec/MultipleMemoizedHelpers before do define_table do |t| t.string :field @@ -715,8 +715,8 @@ def catch_error_message describe '#valid?' do it 'works' do - expect(db_uniqueness.new(persisted_attrs).valid?).to eq(true) - expect(app_uniqueness.new(persisted_attrs).valid?).to eq(true) + expect(db_uniqueness.new(persisted_attrs).valid?).to be(true) + expect(app_uniqueness.new(persisted_attrs).valid?).to be(true) end end