forme 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +28 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +18 -2
- data/Rakefile +14 -8
- data/lib/forme.rb +65 -14
- data/lib/forme/rails.rb +99 -0
- data/lib/forme/sinatra.rb +41 -23
- data/lib/forme/version.rb +1 -1
- data/lib/sequel/plugins/forme.rb +22 -10
- data/spec/forme_spec.rb +44 -0
- data/spec/rails_integration_spec.rb +195 -0
- data/spec/sequel_helper.rb +71 -0
- data/spec/sequel_plugin_spec.rb +41 -96
- data/spec/sinatra_integration_spec.rb +94 -2
- metadata +31 -44
    
        data/CHANGELOG
    CHANGED
    
    | @@ -1,3 +1,31 @@ | |
| 1 | 
            +
            === 0.7.0 (2012-05-02)
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            * Support :label_position option in both of the labelers, can be set to :before or :after to override the default (jeremyevans)
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            * Add Rails integration (jeremyevans)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            * Make explicit labeler put label after checkboxes and radio buttons instead of before (jeremyevans)
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            * Make implicit labeler not include hidden checkbox inside label (jeremyevans)
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            * Recognize :cols and :rows options as attributes for textarea inputs in the default formatter (jeremyevans)
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            * Recognize :size and :maxlength options as attributes for text inputs in the default formatter (jeremyevans)
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            * Recognize :style option as attributes in the default formatter (jeremyevans)
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            * Join attribute values specified as arrays with spaces instead of the empty string (jeremyevans)
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            * Make Sinatra ERB integration work with partials (jeremyevans)
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            * Add id attributes for association :as=>:radio or :as=>:checkbox fields (jeremyevans)
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            * Add an html class attribute for radio/checkbox labels in :as=>:radio or :as=>:checkbox fields (jeremyevans)
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            * Wrap text acting as a label in a span with class label for :as=>:radio or :as=>:checkbox fields (jeremyevans)
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            * Support overriding the true/false label and values for select boolean fields in the Sequel plugin (jeremyevans)
         | 
| 28 | 
            +
             | 
| 1 29 | 
             
            === 0.6.0 (2011-08-01)
         | 
| 2 30 |  | 
| 3 31 | 
             
            * Fix wrapping for :as=>:radio boolean fields to handle them like association :as=>:radio fields (jeremyevans)
         | 
    
        data/MIT-LICENSE
    CHANGED
    
    
    
        data/README.rdoc
    CHANGED
    
    | @@ -200,7 +200,7 @@ The Forme Sequel plugin also integerates with Sequel's validation reflection sup | |
| 200 200 | 
             
            +validation_class_methods+ plugin that ships with Sequel.  It will add +pattern+ and +maxlength+ attributes
         | 
| 201 201 | 
             
            based on the format, numericality, and length validations.
         | 
| 202 202 |  | 
| 203 | 
            -
            = Sinatra  | 
| 203 | 
            +
            = Sinatra Support
         | 
| 204 204 |  | 
| 205 205 | 
             
            Forme ships with a Sinatra extension that you can get by <tt>require "forme/sinatra"</tt> and using
         | 
| 206 206 | 
             
            <tt>helpers Forme::Sinatra::ERB</tt> in your Sinatra::Base subclass.  It allows you to use the
         | 
| @@ -213,7 +213,23 @@ following API in your Sinatra ERB forms: | |
| 213 213 | 
             
                <% end %>
         | 
| 214 214 | 
             
              <% end %>
         | 
| 215 215 |  | 
| 216 | 
            -
             | 
| 216 | 
            +
            This example is for ERB/Erubis.  Other Sinatra template libraries work differently and
         | 
| 217 | 
            +
            probably do not support this integration.
         | 
| 218 | 
            +
             | 
| 219 | 
            +
            = Rails Support
         | 
| 220 | 
            +
             | 
| 221 | 
            +
            Forme ships with a Rails extension that you can get by <tt>require "forme/rails"</tt> and using
         | 
| 222 | 
            +
            <tt>helpers Forme::Rails::ERB</tt> in your controller.  If allows you to use the following API
         | 
| 223 | 
            +
            in your Rails forms:
         | 
| 224 | 
            +
             | 
| 225 | 
            +
              <%= forme(@obj, :action=>'/foo') do |f| %>
         | 
| 226 | 
            +
                <%= f.input(:field) %>
         | 
| 227 | 
            +
                <%= f.tag(:fieldset) do %>
         | 
| 228 | 
            +
                  <%= f.input(:field_two) %>
         | 
| 229 | 
            +
                <% end %>
         | 
| 230 | 
            +
              <% end %>
         | 
| 231 | 
            +
             | 
| 232 | 
            +
            This has been tested on Rails 3.2, but should hopefully work on Rails 3.0+.
         | 
| 217 233 |  | 
| 218 234 | 
             
            = Other Similar Projects
         | 
| 219 235 |  | 
    
        data/Rakefile
    CHANGED
    
    | @@ -1,10 +1,5 @@ | |
| 1 1 | 
             
            require "rake"
         | 
| 2 2 | 
             
            require "rake/clean"
         | 
| 3 | 
            -
            begin
         | 
| 4 | 
            -
              require "hanna/rdoctask"
         | 
| 5 | 
            -
            rescue LoadError
         | 
| 6 | 
            -
              require "rake/rdoctask"
         | 
| 7 | 
            -
            end
         | 
| 8 3 |  | 
| 9 4 | 
             
            NAME = 'forme'
         | 
| 10 5 | 
             
            VERS = lambda do
         | 
| @@ -12,8 +7,6 @@ VERS = lambda do | |
| 12 7 | 
             
              Forme.version
         | 
| 13 8 | 
             
            end
         | 
| 14 9 | 
             
            CLEAN.include ["#{NAME}-*.gem", "rdoc", "coverage", '**/*.rbc']
         | 
| 15 | 
            -
            RDOC_DEFAULT_OPTS = ["--quiet", "--line-numbers", "--inline-source", '--title', 'Forme']
         | 
| 16 | 
            -
            RDOC_OPTS = RDOC_DEFAULT_OPTS + ['--main', 'README.rdoc']
         | 
| 17 10 |  | 
| 18 11 | 
             
            # Gem Packaging and Release
         | 
| 19 12 |  | 
| @@ -29,7 +22,20 @@ end | |
| 29 22 |  | 
| 30 23 | 
             
            ### RDoc
         | 
| 31 24 |  | 
| 32 | 
            -
             | 
| 25 | 
            +
            RDOC_DEFAULT_OPTS = ["--quiet", "--line-numbers", "--inline-source", '--title', 'Forme']
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            rdoc_task_class = begin
         | 
| 28 | 
            +
              require "rdoc/task"
         | 
| 29 | 
            +
              RDOC_DEFAULT_OPTS.concat(['-f', 'hanna'])
         | 
| 30 | 
            +
              RDoc::Task
         | 
| 31 | 
            +
            rescue LoadError
         | 
| 32 | 
            +
              require "rake/rdoctask"
         | 
| 33 | 
            +
              Rake::RDocTask
         | 
| 34 | 
            +
            end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            RDOC_OPTS = RDOC_DEFAULT_OPTS + ['--main', 'README.rdoc']
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            rdoc_task_class.new do |rdoc|
         | 
| 33 39 | 
             
              rdoc.rdoc_dir = "rdoc"
         | 
| 34 40 | 
             
              rdoc.options += RDOC_OPTS
         | 
| 35 41 | 
             
              rdoc.rdoc_files.add %w"README.rdoc CHANGELOG MIT-LICENSE lib/**/*.rb"
         | 
    
        data/lib/forme.rb
    CHANGED
    
    | @@ -205,7 +205,7 @@ module Forme | |
| 205 205 | 
             
                  button = opts[:button]
         | 
| 206 206 | 
             
                  if ins || button
         | 
| 207 207 | 
             
                    block = Proc.new do |form|
         | 
| 208 | 
            -
                      form. | 
| 208 | 
            +
                      form._inputs(ins, opts) if ins
         | 
| 209 209 | 
             
                      yield form if block_given?
         | 
| 210 210 | 
             
                      form.emit(form.button(button)) if button
         | 
| 211 211 | 
             
                    end
         | 
| @@ -354,7 +354,13 @@ module Forme | |
| 354 354 | 
             
                # The given +opts+ are passed to the +inputs_wrapper+, and the default
         | 
| 355 355 | 
             
                # +inputs_wrapper+ supports a <tt>:legend</tt> option that is used to
         | 
| 356 356 | 
             
                # set the legend for the fieldset.
         | 
| 357 | 
            -
                def inputs( | 
| 357 | 
            +
                def inputs(*a, &block)
         | 
| 358 | 
            +
                  _inputs(*a, &block)
         | 
| 359 | 
            +
                end
         | 
| 360 | 
            +
                
         | 
| 361 | 
            +
                # Internals of #inputs, should be used internally by the library, where #inputs
         | 
| 362 | 
            +
                # is designed for external use.
         | 
| 363 | 
            +
                def _inputs(inputs=[], opts={})
         | 
| 358 364 | 
             
                  if inputs.is_a?(Hash)
         | 
| 359 365 | 
             
                    opts = inputs.merge(opts)
         | 
| 360 366 | 
             
                    inputs = []
         | 
| @@ -396,6 +402,10 @@ module Forme | |
| 396 402 | 
             
                  tag
         | 
| 397 403 | 
             
                end
         | 
| 398 404 |  | 
| 405 | 
            +
                def tag_(*a, &block)
         | 
| 406 | 
            +
                  tag(*a, &block)
         | 
| 407 | 
            +
                end
         | 
| 408 | 
            +
             | 
| 399 409 | 
             
                # Creates a :submit +Input+ with the given opts, adding it to the list
         | 
| 400 410 | 
             
                # of children for the currently open tag.
         | 
| 401 411 | 
             
                def button(opts={})
         | 
| @@ -585,7 +595,7 @@ module Forme | |
| 585 595 | 
             
                # attributes hash, so they don't need to be specified in the :attr
         | 
| 586 596 | 
             
                # option.  However, they can be specified in both places, and if so,
         | 
| 587 597 | 
             
                # the :attr option version takes precedence.
         | 
| 588 | 
            -
                ATTRIBUTE_OPTIONS = [:name, :id, :placeholder, :value]
         | 
| 598 | 
            +
                ATTRIBUTE_OPTIONS = [:name, :id, :placeholder, :value, :style]
         | 
| 589 599 |  | 
| 590 600 | 
             
                # Create a new instance and call it
         | 
| 591 601 | 
             
                def self.call(input)
         | 
| @@ -719,6 +729,7 @@ module Forme | |
| 719 729 | 
             
                # with the type attribute set to input.
         | 
| 720 730 | 
             
                def _format_input(type)
         | 
| 721 731 | 
             
                  @attr[:type] = type
         | 
| 732 | 
            +
                  copy_options_to_attributes([:size, :maxlength])
         | 
| 722 733 | 
             
                  tag(:input)
         | 
| 723 734 | 
             
                end
         | 
| 724 735 |  | 
| @@ -789,6 +800,7 @@ module Forme | |
| 789 800 | 
             
                # Formats a textarea.  Respects the following options:
         | 
| 790 801 | 
             
                # :value :: Sets value as the child of the textarea.
         | 
| 791 802 | 
             
                def format_textarea
         | 
| 803 | 
            +
                  copy_options_to_attributes([:cols, :rows])
         | 
| 792 804 | 
             
                  if val = @attr.delete(:value)
         | 
| 793 805 | 
             
                    tag(:textarea, @attr, [val])
         | 
| 794 806 | 
             
                  else
         | 
| @@ -796,15 +808,19 @@ module Forme | |
| 796 808 | 
             
                  end
         | 
| 797 809 | 
             
                end
         | 
| 798 810 |  | 
| 799 | 
            -
                 | 
| 800 | 
            -
             | 
| 801 | 
            -
                # :disabled :: Sets the +disabled+ attribute on the resulting tag if true.
         | 
| 802 | 
            -
                def normalize_options
         | 
| 803 | 
            -
                  ATTRIBUTE_OPTIONS.each do |k|
         | 
| 811 | 
            +
                def copy_options_to_attributes(attributes)
         | 
| 812 | 
            +
                  attributes.each do |k|
         | 
| 804 813 | 
             
                    if @opts.has_key?(k) && !@attr.has_key?(k)
         | 
| 805 814 | 
             
                      @attr[k] = @opts[k]
         | 
| 806 815 | 
             
                    end
         | 
| 807 816 | 
             
                  end
         | 
| 817 | 
            +
                end
         | 
| 818 | 
            +
             | 
| 819 | 
            +
                # Normalize the options used for all input types.  Handles:
         | 
| 820 | 
            +
                # :required :: Sets the +required+ attribute on the resulting tag if true.
         | 
| 821 | 
            +
                # :disabled :: Sets the +disabled+ attribute on the resulting tag if true.
         | 
| 822 | 
            +
                def normalize_options
         | 
| 823 | 
            +
                  copy_options_to_attributes(ATTRIBUTE_OPTIONS)
         | 
| 808 824 |  | 
| 809 825 | 
             
                  Forme.attr_classes(@attr, @opts[:class]) if @opts.has_key?(:class)
         | 
| 810 826 | 
             
                  Forme.attr_classes(@attr, 'error') if @opts[:error]
         | 
| @@ -928,10 +944,24 @@ module Forme | |
| 928 944 | 
             
                # the label occurs before the tag.
         | 
| 929 945 | 
             
                def call(tag, input)
         | 
| 930 946 | 
             
                  label = input.opts[:label]
         | 
| 931 | 
            -
                   | 
| 932 | 
            -
             | 
| 947 | 
            +
                  label_position = input.opts[:label_position]
         | 
| 948 | 
            +
                  if [:radio, :checkbox].include?(input.type)
         | 
| 949 | 
            +
                    if input.type == :checkbox && tag.is_a?(Array) && tag.length == 2 && tag.first.attr[:type].to_s == 'hidden' 
         | 
| 950 | 
            +
                      t = if label_position == :before
         | 
| 951 | 
            +
                        [label, ' ', tag.last]
         | 
| 952 | 
            +
                      else
         | 
| 953 | 
            +
                        [tag.last, ' ', label]
         | 
| 954 | 
            +
                      end
         | 
| 955 | 
            +
                      return [tag.first , input.tag(:label, input.opts[:label_attr]||{}, t)]
         | 
| 956 | 
            +
                    elsif label_position == :before
         | 
| 957 | 
            +
                      t = [label, ' ', tag]
         | 
| 958 | 
            +
                    else
         | 
| 959 | 
            +
                      t = [tag, ' ', label]
         | 
| 960 | 
            +
                    end
         | 
| 961 | 
            +
                  elsif label_position == :after
         | 
| 962 | 
            +
                    t = [tag, ' ', label]
         | 
| 933 963 | 
             
                  else
         | 
| 934 | 
            -
                    [label, ": ", tag]
         | 
| 964 | 
            +
                    t = [label, ": ", tag]
         | 
| 935 965 | 
             
                  end
         | 
| 936 966 | 
             
                  input.tag(:label, input.opts[:label_attr]||{}, t)
         | 
| 937 967 | 
             
                end
         | 
| @@ -951,7 +981,18 @@ module Forme | |
| 951 981 | 
             
                # :label_for option is used, the label created will not be
         | 
| 952 982 | 
             
                # associated with an input.
         | 
| 953 983 | 
             
                def call(tag, input)
         | 
| 954 | 
            -
                  [ | 
| 984 | 
            +
                  if [:radio, :checkbox].include?(input.type)
         | 
| 985 | 
            +
                    t = [tag, input.tag(:label, {:for=>input.opts.fetch(:label_for, input.opts[:id])}.merge(input.opts[:label_attr]||{}), [input.opts[:label]])]
         | 
| 986 | 
            +
                    p = :before
         | 
| 987 | 
            +
                  else
         | 
| 988 | 
            +
                    t = [input.tag(:label, {:for=>input.opts.fetch(:label_for, input.opts[:id])}.merge(input.opts[:label_attr]||{}), [input.opts[:label]]), tag]
         | 
| 989 | 
            +
                    p = :after
         | 
| 990 | 
            +
                  end
         | 
| 991 | 
            +
                  if input.opts[:label_position] == p
         | 
| 992 | 
            +
                    t.reverse
         | 
| 993 | 
            +
                  else
         | 
| 994 | 
            +
                    t
         | 
| 995 | 
            +
                  end
         | 
| 955 996 | 
             
                end
         | 
| 956 997 | 
             
              end
         | 
| 957 998 |  | 
| @@ -995,7 +1036,7 @@ module Forme | |
| 995 1036 |  | 
| 996 1037 | 
             
                # Wrap the inputs in an ol tag
         | 
| 997 1038 | 
             
                def call(form, opts)
         | 
| 998 | 
            -
                  super(form, opts){form. | 
| 1039 | 
            +
                  super(form, opts){form.tag_(:ol){yield}}
         | 
| 999 1040 | 
             
                end
         | 
| 1000 1041 | 
             
              end
         | 
| 1001 1042 |  | 
| @@ -1106,11 +1147,21 @@ module Forme | |
| 1106 1147 | 
             
                  string.to_s.gsub(ESCAPE_HTML_PATTERN){|c| ESCAPE_HTML[c] }
         | 
| 1107 1148 | 
             
                end
         | 
| 1108 1149 |  | 
| 1150 | 
            +
                # Join attribute values that are arrays with spaces instead of an empty
         | 
| 1151 | 
            +
                # string.
         | 
| 1152 | 
            +
                def attr_value(v)
         | 
| 1153 | 
            +
                  if v.is_a?(Array)
         | 
| 1154 | 
            +
                    v.map{|c| attr_value(c)}.join(' ')
         | 
| 1155 | 
            +
                  else
         | 
| 1156 | 
            +
                    call(v)
         | 
| 1157 | 
            +
                  end
         | 
| 1158 | 
            +
                end
         | 
| 1159 | 
            +
             | 
| 1109 1160 | 
             
                # Transforms the +tag+'s attributes into an html string, sorting by the keys
         | 
| 1110 1161 | 
             
                # and quoting and html escaping the values.
         | 
| 1111 1162 | 
             
                def attr_html(tag)
         | 
| 1112 1163 | 
             
                  attr = tag.attr.to_a.reject{|k,v| v.nil?}
         | 
| 1113 | 
            -
                  " #{attr.map{|k, v| "#{k}=\"#{ | 
| 1164 | 
            +
                  " #{attr.map{|k, v| "#{k}=\"#{attr_value(v)}\""}.sort.join(' ')}" unless attr.empty?
         | 
| 1114 1165 | 
             
                end
         | 
| 1115 1166 | 
             
              end
         | 
| 1116 1167 |  | 
    
        data/lib/forme/rails.rb
    ADDED
    
    | @@ -0,0 +1,99 @@ | |
| 1 | 
            +
            require 'forme'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Forme
         | 
| 4 | 
            +
              module Rails # :nodoc:
         | 
| 5 | 
            +
                # Subclass used when using Forme/Rails ERB integration,
         | 
| 6 | 
            +
                # handling integration with the view template.
         | 
| 7 | 
            +
                class Form < ::Forme::Form
         | 
| 8 | 
            +
                  # The Rails template that created this form.
         | 
| 9 | 
            +
                  attr_reader :template
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  # Set the template object when initializing.
         | 
| 12 | 
            +
                  def initialize(*)
         | 
| 13 | 
            +
                    super
         | 
| 14 | 
            +
                    @template = @opts[:template]
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  # Serialize and mark as already escaped the string version of
         | 
| 18 | 
            +
                  # the input.
         | 
| 19 | 
            +
                  def emit(tag)
         | 
| 20 | 
            +
                    template.output_buffer << template.raw(tag.to_s)
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  # Capture the inputs into a new output buffer, and return
         | 
| 24 | 
            +
                  # the buffer if not given a block
         | 
| 25 | 
            +
                  def inputs(*)
         | 
| 26 | 
            +
                    if block_given?
         | 
| 27 | 
            +
                      super
         | 
| 28 | 
            +
                    else
         | 
| 29 | 
            +
                      template.send(:with_output_buffer){super}
         | 
| 30 | 
            +
                    end
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
                  
         | 
| 33 | 
            +
                  # If a block is not given, emit the inputs into the current output
         | 
| 34 | 
            +
                  # buffer.
         | 
| 35 | 
            +
                  def _inputs(*)
         | 
| 36 | 
            +
                    if block_given?
         | 
| 37 | 
            +
                      super
         | 
| 38 | 
            +
                    else
         | 
| 39 | 
            +
                      emit(super)
         | 
| 40 | 
            +
                    end
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  # Return a string version of the input that is already marked as safe.
         | 
| 44 | 
            +
                  def input(*)
         | 
| 45 | 
            +
                    template.raw(super.to_s)
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  # Return a string version of the button that is already marked as safe.
         | 
| 49 | 
            +
                  def button(*)
         | 
| 50 | 
            +
                    template.raw(super.to_s)
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                  # If a block is given, create a new output buffer and make sure all the
         | 
| 54 | 
            +
                  # output of the tag goes into that buffer, and return the buffer.
         | 
| 55 | 
            +
                  # Otherwise, just return a string version of the tag that is already
         | 
| 56 | 
            +
                  # marked as safe.
         | 
| 57 | 
            +
                  def tag(type, attr={}, children=[], &block)
         | 
| 58 | 
            +
                    if block_given?
         | 
| 59 | 
            +
                      template.send(:with_output_buffer){tag_(type, attr, children, &block)}
         | 
| 60 | 
            +
                    else
         | 
| 61 | 
            +
                      tag = _tag(type, attr, children)
         | 
| 62 | 
            +
                      template.raw(tag.to_s)
         | 
| 63 | 
            +
                    end
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                  def tag_(type, attr={}, children=[])
         | 
| 67 | 
            +
                    tag = _tag(type, attr, children)
         | 
| 68 | 
            +
                    emit(serializer.serialize_open(tag)) if serializer.respond_to?(:serialize_open)
         | 
| 69 | 
            +
                    Array(children).each{|c| emit(c)}
         | 
| 70 | 
            +
                    yield self if block_given?
         | 
| 71 | 
            +
                    emit(serializer.serialize_close(tag)) if serializer.respond_to?(:serialize_close)
         | 
| 72 | 
            +
                  end
         | 
| 73 | 
            +
                end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                module ERB
         | 
| 76 | 
            +
                  # Create a +Form+ object and yield it to the block,
         | 
| 77 | 
            +
                  # injecting the opening form tag before yielding and
         | 
| 78 | 
            +
                  # the closing form tag after yielding.
         | 
| 79 | 
            +
                  #
         | 
| 80 | 
            +
                  # Argument Handling:
         | 
| 81 | 
            +
                  # No args :: Creates a +Form+ object with no options and not associated
         | 
| 82 | 
            +
                  #            to an +obj+, and with no attributes in the opening tag.
         | 
| 83 | 
            +
                  # 1 hash arg :: Treated as opening form tag attributes, creating a
         | 
| 84 | 
            +
                  #               +Form+ object with no options.
         | 
| 85 | 
            +
                  # 1 non-hash arg :: Treated as the +Form+'s +obj+, with empty options
         | 
| 86 | 
            +
                  #                   and no attributes in the opening tag.
         | 
| 87 | 
            +
                  # 2 hash args :: First hash is opening attributes, second hash is +Form+
         | 
| 88 | 
            +
                  #                options.
         | 
| 89 | 
            +
                  # 1 non-hash arg, 1-2 hash args :: First argument is +Form+'s obj, second is
         | 
| 90 | 
            +
                  #                                  opening attributes, third if provided is
         | 
| 91 | 
            +
                  #                                  +Form+'s options.
         | 
| 92 | 
            +
                  def forme(obj=nil, attr={}, opts={}, &block)
         | 
| 93 | 
            +
                    h = {:template=>self}
         | 
| 94 | 
            +
                    (obj.is_a?(Hash) ? attr = attr.merge(h) : opts = opts.merge(h))
         | 
| 95 | 
            +
                    Form.form(obj, attr, opts, &block)
         | 
| 96 | 
            +
                  end
         | 
| 97 | 
            +
                end
         | 
| 98 | 
            +
              end
         | 
| 99 | 
            +
            end
         | 
    
        data/lib/forme/sinatra.rb
    CHANGED
    
    | @@ -13,7 +13,7 @@ module Forme | |
| 13 13 | 
             
                  # Set the template output object when initializing.
         | 
| 14 14 | 
             
                  def initialize(*)
         | 
| 15 15 | 
             
                    super
         | 
| 16 | 
            -
                    @output = @opts[:output]
         | 
| 16 | 
            +
                    @output = @opts[:output] ? @opts[:output] : ''
         | 
| 17 17 | 
             
                  end
         | 
| 18 18 |  | 
| 19 19 | 
             
                  # Serialize the tag and inject it into the output.
         | 
| @@ -21,37 +21,51 @@ module Forme | |
| 21 21 | 
             
                    output << tag.to_s
         | 
| 22 22 | 
             
                  end
         | 
| 23 23 |  | 
| 24 | 
            -
                  #  | 
| 25 | 
            -
                  #  | 
| 26 | 
            -
                  def inputs(*a)
         | 
| 27 | 
            -
                     | 
| 28 | 
            -
             | 
| 24 | 
            +
                  # Capture the inside of the inputs, injecting it into the template
         | 
| 25 | 
            +
                  # if a block is given, or returning it as a string if not.
         | 
| 26 | 
            +
                  def inputs(*a, &block)
         | 
| 27 | 
            +
                    if block
         | 
| 28 | 
            +
                      capture(block){super}
         | 
| 29 | 
            +
                    else
         | 
| 30 | 
            +
                      capture{super}
         | 
| 31 | 
            +
                    end
         | 
| 29 32 | 
             
                  end
         | 
| 30 33 |  | 
| 31 | 
            -
                  #  | 
| 32 | 
            -
                  #  | 
| 34 | 
            +
                  # Capture the inside of the form, injecting it into the template if
         | 
| 35 | 
            +
                  # a block is given, or returning it as a string if not.
         | 
| 33 36 | 
             
                  def form(*a, &block)
         | 
| 34 | 
            -
                     | 
| 35 | 
            -
             | 
| 37 | 
            +
                    if block
         | 
| 38 | 
            +
                      capture(block){super}
         | 
| 39 | 
            +
                    else
         | 
| 40 | 
            +
                      capture{super}
         | 
| 41 | 
            +
                    end
         | 
| 36 42 | 
             
                  end
         | 
| 37 43 |  | 
| 38 | 
            -
                  # If a block is  | 
| 44 | 
            +
                  # If a block is given, inject an opening tag into the
         | 
| 39 45 | 
             
                  # output, inject any given children into the output, yield to the
         | 
| 40 | 
            -
                  # block, inject a closing tag into the output | 
| 41 | 
            -
                  # so that usage with <%= doesn't cause multiple things to be output.
         | 
| 46 | 
            +
                  # block, inject a closing tag into the output.
         | 
| 42 47 | 
             
                  # If a block is not given, just return the tag created.
         | 
| 43 | 
            -
                  def tag(type, attr={}, children=[])
         | 
| 48 | 
            +
                  def tag(type, attr={}, children=[], &block)
         | 
| 44 49 | 
             
                    tag = _tag(type, attr, children)
         | 
| 45 | 
            -
                    if  | 
| 46 | 
            -
                       | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 50 | 
            +
                    if block
         | 
| 51 | 
            +
                      capture(block) do
         | 
| 52 | 
            +
                        emit(serializer.serialize_open(tag)) if serializer.respond_to?(:serialize_open)
         | 
| 53 | 
            +
                        children.each{|c| emit(c)}
         | 
| 54 | 
            +
                        yield self
         | 
| 55 | 
            +
                        emit(serializer.serialize_close(tag)) if serializer.respond_to?(:serialize_close)
         | 
| 56 | 
            +
                      end
         | 
| 51 57 | 
             
                    else
         | 
| 52 58 | 
             
                      tag
         | 
| 53 59 | 
             
                    end
         | 
| 54 60 | 
             
                  end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                  def capture(block='')
         | 
| 63 | 
            +
                    buf_was, @output = @output, block.is_a?(Proc) ? (eval("@_out_buf", block.binding) || @output) : block
         | 
| 64 | 
            +
                    yield
         | 
| 65 | 
            +
                    ret = @output
         | 
| 66 | 
            +
                    @output = buf_was
         | 
| 67 | 
            +
                    ret
         | 
| 68 | 
            +
                  end
         | 
| 55 69 | 
             
                end
         | 
| 56 70 |  | 
| 57 71 | 
             
                # This is the module used to add the Forme integration
         | 
| @@ -77,9 +91,13 @@ module Forme | |
| 77 91 | 
             
                  #                                  opening attributes, third if provided is
         | 
| 78 92 | 
             
                  #                                  +Form+'s options.
         | 
| 79 93 | 
             
                  def form(obj=nil, attr={}, opts={}, &block)
         | 
| 80 | 
            -
                     | 
| 81 | 
            -
             | 
| 82 | 
            -
             | 
| 94 | 
            +
                    if block
         | 
| 95 | 
            +
                      h = {:output=>@_out_buf}
         | 
| 96 | 
            +
                      (obj.is_a?(Hash) ? attr = attr.merge(h) : opts = opts.merge(h))
         | 
| 97 | 
            +
                      Form.form(obj, attr, opts, &block)
         | 
| 98 | 
            +
                    else
         | 
| 99 | 
            +
                      Form.form(obj, attr, opts)
         | 
| 100 | 
            +
                    end
         | 
| 83 101 | 
             
                  end
         | 
| 84 102 | 
             
                end 
         | 
| 85 103 |  |