<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>spec/datatypes_spec.rb</filename>
    </added>
    <added>
      <filename>spec/marshal_spec.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,8 +1,11 @@
-== 0.2.4 / 2009-03-24
+== 0.2.4 / 2009-10-10
 
 - Features:
   - Doodle::XML::Element
     - defines class level #tag method to specify output tag name
+  - Refactored into separate files
+  - More specs (improved coverage)
+  - fixed some errors in datatypes
 
 == 0.2.3 / 2009-03-06
 </diff>
      <filename>History.txt</filename>
    </modified>
    <modified>
      <diff>@@ -29,7 +29,6 @@ class Doodle
         #DBG: Doodle::Debug.d { [:has, self, self.class, params] }
         if !params.key?(:name)
           __doodle__.handle_error name, ArgumentError, &quot;#{self.class} must have a name&quot;, Doodle::Utils.doodle_caller
-          params[:name] = :__ERROR_missing_name__
         else
           # ensure that :name is a symbol
           params[:name] = params[:name].to_sym
@@ -135,12 +134,12 @@ class Doodle
     end
 
     # temporarily fake existence of readonly attribute
-    def readonly
-      false
+    def readonly(tf)
+      @readonly = tf
     end
 
     # name of attribute
-    has :name, :kind =&gt; Symbol do
+    has :name, :kind =&gt; Symbol, :readonly =&gt; true do
       from String do |s|
         s.to_sym
       end</diff>
      <filename>lib/doodle/attribute.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,11 +1,9 @@
-$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
-$:.unshift(File.join(File.dirname(__FILE__), '.'))
-
+base_path = File.dirname(__FILE__)
 require 'doodle'
-
 require 'date'
+require 'time'
 require 'uri'
-require 'rfc822'
+require File.join(base_path, 'rfc822')
 
 # note: this doesn't have to be in Doodle namespace
 class Doodle
@@ -43,6 +41,7 @@ class Doodle
     end
 
     def integer(name, params = { }, &amp;block)
+      params = params.dup
       if params.key?(:max)
         max = params.delete(:max)
       end
@@ -59,12 +58,12 @@ class Doodle
         end
         if max
           must &quot;be &lt;= #{max}&quot; do |s|
-            s.size &lt;= max
+            s &lt;= max
           end
         end
         if min
           must &quot;be &gt;= #{min}&quot; do |s|
-            s.size &gt;= min
+            s &gt;= max
           end
         end
       end
@@ -88,7 +87,8 @@ class Doodle
           when /^(no|false|off|0)$/
             false
           else
-            v
+            # empty string &quot;&quot; is false by this definition
+            !v.empty?
           end
         end
       end
@@ -105,9 +105,13 @@ class Doodle
     def string(name, params = { }, &amp;block)
       # must extract non-standard attributes before processing with
       # datatype otherwise causes UnknownAttribute error in Attribute definition
+      params = params.dup
       if params.key?(:max)
         max = params.delete(:max)
       end
+      if params.key?(:min)
+        min = params.delete(:min)
+      end
       if params.key?(:size)
         size = params.delete(:size)
         # size should be a Range
@@ -128,8 +132,13 @@ class Doodle
             s.size &lt;= max
           end
         end
+        if min
+          must &quot;be &gt;= #{min} characters&quot; do |s|
+            s.size &gt;= min
+          end
+        end
         if size
-          must &quot;have size from #{size} characters&quot; do |s|
+          must &quot;have size of #{size} characters&quot; do |s|
             size.include?(s.size)
           end
         end
@@ -171,6 +180,7 @@ class Doodle
     # defaults to UTC if passed an array
     # use :timezone =&gt; :local if you want local time
     def time(name, params = { }, &amp;block)
+      params = params.dup
       timezone_method = params.delete(:timezone) || :utc
       if timezone_method == :local
         timezone_method = :mktime
@@ -179,7 +189,7 @@ class Doodle
         from String do |s|
           Time.parse(s)
         end
-        from Array do |*args|
+        from Array do |args|
           Time.send(timezone_method, *args)
         end
         # seconds since Thu Jan 01 00:00:00 UTC 1970
@@ -189,7 +199,7 @@ class Doodle
       end
     end
 
-    RX_ISODATE = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(\.\d+)? ?Z$/
+    RX_ISODATE = /^\d{4}-\d{2}-\d{2}([T ]\d{2}:\d{2}(:\d{2})?(\.\d+)?)? ?Z?$/
 
     def utc(name, params = { }, &amp;block)
       da = time( name, { :kind =&gt; Time }.merge(params))
@@ -197,7 +207,7 @@ class Doodle
         # override time from String
         from String do |s|
           if s !~ RX_ISODATE
-            raise ArgumentError, &quot;date must be in ISO format (YYYY-MM-DDTHH:MM:SS, e.g. #{Time.now.utc.xmlschema})&quot;
+            raise ArgumentError, &quot;date must be in ISO format yyyy-mm-ddThh:mm:ss (e.g. #{Time.now.utc.xmlschema})&quot;
           end
           Time.parse(s)
         end</diff>
      <filename>lib/doodle/datatypes.rb</filename>
    </modified>
    <modified>
      <diff>@@ -139,3 +139,23 @@ describe Doodle::DoodleAttribute, 'attribute order' do
     end
   end
 end
+
+describe Doodle::DoodleAttribute, 'attribute order' do
+  it 'should reject attributes without names' do
+    proc { Doodle::DoodleAttribute.params_from_args(:kind =&gt; String) }.should raise_error(ArgumentError)
+  end
+
+  it 'should not allow changing name' do
+    proc { Doodle::DoodleAttribute.new(:name =&gt; &quot;foo&quot;)}.should_not raise_error(ArgumentError)
+    d = Doodle::DoodleAttribute.new(:name =&gt; &quot;foo&quot;)
+    d.name.should_be :foo
+    proc { d.name = :bar }.should raise_error(Doodle::ReadOnlyError)
+  end
+
+  it 'should ensure that attribute name is readonly' do
+    d = Doodle::DoodleAttribute.new(:name =&gt; &quot;foo&quot;, :readonly =&gt; true)
+    d.name.should_be :foo
+    proc { d.name = &quot;foo&quot; }.should raise_error(Doodle::ReadOnlyError)
+  end
+end
+</diff>
      <filename>spec/attributes_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,6 +2,12 @@ require File.dirname(__FILE__) + '/spec_helper.rb'
 
 describe Doodle, 'has Class' do
   temporary_constant :Foo, :Bar, :AudioClip do
+    it &quot;should convert 'has \&quot;foo\&quot;' into 'has :foo&quot; do
+      class Bar &lt; Doodle
+        has &quot;foo&quot;
+      end
+      Bar.doodle.attributes.keys.include?(:foo).should_be true
+    end
     it &quot;should convert 'has Bar' into 'has :bar, :kind =&gt; Bar'&quot; do
       class Bar
       end</diff>
      <filename>spec/has_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -26,7 +26,7 @@ doodle is eco-friendly - it does not globally modify Object, Class or Module, no
 * link[collectors] to help in defining simple DSLs
 * works for [[classes_and_singletons.html|classes, instances and singletons]]
 
-Doodle also supports link[reflection], serialization to and from [[yaml.html|YAML]] and [[doodle-xml.html|XML]], and [[doodle-app.html|command line argument processing]].
+Doodle also supports link[reflection], serialization to and from [[doodle-json.html|JSON]], [[yaml.html|YAML]] and [[doodle-xml.html|XML]], and [[doodle-app.html|command line argument processing]].
 
 == example
 </diff>
      <filename>www/content/index.txt</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>7625e22487a2239d5c0a65847b5a5eb32ad77a6f</id>
    </parent>
  </parents>
  <author>
    <name>Sean O'Halpin</name>
    <email>sean.ohalpin@gmail.com</email>
  </author>
  <url>http://github.com/seanohalpin/doodle/commit/a28091b196915e8f430de7d5fe26a8135d220f6e</url>
  <id>a28091b196915e8f430de7d5fe26a8135d220f6e</id>
  <committed-date>2009-10-10T12:32:33-07:00</committed-date>
  <authored-date>2009-10-10T12:32:33-07:00</authored-date>
  <message>added specs for datatypes (and fixed bugs found as result)</message>
  <tree>c8e38122c1ea87a89253f0a4bd75104f29f0839d</tree>
  <committer>
    <name>Sean O'Halpin</name>
    <email>sean.ohalpin@gmail.com</email>
  </committer>
</commit>
