<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -1,6 +1,9 @@
-=== 1.0.0 / 2008-04-11
+=== 0.0.2 / 2008-04-12
 
-* 1 major enhancement
+* Added bang(!) method support
+* No longer automatically multi-level assigning
+* Hash conversion now calls methods instead of []= to allow for overrides
 
-  * Birthday!
+=== 0.0.1 / 2008-04-12
 
+* Initial release
\ No newline at end of file</diff>
      <filename>History.txt</filename>
    </modified>
    <modified>
      <diff>@@ -10,13 +10,19 @@ be used in RESTful API libraries to provide easy object-like access
 to JSON and XML parsed hashes.
 
 == SYNOPSIS:
-
+  
   mash = Mash.new
   mash.name? # =&gt; false
+  mash.name # =&gt; nil
   mash.name = &quot;My Mash&quot;
   mash.name # =&gt; &quot;My Mash&quot;
   mash.name? # =&gt; true
   mash.inspect # =&gt; &lt;Mash name=&quot;My Mash&quot;&gt;
+  
+  mash = Mash.new
+  # use bang methods for multi-level assignment
+  mash.author!.name = &quot;Michael Bleigh&quot;
+  mash.author # =&gt; &lt;Mash name=&quot;Michael Bleigh&quot;&gt;
 
 == INSTALL:
 </diff>
      <filename>README.txt</filename>
    </modified>
    <modified>
      <diff>@@ -4,6 +4,14 @@
 # without the overhead of actually doing so. Think of it as OpenStruct
 # with some additional goodies.
 #
+# A Mash will look at the methods you pass it and perform operations
+# based on the following rules:
+# 
+# * No punctuation: Returns the value of the hash for that key, or nil if none exists.
+# * Assignment (&lt;tt&gt;=&lt;/tt&gt;): Sets the attribute of the given method name.
+# * Existence (&lt;tt&gt;?&lt;/tt&gt;): Returns true or false depending on whether that key has been set.
+# * Bang (&lt;tt&gt;!&lt;/tt&gt;): Forces the existence of this key, used for deep Mashes. Think of it as &quot;touch&quot; for mashes.
+#
 # == Basic Example
 #    
 #   mash = Mash.new
@@ -21,8 +29,18 @@
 #   mash.f.first.g # =&gt; 44
 #   mash.f.last # =&gt; 12
 #
+# == Bang Example
+#
+#   mash = Mash.new
+#   mash.author # =&gt; nil
+#   mash.author! # =&gt; &lt;Mash&gt;
+#   
+#   mash = Mash.new
+#   mash.author!.name = &quot;Michael Bleigh&quot;
+#   mash.author # =&gt; &lt;Mash name=&quot;Michael Bleigh&quot;&gt;
+#
 class Mash &lt; Hash
-  VERSION = '0.0.1'
+  VERSION = '0.0.2'
   
   # If you pass in an existing hash, it will
   # convert it to a Mash including recursively
@@ -66,16 +84,19 @@ class Mash &lt; Hash
       self[match[1]] = args.first
     elsif (match = method_name.to_s.match(/(.*)\?$/)) &amp;&amp; args.size == 0
       key?(match[1])
+    elsif (match = method_name.to_s.match(/(.*)!$/)) &amp;&amp; args.size == 0
+      return self[match[1]] if key?(match[1])
+      self[match[1]] = Mash.new
     elsif keys.include?(method_name.to_s)
       self[method_name]
     elsif match = method_name.to_s.match(/^([a-z][a-z0-9A-Z_]+)$/)
-      Mash.new
+      nil
     else
       super
     end
   end
   
-  private
+  protected
   
   def mash_a_hash(hash) #:nodoc:
     hash.each do |k,v|
@@ -86,7 +107,10 @@ class Mash &lt; Hash
           v = collect_mashed_hashes_in(v) if v.is_a?(Array)
       end
       
-      self[k] = v
+      # we use the method call instead of []= here so that
+      # it can be easily overridden for custom behavior in
+      # inheriting objects
+      self.send &quot;#{k.to_s}=&quot;, v
     end
   end
   </diff>
      <filename>lib/mash.rb</filename>
    </modified>
    <modified>
      <diff>@@ -37,6 +37,26 @@ describe Mash do
     @mash.to_s.should == @mash.inspect
   end
   
+  it &quot;should return nil instead of raising an error for attribute-esque method calls&quot; do
+    @mash.abc.should be_nil
+  end
+  
+  it &quot;should return a Mash when passed a bang method to a non-existenct key&quot; do
+    @mash.abc!.is_a?(Mash).should be_true
+  end
+  
+  it &quot;should return the existing value when passed a bang method for an existing key&quot; do
+    @mash.name = &quot;Bob&quot;
+    @mash.name!.should == &quot;Bob&quot;
+  end
+  
+  it &quot;should allow for multi-level assignment through bang methods&quot; do
+    @mash.author!.name = &quot;Michael Bleigh&quot;
+    @mash.author.should == Mash.new(:name =&gt; &quot;Michael Bleigh&quot;)
+    @mash.author!.website!.url = &quot;http://www.mbleigh.com/&quot;
+    @mash.author.website.should == Mash.new(:url =&gt; &quot;http://www.mbleigh.com/&quot;)
+  end
+  
   context &quot;#initialize&quot; do
     it &quot;should convert an existing hash to a Mash&quot; do
       converted = Mash.new({:abc =&gt; 123, :name =&gt; &quot;Bob&quot;})</diff>
      <filename>spec/mash_spec.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>3f8b5ad2667f92193c141cfbc191ff07732127a2</id>
    </parent>
  </parents>
  <author>
    <name>Michael Bleigh</name>
    <email>michael@intridea.com</email>
  </author>
  <url>http://github.com/mbleigh/mash/commit/8d5f386193c70298b8372fd26ac8799065871a1c</url>
  <id>8d5f386193c70298b8372fd26ac8799065871a1c</id>
  <committed-date>2008-04-12T12:42:39-07:00</committed-date>
  <authored-date>2008-04-12T12:42:39-07:00</authored-date>
  <message>Adding bang method support for multi-level assignment. Hash conversion now calls methods instead of []= for overridability.</message>
  <tree>1053e62be5c14c8f205b4cf2daddf1fb5d5f8107</tree>
  <committer>
    <name>Michael Bleigh</name>
    <email>michael@intridea.com</email>
  </committer>
</commit>
