<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>autotest/discover.rb</filename>
    </added>
    <added>
      <filename>autotest/testunit.rb</filename>
    </added>
    <added>
      <filename>test/forms/_field.html.erb</filename>
    </added>
    <added>
      <filename>test/forms/_fieldset.html.erb</filename>
    </added>
    <added>
      <filename>test/forms/_text_field.html.erb</filename>
    </added>
    <added>
      <filename>test/forms/_widget.html.erb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -130,23 +130,18 @@ module RPH
         end
       end
     
-    public
-      # redefining all traditional form helpers so that they
-      # behave the way FormAssistant thinks they should behave
-      send(:form_helpers).each do |name|
-        define_method name do |field, *args|
-          options, label_options = args.extract_options!, {}
-          
-          # consider the global setting for labels first
-          options[:label] = false if self.class.ignore_labels
-          
-          # allow for turning labels off on a per-helper basis
-          # &lt;%= form.text_field :title, :label =&gt; false %&gt;
-          ignore_label = !!(options[:label].kind_of?(FalseClass))
-          
+      def extract_options_for_label(field, options={})
+        label_options = {}
+
+        # consider the global setting for labels and
+        # allow for turning labels off on a per-helper basis
+        # &lt;%= form.text_field :title, :label =&gt; false %&gt;
+        if self.class.ignore_labels || options[:label] === false
+          label_options[:label] = false
+        else  
           # ensure that the :label option is a Hash from this point on
           options[:label] ||= {}
-          
+        
           # allow for a cleaner way of setting label text
           # &lt;%= form.text_field :whatever, :label =&gt; 'Whatever Title' %&gt;
           label_options.merge!(options[:label].is_a?(String) ? {:text =&gt; options[:label]} : options[:label])
@@ -159,20 +154,67 @@ module RPH
             label_option = &quot;label_#{option}&quot;.to_sym
             label_options.merge!(option.to_sym =&gt; options.delete(label_option)) if options[label_option]
           end
-          
+        
           # Ensure we have default label text 
           # (since Rails' label() does not currently respect I18n)
           label_options[:text] ||= object.class.human_attribute_name(field.to_s)
+        end
           
-          # build out the label element (if desired)
-          label = ignore_label ? nil : self.label(field, label_options.delete(:text), label_options)
-
-          should_render_with_template = true
-          should_render_with_template = false if options.has_key?(:template) &amp;&amp; options[:template].kind_of?(FalseClass)
-          
+        label_options
+      end
+      
+      def extract_options_for_template(helper_name, options={})
+        template_options = {}
+        
+        if options.has_key?(:template) &amp;&amp; options[:template].kind_of?(FalseClass)
+          template_options[:template] = false
+        else  
           # grab the template
-          template = options.delete(:template) || name.to_s
+          template = options.delete(:template) || helper_name.to_s
           template = self.fallback_template unless template_exists?(template)
+          template_options[:template] = template
+        end
+          
+        template_options
+      end  
+    
+    public
+      def without_assistance(options={}, &amp;block)
+        # TODO - allow options to only turn off templates and/or labels
+        ignore_labels, ignore_templates = self.class.ignore_labels, self.class.ignore_templates
+       
+        self.class.ignore_labels, self.class.ignore_templates = true, true
+          result = yield
+        self.class.ignore_labels, self.class.ignore_templates = ignore_labels, ignore_templates
+
+        result
+      end
+    
+      def widget(field, *args, &amp;block)
+        options          = args.extract_options!
+        label_options    = extract_options_for_label(field, options)
+        template_options = extract_options_for_template(self.fallback_template, options)
+        label            = label_options[:label] === false ? nil : self.label(field, label_options.delete(:text), label_options)
+        tip              = options.delete(:tip)
+        required         = !!options.delete(:required)
+
+        element = without_assistance do
+          @template.capture(&amp;block)
+        end  
+        
+        render_partial_for(element, field, label, tip, template_options[:template], 'widget', required, args)
+      end
+      
+      # redefining all traditional form helpers so that they
+      # behave the way FormAssistant thinks they should behave
+      send(:form_helpers).each do |helper_name|
+        define_method(helper_name) do |field, *args|
+          options          = args.extract_options!
+          label_options    = extract_options_for_label(field, options)
+          template_options = extract_options_for_template(helper_name, options)
+          
+          # build out the label element (if desired)
+          label = label_options[:label] === false ? nil : self.label(field, label_options.delete(:text), label_options)
 
           # grab the tip, if any
           tip = options.delete(:tip)
@@ -186,13 +228,13 @@ module RPH
           # call the original render for the element
           element = super(field, *(args &lt;&lt; field_options))
           
-          return element unless should_render_with_template
+          return element if template_options[:template] === false
           
           # return the helper with an optional label if templates are not to be used
-          return render_element(element, field, name, options, ignore_label) if self.class.ignore_templates
+          return render_element(element, field, helper_name, options, label_options[:label] === false) if self.class.ignore_templates
           
           # render the partial template from the desired template root
-          render_partial_for(element, field, label, tip, template, name, required, args)
+          render_partial_for(element, field, label, tip, template_options[:template], helper_name, required, args)
         end
       end
       </diff>
      <filename>lib/form_assistant.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,9 +2,16 @@ require 'test_helper'
 
 module FormAssistantHelpers
   attr_accessor :render_options
+  attr_accessor :view
+  attr_accessor :response
+  
+  def view
+    @view ||= ActionView::Base.new(Rails.configuration.view_path)  
+  end
+  
   def render(options={})
     self.render_options = options
-    String.new
+    @response = view.render(options)
   end
 
   def locals
@@ -35,7 +42,7 @@ module FormAssistantHelpers
 end
 
 class AddressBook &lt; ActiveRecord::Base
-  attr_accessor *%w(first_name nickname)
+  attr_accessor *%w(first_name nickname day month year)
   
   def self.columns
     Hash.new
@@ -48,11 +55,11 @@ class FormAssistantTest &lt; ActionView::TestCase
   attr_accessor :form
 
   def setup
+    Rails.configuration.view_path = File.expand_path(File.dirname(__FILE__))
+
     @address_book = AddressBook.new
-    # @address_book = OpenStruct.new
-    # @address_book.stubs(:errors).returns(@errors ||= ActiveRecord::Errors.new(@address_book))
     @form = RPH::FormAssistant::FormBuilder.new(:address_book, @address_book, self, {}, nil)
-    RPH::FormAssistant::FormBuilder.template_root = File.expand_path(File.join(File.dirname(__FILE__), '../forms'))
+    RPH::FormAssistant::FormBuilder.template_root = File.expand_path(File.join(File.dirname(__FILE__), 'forms'))
   end
   
   test &quot;should use template based on input type&quot; do
@@ -119,4 +126,21 @@ class FormAssistantTest &lt; ActionView::TestCase
     form.text_field :first_name
     expect_locals :errors =&gt; ['First name cannot be root and cannot be admin']
   end
+  
+  test &quot;should create widget&quot; do
+    @address_book.errors.add(:birthday, 'is invalid')
+    
+    form.widget :birthday, :tip =&gt; 'Enter your birthday' do
+      concat @day   = form.select(:day,   (1..31))
+      concat @month = form.select(:month, (1..12))
+      concat @year  = form.select(:year,  (1975...1985))
+    end
+    
+    expect_locals :element =&gt; (@day + @month + @year),
+      :errors =&gt; ['Birthday is invalid'],
+      :tip    =&gt; 'Enter your birthday',
+      :helper =&gt; 'widget'
+    
+    expect_render :partial =&gt; template_path('field')  
+  end
 end
\ No newline at end of file</diff>
      <filename>test/form_assistant_test.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>9eecb37b64c3c9f8fea07227da84f0b4fd7de060</id>
    </parent>
  </parents>
  <author>
    <name>Chris Scharf</name>
    <email>scharfie@gmail.com</email>
  </author>
  <url>http://github.com/rpheath/form_assistant/commit/b02e211452d2d7908f0a4f7ea813d56fa63aeae3</url>
  <id>b02e211452d2d7908f0a4f7ea813d56fa63aeae3</id>
  <committed-date>2009-03-24T09:23:55-07:00</committed-date>
  <authored-date>2009-03-06T08:18:20-08:00</authored-date>
  <message>Added widget support

Signed-off-by: Ryan Heath &lt;rpheath@gmail.com&gt;</message>
  <tree>14e309e8ce0798e0e4cdd0b880de78d251c19393</tree>
  <committer>
    <name>Ryan Heath</name>
    <email>rpheath@gmail.com</email>
  </committer>
</commit>
