diff --git a/lib/db_nazi.rb b/lib/db_nazi.rb index 26b6b62..daf09a8 100644 --- a/lib/db_nazi.rb +++ b/lib/db_nazi.rb @@ -2,6 +2,7 @@ module DBNazi autoload :AbstractAdapter, 'db_nazi/abstract_adapter' autoload :Migration, 'db_nazi/migration' autoload :MigrationProxy, 'db_nazi/migration_proxy' + autoload :Table, 'db_nazi/table' autoload :TableDefinition, 'db_nazi/table_definition' autoload :VERSION, 'db_nazi/version' @@ -55,6 +56,25 @@ def reset self.require_varchar_limits = true self.require_index_uniqueness = true end + + def check_column(type, options) + if DBNazi.enabled?(:require_nullability) && type != :primary_key + options.key?(:null) or + raise NullabilityRequired, "[db_nazi] :null parameter required" + end + if DBNazi.enabled?(:require_varchar_limits) + # AR calls #to_sym on type, so do the same here. + type.to_sym == :string && !options.key?(:limit) and + raise VarcharLimitRequired, "[db_nazi] string column requires :limit parameter" + end + end + + def check_index(options) + if DBNazi.enabled?(:require_index_uniqueness) + options.key?(:unique) or + raise IndexUniquenessRequired, "[db_nazi] :unique parameter required" + end + end end reset @@ -62,5 +82,6 @@ def reset ActiveRecord::ConnectionAdapters::AbstractAdapter.__send__ :include, DBNazi::AbstractAdapter ActiveRecord::ConnectionAdapters::TableDefinition.__send__ :include, DBNazi::TableDefinition +ActiveRecord::ConnectionAdapters::Table.__send__ :include, DBNazi::Table ActiveRecord::Migration.__send__ :include, DBNazi::Migration ActiveRecord::MigrationProxy.__send__ :include, DBNazi::MigrationProxy diff --git a/lib/db_nazi/abstract_adapter.rb b/lib/db_nazi/abstract_adapter.rb index b938cbd..a19a985 100644 --- a/lib/db_nazi/abstract_adapter.rb +++ b/lib/db_nazi/abstract_adapter.rb @@ -15,15 +15,18 @@ def new(*) module Adapter def add_column(table_name, column_name, type, options = {}) - nazi_column_options(type, options) + DBNazi.check_column(type, options) super end def add_index(table_name, column_name, options = {}) - if DBNazi.enabled?(:require_index_uniqueness) - options.key?(:unique) or - raise IndexUniquenessRequired, "[db_nazi] :unique parameter required" - end + DBNazi.check_index(options) + super + end + + def change_column(table_name, column_name, type, options = {}) + DBNazi.check_column(type, options) + super end def create_table(name, *) @@ -33,23 +36,6 @@ def create_table(name, *) super end end - - def change_column(table_name, column_name, type, options = {}) - nazi_column_options(type, options) - super - end - - def nazi_column_options(type, options) - if DBNazi.enabled?(:require_nullability) - options.key?(:null) or - raise NullabilityRequired, "[db_nazi] :null parameter required" - end - if DBNazi.enabled?(:require_varchar_limits) - # AR calls #to_sym on type, so do the same here. - type.to_sym == :string && !options.key?(:limit) and - raise VarcharLimitRequired, "[db_nazi] string column requires :limit parameter" - end - end end end end diff --git a/lib/db_nazi/table.rb b/lib/db_nazi/table.rb new file mode 100644 index 0000000..734740d --- /dev/null +++ b/lib/db_nazi/table.rb @@ -0,0 +1,26 @@ +module DBNazi + module Table + def self.included(base) + base.class_eval do + alias_method_chain :column, :db_nazi + alias_method_chain :index, :db_nazi + alias_method_chain :change, :db_nazi + end + end + + def column_with_db_nazi(column_name, type, options = {}) + DBNazi.check_column(type, options) + column_without_db_nazi(column_name, type, options) + end + + def index_with_db_nazi(column_name, options = {}) + DBNazi.check_index(options) + index_without_db_nazi(column_name, options) + end + + def change_with_db_nazi(column_name, type, options = {}) + DBNazi.check_column(type, options) + change_without_db_nazi(column_name, type, options) + end + end +end diff --git a/lib/db_nazi/table_definition.rb b/lib/db_nazi/table_definition.rb index 04146dc..db3c381 100644 --- a/lib/db_nazi/table_definition.rb +++ b/lib/db_nazi/table_definition.rb @@ -8,15 +8,7 @@ def self.included(base) end def column_with_db_nazi(name, type, options = {}) - if DBNazi.enabled?(:require_nullability) && type != :primary_key - options.key?(:null) or - raise NullabilityRequired, "[db_nazi] :null parameter required" - end - if DBNazi.enabled?(:require_varchar_limits) - # AR calls #to_sym on type, so do the same here. - type.to_sym == :string && !options.key?(:limit) and - raise VarcharLimitRequired, "[db_nazi] string column requires :limit parameter" - end + DBNazi.check_column(type, options) column_without_db_nazi(name, type, options) end end diff --git a/test/unit/db_nazi/test_table.rb b/test/unit/db_nazi/test_table.rb new file mode 100644 index 0000000..0535010 --- /dev/null +++ b/test/unit/db_nazi/test_table.rb @@ -0,0 +1,189 @@ +require_relative '../../test_helper' + +describe DBNazi::TableDefinition do + use_database + + before do + DBNazi.reset + end + + describe "#column" do + before do + connection.create_table 'test_table' + end + + describe "when nullability is required" do + use_attribute_value DBNazi, :require_nullability, true + + it "raises a DBNazi::NullabilityRequired if :null is not specified" do + connection.change_table 'test_table', bulk: true do |t| + lambda do + t.column 'test_column', :boolean + end.must_raise(DBNazi::NullabilityRequired) + end + end + + it "does not raise a DBNazi::NullabilityRequired if :null is true" do + connection.change_table 'test_table', bulk: true do |t| + t.column 'test_column', :boolean, null: true + end + end + + it "does not raise a DBNazi::NullabilityRequired if :null is false" do + connection.change_table 'test_table', bulk: true do |t| + t.column 'test_column', :boolean, null: false, default: false + end + end + end + + describe "when nullability is not required" do + use_attribute_value DBNazi, :require_nullability, false + + it "does not raise a DBNazi::NullabilityRequired if :null is not specified" do + connection.change_table 'test_table', bulk: true do |t| + t.column 'test_column', :boolean + end + end + end + + describe "when varchar limits are required" do + use_attribute_value DBNazi, :require_varchar_limits, true + + it "raises a DBNazi::VarcharLimitRequired if :limit is not specified for a :string column" do + connection.change_table 'test_table', bulk: true do |t| + lambda do + t.column 'test_column', :string, null: true + end.must_raise(DBNazi::VarcharLimitRequired) + end + end + + it "does not raise a DBNazi::VarcharLimitRequired if :limit is specified for a :string column" do + connection.change_table 'test_table', bulk: true do |t| + t.column 'test_column', :string, limit: 255, null: true + end + end + end + + describe "when varchar limits are not required" do + use_attribute_value DBNazi, :require_varchar_limits, false + + it "does not raise a DBNazi::VarcharLimitRequired if :limit is not specified for a :string column" do + connection.change_table 'test_table', bulk: true do |t| + t.column 'test_column', :string, null: true + end + end + end + end + + describe "#index" do + before do + connection.create_table 'test_table' do |t| + t.column 'test_column', :boolean, null: true + end + end + + describe "when index uniqueness is required" do + use_attribute_value DBNazi, :require_index_uniqueness, true + + it "raises a DBNazi::IndexUniquenessRequired if :unique is not specified for an index" do + connection.change_table 'test_table', bulk: true do |t| + lambda do + t.index 'test_column' + end.must_raise(DBNazi::IndexUniquenessRequired) + end + end + + it "does not raise a DBNazi::IndexUniquenessRequired if :unique is true for an index" do + connection.change_table 'test_table', bulk: true do |t| + t.index 'test_column', unique: true + end + end + + it "does not raise a DBNazi::IndexUniquenessRequired if :unique is false for an index" do + connection.change_table 'test_table', bulk: true do |t| + t.index 'test_column', unique: false + end + end + end + + describe "when index uniqueness is not required" do + use_attribute_value DBNazi, :require_index_uniqueness, false + + it "does not raise a DBNazi::IndexUniquenessRequired if :unique is not specified for an index" do + connection.change_table 'test_table', bulk: true do |t| + t.index 'test_column' + end + end + end + end + + describe "#change" do + before do + connection.create_table 'test_table' do |t| + t.column 'test_column', :boolean, null: true + end + end + + describe "when nullability is required" do + use_attribute_value DBNazi, :require_nullability, true + + it "raises a DBNazi::NullabilityRequired if :null is not specified" do + connection.change_table 'test_table', bulk: true do |t| + lambda do + t.change 'test_column', :boolean + end.must_raise(DBNazi::NullabilityRequired) + end + end + + it "does not raise a DBNazi::NullabilityRequired if :null is true" do + connection.change_table 'test_table', bulk: true do |t| + t.change 'test_column', :boolean, null: true + end + end + + it "does not raise a DBNazi::NullabilityRequired if :null is false" do + connection.change_table 'test_table', bulk: true do |t| + t.change 'test_column', :boolean, null: false, default: false + end + end + end + + describe "when nullability is not required" do + use_attribute_value DBNazi, :require_nullability, false + + it "does not raise a DBNazi::NullabilityRequired if :null is not specified" do + connection.change_table 'test_table', bulk: true do |t| + t.change 'test_column', :boolean + end + end + end + + describe "when varchar limits are required" do + use_attribute_value DBNazi, :require_varchar_limits, true + + it "raises a DBNazi::VarcharLimitRequired if :limit is not specified for a :string column" do + connection.change_table 'test_table', bulk: true do |t| + lambda do + t.change 'test_column', :string, null: true + end.must_raise(DBNazi::VarcharLimitRequired) + end + end + + it "does not raise a DBNazi::VarcharLimitRequired if :limit is specified for a :string column" do + connection.change_table 'test_table', bulk: true do |t| + t.change 'test_column', :string, limit: 255, null: true + end + end + end + + describe "when varchar limits are not required" do + use_attribute_value DBNazi, :require_varchar_limits, false + + it "does not raise a DBNazi::VarcharLimitRequired if :limit is not specified for a :string column" do + connection.change_table 'test_table', bulk: true do |t| + t.change 'test_column', :string, null: true + end + end + end + end +end diff --git a/test/unit/db_nazi/test_table_definition.rb b/test/unit/db_nazi/test_table_definition.rb index e5d205b..7fd0792 100644 --- a/test/unit/db_nazi/test_table_definition.rb +++ b/test/unit/db_nazi/test_table_definition.rb @@ -7,11 +7,11 @@ DBNazi.reset end - describe "nullability" do - describe "when it is required" do + describe "#column" do + describe "when nullability is required" do use_attribute_value DBNazi, :require_nullability, true - it "raises a DBNazi::NullabilityRequired if :null is not specified when adding a column" do + it "raises a DBNazi::NullabilityRequired if :null is not specified" do connection.create_table 'test_table' do |t| lambda do t.column 'test_column', :boolean @@ -19,32 +19,30 @@ end end - it "does not raise a DBNazi::NullabilityRequired if :null is true when adding a column" do + it "does not raise a DBNazi::NullabilityRequired if :null is true" do connection.create_table 'test_table' do |t| t.column 'test_column', :boolean, null: true end end - it "does not raise a DBNazi::NullabilityRequired if :null is false when adding a column" do + it "does not raise a DBNazi::NullabilityRequired if :null is false" do connection.create_table 'test_table' do |t| t.column 'test_column', :boolean, null: false, default: false end end end - describe "when it is not required" do + describe "when nullability is not required" do use_attribute_value DBNazi, :require_nullability, false - it "does not raise a DBNazi::NullabilityRequired if :null is not specified when adding a column" do + it "does not raise a DBNazi::NullabilityRequired if :null is not specified" do connection.create_table 'test_table' do |t| t.column 'test_column', :boolean end end end - end - describe "varchar limits" do - describe "when they are required" do + describe "when varchar limits are required" do use_attribute_value DBNazi, :require_varchar_limits, true it "raises a DBNazi::VarcharLimitRequired if :limit is not specified for a :string column" do @@ -62,7 +60,7 @@ end end - describe "when they are not required" do + describe "when varchar limits are not required" do use_attribute_value DBNazi, :require_varchar_limits, false it "does not raise a DBNazi::VarcharLimitRequired if :limit is not specified for a :string column" do