Using the database schema to help validate data

I started working on this in response to Dave T.’ keynote as
RailsConf 2006. This little patch will validate that your text fields
will fit into the database. Obviously this is just a start, and many
more validations could be added. Also, this code could probably be
extracted into a plugin instead of patch to ActiveRecord.

Index: test/validations_test.rb

— test/validations_test.rb (revision 4495)
+++ test/validations_test.rb (working copy)
@@ -461,6 +461,13 @@
t.title = nil
assert t.valid?
end
+

  • def test_validates_database_schema

  • Topic.validates_database_schema

  • t = Topic.create(“title” => “a” * 256, “content” => “whatever”)

  • assert !t.valid?, “validation should have failed because the title
    is too long”

  • end

    def test_validates_length_of_using_maximum
    Topic.validates_length_of :title, :maximum => 5
    Index: lib/active_record/validations.rb
    ===================================================================
    — lib/active_record/validations.rb (revision 4491)
    +++ lib/active_record/validations.rb (working copy)
    @@ -250,6 +250,21 @@
    write_inheritable_set(:validate_on_update, methods)
    end

  •  def validates_database_schema()
    
  •    columns.each {|column|
    
  •      column.primary = column.name == primary_key
    
  •      # Setup default validation for text columns
    
  •      if column.text? then
    
  •        # varchars have a limit, while text columns generally do 
    

not

  •        if column.limit then
    
  •          # this is a hack for attributes which are reserved words 
    

like ‘type’

  •          name = "#{column.name}_before_type_cast"
    
  •          validates_length_of name, :maximum=>column.limit
    
  •        end
    
  •      end
    
  •    }
    
  •  end
    
  •  def condition_block?(condition)
       condition.respond_to?("call") && (condition.arity == 1 || 
    

condition.arity == -1)
end