<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -1,4 +1,8 @@
 === 0.1.1 - 11.30.2008
 
+* New constraints: even, odd, format
+
+=== 0.1.1 - 11.30.2008
+
 * Added foreign key constraints support.
 * Added multi-column constraints support.</diff>
      <filename>CHANGELOG.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -103,6 +103,9 @@ Below is the list of constraints available and tested so far.
 * unique
 * exact_length
 * reference
+* even
+* odd
+* format
 
 == Extensibility
 
@@ -110,7 +113,6 @@ All constraints are located in the lib/constraints.rb. Extending this module wit
 
 == TODO
 
-* Add constraints with functionality corresponding to ActiveRecord validates_* pack
 * Create better API for adding constraints
 
 == License</diff>
      <filename>README.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -22,15 +22,7 @@ module SexyPgConstraints
     
     class &lt;&lt; self
       def add_constraints(table, column, constraints)
-        available_constraints = SexyPgConstraints::Constraints.methods - Object.methods
-        valid_constraints = constraints.reject { |k, v| !(available_constraints).include?(k.to_s) }
-        invalid_constraints = constraints.keys - valid_constraints.keys
-        
-        if invalid_constraints.size &gt; 0 
-          raise &quot;Invalid constraints specified: #{(invalid_constraints).join(',')}&quot;
-        end
-        
-        valid_constraints.each_pair do |type, options|
+        constraints.each_pair do |type, options|
           sql = &quot;alter table #{table} add constraint #{make_title(table, column, type)} &quot; + 
             SexyPgConstraints::Constraints.send(type, column, options) + ';'
           </diff>
      <filename>lib/constrainer.rb</filename>
    </modified>
    <modified>
      <diff>@@ -83,6 +83,26 @@ module SexyPgConstraints
     def positive(column, options)
       &quot;check (#{column} &gt; 0)&quot;
     end
+    
+    ## 
+    # Allow only odd values.
+    #
+    # Example:
+    #   constrain :books, :quantity, :odd =&gt; true
+    #
+    def odd(column, options)
+      &quot;check (mod(#{column}, 2) != 0)&quot;
+    end
+
+    ## 
+    # Allow only even values.
+    #
+    # Example:
+    #   constrain :books, :quantity, :even =&gt; true
+    #
+    def even(column, options)
+      &quot;check (mod(#{column}, 2) = 0)&quot;
+    end
 
     ## 
     # Make sure every entry in the column is unique.
@@ -106,6 +126,16 @@ module SexyPgConstraints
     end
     
     ## 
+    # Allow only values that match the regular expression.
+    #
+    # Example:
+    #   constrain :orders, :visa, :format =&gt; /^([4]{1})([0-9]{12,15})$/
+    #
+    def format(column, options)
+      &quot;check (((#{column})::text #{options.casefold? ? '~*' : '~'}  E'#{options.source}'::text ))&quot;
+    end
+    
+    ## 
     # Add foreign key constraint.
     #
     # Example:</diff>
      <filename>lib/constraints.rb</filename>
    </modified>
    <modified>
      <diff>@@ -248,6 +248,42 @@ class SexyPgConstraintsTest &lt; Test::Unit::TestCase
     end
   end
   
+  def test_odd
+    ActiveRecord::Migration.constrain :books, :quantity, :odd =&gt; true
+    
+    assert_prohibits :quantity, :odd do |book|
+      book.quantity = 2
+    end
+    
+    assert_allows do |book|
+      book.quantity = 1
+    end
+    
+    ActiveRecord::Migration.deconstrain :books, :quantity, :odd
+    
+    assert_allows do |book|
+      book.quantity = 2
+    end
+  end
+  
+  def test_even
+    ActiveRecord::Migration.constrain :books, :quantity, :even =&gt; true
+    
+    assert_prohibits :quantity, :even do |book|
+      book.quantity = 1
+    end
+    
+    assert_allows do |book|
+      book.quantity = 2
+    end
+    
+    ActiveRecord::Migration.deconstrain :books, :quantity, :even
+    
+    assert_allows do |book|
+      book.quantity = 1
+    end
+  end
+  
   def test_unique
     ActiveRecord::Migration.constrain :books, :isbn, :unique =&gt; true
     
@@ -288,6 +324,50 @@ class SexyPgConstraintsTest &lt; Test::Unit::TestCase
     end
   end
   
+  def test_format_case_insensitive
+    ActiveRecord::Migration.constrain :books, :title, :format =&gt; /^[a-z]+$/i
+    
+    assert_prohibits :title, :format do |book|
+      book.title = 'abc3'
+    end
+    
+    assert_prohibits :title, :format do |book|
+      book.title = ''
+    end
+    
+    assert_allows do |book|
+      book.title = 'abc'
+    end
+    
+    assert_allows do |book|
+      book.title = 'ABc'
+    end
+    
+    ActiveRecord::Migration.deconstrain :books, :title, :format
+    
+    assert_allows do |book|
+      book.title = 'abc3'
+    end
+  end
+  
+  def test_format_case_sensitive
+    ActiveRecord::Migration.constrain :books, :title, :format =&gt; /^[a-z]+$/
+    
+    assert_prohibits :title, :format do |book|
+      book.title = 'aBc'
+    end
+    
+    assert_allows do |book|
+      book.title = 'abc'
+    end
+    
+    ActiveRecord::Migration.deconstrain :books, :title, :format
+    
+    assert_allows do |book|
+      book.title = 'aBc'
+    end
+  end
+  
   def test_reference
     ActiveRecord::Migration.constrain :books, :author_id, :reference =&gt; {:authors =&gt; :id}
     </diff>
      <filename>test/sexy_pg_constraints_test.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>c89718862510a87fd2038400c9771fe06a90c149</id>
    </parent>
  </parents>
  <author>
    <name>Maxim Chernyak</name>
    <email>max@bitsonnet.com</email>
  </author>
  <url>http://github.com/maxim/sexy_pg_constraints/commit/74bf8f02dbef6ed67e9460ffbf67e107dd292fe4</url>
  <id>74bf8f02dbef6ed67e9460ffbf67e107dd292fe4</id>
  <committed-date>2008-11-30T13:20:37-08:00</committed-date>
  <authored-date>2008-11-30T13:20:37-08:00</authored-date>
  <message>New constraints: even, odd, format.</message>
  <tree>55f2fdb9f894dc35e9a597a3be470751d036eb47</tree>
  <committer>
    <name>Maxim Chernyak</name>
    <email>max@bitsonnet.com</email>
  </committer>
</commit>
