From 165859247cd679e4894e88a21d351927b68fe6f9 Mon Sep 17 00:00:00 2001 From: Alexey Blinov Date: Fri, 25 Apr 2014 17:39:24 +0400 Subject: [PATCH] validate_absence_of: cast `@attribute` to String ActiveRecord.columns_hash returns Hash with String keys. This is why `it { expect(offer).to validate_absence_of(:expired_at) }` is not working. --- NEWS.md | 5 ++- .../validate_absence_of_matcher.rb | 8 +++-- .../validate_absence_of_matcher_spec.rb | 33 +++++++++++++++++-- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/NEWS.md b/NEWS.md index f0445cbc..41bae71e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -24,6 +24,9 @@ the record had to be persisted in order for the matcher to work. Now this is no longer the case and the record can remain unpersisted. +* Fix `validate_absence_of`: it required that a string be passed as the + attribute name rather than a symbol (which is the usual and documented usage). + ### Improvements * `have_and_belongs_to_many` now checks to make sure that the join table @@ -140,7 +143,7 @@ * Change `validate_uniqueness_of(...)` so that it provides default values for non-nullable attributes. -* Running `rake` now installs Appraisals before running the test suite. +* Running `rake` now installs Appraisals before running the test suite. (Additionally, we now manage Appraisals using the `appraisal` executable in Appraisal 1.0.0.) diff --git a/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb b/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb index 0bdf364e..ee9059a0 100644 --- a/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +++ b/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb @@ -82,8 +82,10 @@ module Shoulda else obj end - elsif attribute_class == Fixnum + elsif [Fixnum, Float].include?(attribute_class) 1 + elsif attribute_class == BigDecimal + BigDecimal.new(1, 0) elsif !attribute_class || attribute_class == String 'an arbitrary value' else @@ -93,8 +95,8 @@ module Shoulda def attribute_class @subject.class.respond_to?(:columns_hash) && - @subject.class.columns_hash[@attribute].respond_to?(:klass) && - @subject.class.columns_hash[@attribute].klass + @subject.class.columns_hash[@attribute.to_s].respond_to?(:klass) && + @subject.class.columns_hash[@attribute.to_s].klass end def collection? diff --git a/spec/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb b/spec/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb index 56384173..98bab047 100644 --- a/spec/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +++ b/spec/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb @@ -2,6 +2,21 @@ require 'spec_helper' describe Shoulda::Matchers::ActiveModel::ValidateAbsenceOfMatcher do if active_model_4_0? + def self.available_column_types + [ + :string, + :text, + :integer, + :float, + :decimal, + :datetime, + :timestamp, + :time, + :date, + :binary + ] + end + context 'a model with an absence validation' do it 'accepts' do expect(validating_absence_of(:attr)).to validate_absence_of(:attr) @@ -10,6 +25,15 @@ describe Shoulda::Matchers::ActiveModel::ValidateAbsenceOfMatcher do it 'does not override the default message with a present' do expect(validating_absence_of(:attr)).to validate_absence_of(:attr).with_message(nil) end + + available_column_types.each do |type| + context "when column is of type #{type}" do + it "accepts" do + expect(validating_absence_of(:attr, {}, type: type)). + to validate_absence_of(:attr) + end + end + end end context 'a model without an absence validation' do @@ -95,9 +119,12 @@ describe Shoulda::Matchers::ActiveModel::ValidateAbsenceOfMatcher do end end - def validating_absence_of(attr, options = {}) - define_model :example, attr => :string do - validates_absence_of attr, options + def validating_absence_of(attr, validation_options = {}, given_column_options = {}) + default_column_options = { type: :string, options: {} } + column_options = default_column_options.merge(given_column_options) + + define_model :example, attr => column_options do + validates_absence_of attr, validation_options end.new end