Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Three-State Boolean checker #189

Merged
merged 6 commits into from
Apr 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/database_consistency.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
require 'database_consistency/writers/simple/enum_values_inconsistent_with_ar_enum'
require 'database_consistency/writers/simple/enum_values_inconsistent_with_inclusion'
require 'database_consistency/writers/simple/redundant_case_insensitive_option'
require 'database_consistency/writers/simple/three_state_boolean'
require 'database_consistency/writers/simple_writer'

require 'database_consistency/writers/autofix/helpers/migration'
Expand Down Expand Up @@ -71,6 +72,7 @@
require 'database_consistency/checkers/column_checkers/length_constraint_checker'
require 'database_consistency/checkers/column_checkers/primary_key_type_checker'
require 'database_consistency/checkers/column_checkers/enum_value_checker'
require 'database_consistency/checkers/column_checkers/three_state_boolean_checker'

require 'database_consistency/checkers/validator_checkers/validator_checker'
require 'database_consistency/checkers/validator_checkers/missing_unique_index_checker'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# frozen_string_literal: true

module DatabaseConsistency
module Checkers
# This class checks missing NOT NULL constraint for boolean columns
class ThreeStateBooleanChecker < ColumnChecker
Report = ReportBuilder.define(
DatabaseConsistency::Report,
:table_name,
:column_name
)

private

def preconditions
column.type == :boolean
end

def check
if valid?
report_template(:ok)
else
report_template(:fail, error_slug: :three_state_boolean)
end
end

def report_template(status, error_slug: nil)
Report.new(
status: status,
error_slug: error_slug,
error_message: nil,
table_name: model.table_name,
column_name: column.name,
**report_attributes
)
end

# @return [Boolean]
def valid?
!column.null
end
end
end
end
3 changes: 2 additions & 1 deletion lib/database_consistency/processors/columns_processor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ class ColumnsProcessor < BaseProcessor
Checkers::NullConstraintChecker,
Checkers::LengthConstraintChecker,
Checkers::PrimaryKeyTypeChecker,
Checkers::EnumValueChecker
Checkers::EnumValueChecker,
Checkers::ThreeStateBooleanChecker
].freeze

private
Expand Down
3 changes: 2 additions & 1 deletion lib/database_consistency/writers/autofix_writer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ class AutofixWriter < BaseWriter
null_constraint_missing: Autofix::NullConstraintMissing,
redundant_index: Autofix::RedundantIndex,
redundant_unique_index: Autofix::RedundantIndex,
small_primary_key: Autofix::InconsistentTypes
small_primary_key: Autofix::InconsistentTypes,
three_state_boolean: Autofix::NullConstraintMissing
}.freeze

def write
Expand Down
22 changes: 22 additions & 0 deletions lib/database_consistency/writers/simple/three_state_boolean.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

module DatabaseConsistency
module Writers
module Simple
class ThreeStateBoolean < Base # :nodoc:
private

def template
'boolean column should have NOT NULL constraint'
end

def unique_attributes
{
table_name: report.table_name,
column_name: report.column_name
}
end
end
end
end
end
3 changes: 2 additions & 1 deletion lib/database_consistency/writers/simple_writer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ class SimpleWriter < BaseWriter
missing_foreign_key_cascade: Simple::MissingForeignKeyCascade,
enum_values_inconsistent_with_ar_enum: Simple::EnumValuesInconsistentWithArEnum,
enum_values_inconsistent_with_inclusion: Simple::EnumValuesInconsistentWithInclusion,
redundant_case_insensitive_option: Simple::RedundantCaseInsensitiveOption
redundant_case_insensitive_option: Simple::RedundantCaseInsensitiveOption,
three_state_boolean: Simple::ThreeStateBoolean
}.freeze

def write
Expand Down
93 changes: 93 additions & 0 deletions spec/checkers/three_state_boolean_checker_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# frozen_string_literal: true

RSpec.describe DatabaseConsistency::Checkers::ThreeStateBooleanChecker, :sqlite, :mysql, :postgresql do
subject(:checker) { described_class.new(model, column) }

let(:klass) { define_class }
let(:model) { klass }
let(:column) { klass.columns.first }

context 'when column is nullable and without default' do
before do
define_database_with_entity do |table|
table.boolean :active
end
end

specify do
expect(checker.report).to have_attributes(
checker_name: 'ThreeStateBooleanChecker',
table_or_model_name: klass.name,
column_or_attribute_name: 'active',
status: :fail,
error_message: nil,
error_slug: :three_state_boolean,
table_name: klass.table_name,
column_name: 'active'
)
end
end

context 'when column is not nullable and without default' do
before do
define_database_with_entity do |table|
table.boolean :active, null: false
end
end

specify do
expect(checker.report).to have_attributes(
checker_name: 'ThreeStateBooleanChecker',
table_or_model_name: klass.name,
column_or_attribute_name: 'active',
status: :ok,
error_message: nil,
error_slug: nil,
table_name: klass.table_name,
column_name: 'active'
)
end
end

context 'when column is nullable and with default' do
before do
define_database_with_entity do |table|
table.boolean :active, default: true
end
end

specify do
expect(checker.report).to have_attributes(
checker_name: 'ThreeStateBooleanChecker',
table_or_model_name: klass.name,
column_or_attribute_name: 'active',
status: :fail,
error_message: nil,
error_slug: :three_state_boolean,
table_name: klass.table_name,
column_name: 'active'
)
end
end

context 'when column is not nullable and with default' do
before do
define_database_with_entity do |table|
table.boolean :active, null: false, default: true
end
end

specify do
expect(checker.report).to have_attributes(
checker_name: 'ThreeStateBooleanChecker',
table_or_model_name: klass.name,
column_or_attribute_name: 'active',
status: :ok,
error_message: nil,
error_slug: nil,
table_name: klass.table_name,
column_name: 'active'
)
end
end
end