#47 Ensure that the attribute's default value is set correctly. Examples... #95

Closed
wants to merge 1 commit into
from
Jump to file or symbol
Failed to load files and symbols.
+167 −1
Split
@@ -10,7 +10,7 @@
require 'shoulda/matchers/active_model/validate_acceptance_of_matcher'
require 'shoulda/matchers/active_model/validate_numericality_of_matcher'
require 'shoulda/matchers/active_model/allow_mass_assignment_of_matcher'
-
+require 'shoulda/matchers/active_model/have_a_default_matcher'
module Shoulda
module Matchers
@@ -0,0 +1,100 @@
+module Shoulda # :nodoc:
+ module Matchers
+ module ActiveModel # :nodoc:
+
+ # Ensures that the attribute's default value is set correctly.
+ #
+ # Example:
+ # # the :count field's default value is 0
+ # it { should have_a_default.of(0).for(:count) }
+ # it { should have_a_default.of(0).for(:count).column }
+ # it { should have_a_default.of(0).for(:count).attribute }
+ #
+ # # the :count field has a default value (e.g. it's default value is not nil)
+ # it { should have_a_default.for(:count) }
+ # it { should have_a_default.for(:count).column }
+ # it { should have_a_default.for(:count).attribute }
+ #
+ # # the :count field's default value is not 0
+ # it { should_not have_a_default.of(0).for(:count) }
+ # it { should_not have_a_default.of(0).for(:count).column }
+ # it { should_not have_a_default.of(0).for(:count).attribute }
+ #
+ # # the :count field does not have a default value (e.g. it's default value is nil)
+ # it { should_not have_a_default.for(:count) }
+ # it { should_not have_a_default.for(:count).column }
+ # it { should_not have_a_default.for(:count).attribute }
+ #
+ def have_a_default
+ HaveADefaultMatcher.new
+ end
+
+ # Same as have_a_default.of
+ #
+ # Example:
+ # # the :count field's default value is 0
+ # it { should default_to(0).on_the(:count).column }
+ # it { should default_to(0).on_the(:count).attribute }
+ #
+ # # the :count field's default value is not 0
+ # it { should_not default_to(0).on_the(:count).column }
+ # it { should_not default_to(0).on_the(:count).attribute }
+ #
+ def default_to(value)
+ have_a_default.of(value)
+ end
+
+ class HaveADefaultMatcher # :nodoc:
+
+ def of(value)
+ @default_value = value
+ self
+ end
+
+ def for(attribute)
+ @attribute = attribute
+ self
+ end
+ alias :on_the :for
+
+ def column
+ self #syntactic sugar
+ end
+ alias :attribute :column
+
+ def matches?(instance)
+ @instance = instance
+ @instance.valid?
+ @default_value.nil? ? value : value == @default_value

This comment has been minimized.

Show comment Hide comment
@gabebw

gabebw Apr 13, 2012

Contributor

I'm worried that this doesn't check for when people have a default value of false (e.g. boolean columns) but don't set an explicit @default_value. In those cases, value would be false, making this fail incorrectly.

What about this instead?

if @default_value.nil?  # test is just checking for any default value
  # Assume that people don't set NULL as a default value.  
  value != nil
else
  # Otherwise, check that the actual value and the expected value are the same.
  value == @default_value
end
@gabebw

gabebw Apr 13, 2012

Contributor

I'm worried that this doesn't check for when people have a default value of false (e.g. boolean columns) but don't set an explicit @default_value. In those cases, value would be false, making this fail incorrectly.

What about this instead?

if @default_value.nil?  # test is just checking for any default value
  # Assume that people don't set NULL as a default value.  
  value != nil
else
  # Otherwise, check that the actual value and the expected value are the same.
  value == @default_value
end
+ end
+
+ def failure_message
+ if @default_value
+ "Expected default value for #{@attribute} to be #{@default_value.inspect} but it was #{value.inspect} !"
+ else
+ "Expected to find a default value for #{@attribute} but there wasn't any !"
+ end
+ end
+
+ def negative_failure_message
+ if @default_value
+ "Expected default value for #{@attribute} not to be #{@default_value.inspect} but it was!"
+ else
+ "Not expecting to find a default value for #{@attribute} but found #{value.inspect}!"
+ end
+ end
+
+ def description
+ "check if the #{@attribute}'s default value is #{@default_value.inspect}"
+ end
+
+ private
+
+ def value
+ @instance.send(@attribute.to_sym)
+ end
+ end
+
+ end
+ end
+end
@@ -0,0 +1,66 @@
+require 'spec_helper'
+
+describe Shoulda::Matchers::ActiveModel::HaveADefaultMatcher do
+
+ context "an attribute with a default value" do
+ before do
+ define_model :example, :attr => :string do
+ before_validation :set_attr
+ def set_attr
+ self.attr = "abc" if attr.nil?
+ end

This comment has been minimized.

Show comment Hide comment
@mike-burns

mike-burns May 17, 2012

Owner

This is not the proper way to set a default value; instead you should set the default in the DB schema. Does this matcher work with that methodology?

@mike-burns

mike-burns May 17, 2012

Owner

This is not the proper way to set a default value; instead you should set the default in the DB schema. Does this matcher work with that methodology?

+ end
+ @model = Example.new
+ end
+
+ subject {@model}
+
+ describe "when testing with the right default value" do
+ it {should have_a_default.of("abc").for(:attr) }
+ it {should have_a_default.of("abc").for(:attr).column }
+ it {should have_a_default.of("abc").for(:attr).attribute}
+ it {should default_to("abc").on_the(:attr) }
+ it {should default_to("abc").on_the(:attr).column }
+ it {should default_to("abc").on_the(:attr).attribute }
+ end
+
+ describe "when testing for any default value" do
+ it {should have_a_default.for(:attr) }
+ it {should have_a_default.for(:attr).column }
+ it {should have_a_default.for(:attr).attribute}
+ end
+
+ describe "when testing with the wrong default value" do
+ it {should_not have_a_default.of("xyz").for(:attr) }
+ it {should_not have_a_default.of("xyz").for(:attr).column }
+ it {should_not have_a_default.of("xyz").for(:attr).attribute}
+ it {should_not default_to("xyz").on_the(:attr) }
+ it {should_not default_to("xyz").on_the(:attr).column }
+ it {should_not default_to("xyz").on_the(:attr).attribute }
+ end
+ end
+
+ context "an attribute without a default value" do
+ before do
+ define_model :example, :attr => :string
+ @model = Example.new
+ end
+
+ subject {@model}
+
+ describe "when testing for any default value" do
+ it {should_not have_a_default.for(:attr) }
+ it {should_not have_a_default.for(:attr).column }
+ it {should_not have_a_default.for(:attr).attribute}
+ end
+
+ describe "when testing with the wrong default value" do
+ it {should_not have_a_default.of("xyz").for(:attr) }
+ it {should_not have_a_default.of("xyz").for(:attr).column }
+ it {should_not have_a_default.of("xyz").for(:attr).attribute}
+ it {should_not default_to("xyz").on_the(:attr) }
+ it {should_not default_to("xyz").on_the(:attr).column }
+ it {should_not default_to("xyz").on_the(:attr).attribute }
+ end
+ end
+end