case_form 0.0.3
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.rdoc +1 -0
- data/MIT-LICENSE.rdoc +20 -0
- data/Manifest +86 -0
- data/README.rdoc +0 -0
- data/Rakefile +30 -0
- data/TODO.rdoc +7 -0
- data/case_form.gemspec +31 -0
- data/lib/case_form.rb +88 -0
- data/lib/case_form/associations.rb +50 -0
- data/lib/case_form/buttons.rb +175 -0
- data/lib/case_form/core_ext/form_helper.rb +54 -0
- data/lib/case_form/core_ext/layout_helper.rb +16 -0
- data/lib/case_form/core_ext/sentence_error.rb +38 -0
- data/lib/case_form/element.rb +40 -0
- data/lib/case_form/element/base.rb +95 -0
- data/lib/case_form/element/button.rb +64 -0
- data/lib/case_form/element/error.rb +54 -0
- data/lib/case_form/element/errors/complex_error.rb +107 -0
- data/lib/case_form/element/errors/simple_error.rb +76 -0
- data/lib/case_form/element/fieldset.rb +35 -0
- data/lib/case_form/element/hint.rb +54 -0
- data/lib/case_form/element/input.rb +106 -0
- data/lib/case_form/element/inputs/collection/checkbox_input.rb +36 -0
- data/lib/case_form/element/inputs/collection/radio_input.rb +27 -0
- data/lib/case_form/element/inputs/collection/select_input.rb +22 -0
- data/lib/case_form/element/inputs/collection_input.rb +89 -0
- data/lib/case_form/element/inputs/datetime/date_input.rb +45 -0
- data/lib/case_form/element/inputs/datetime/date_time_input.rb +50 -0
- data/lib/case_form/element/inputs/datetime/time_input.rb +34 -0
- data/lib/case_form/element/inputs/datetime/time_zone_input.rb +24 -0
- data/lib/case_form/element/inputs/file_input.rb +13 -0
- data/lib/case_form/element/inputs/hidden_input.rb +17 -0
- data/lib/case_form/element/inputs/number_input.rb +42 -0
- data/lib/case_form/element/inputs/search_input.rb +32 -0
- data/lib/case_form/element/inputs/string_input.rb +18 -0
- data/lib/case_form/element/inputs/text_input.rb +19 -0
- data/lib/case_form/element/label.rb +52 -0
- data/lib/case_form/element/nested_model.rb +105 -0
- data/lib/case_form/element/nested_models/handle.rb +18 -0
- data/lib/case_form/element/nested_models/handles/destructor_handle.rb +47 -0
- data/lib/case_form/element/nested_models/handles/generator_handle.rb +55 -0
- data/lib/case_form/element_ext/associationable.rb +54 -0
- data/lib/case_form/element_ext/columnable.rb +21 -0
- data/lib/case_form/element_ext/naming.rb +17 -0
- data/lib/case_form/element_ext/validationable.rb +13 -0
- data/lib/case_form/errors.rb +189 -0
- data/lib/case_form/form_builder.rb +11 -0
- data/lib/case_form/inputs.rb +1095 -0
- data/lib/case_form/labels.rb +102 -0
- data/lib/case_form/version.rb +6 -0
- data/lib/generators/case_form/install_generator.rb +33 -0
- data/lib/generators/case_form/templates/case_form.rb +63 -0
- data/lib/generators/case_form/templates/javascripts/jquery.case_form.js +10 -0
- data/lib/generators/case_form/templates/javascripts/prototype.case_form.js +0 -0
- data/lib/generators/case_form/templates/locales/en.yml +28 -0
- data/lib/generators/case_form/templates/locales/pl.yml +28 -0
- data/lib/generators/case_form/templates/stylesheets/stylesheet.css +93 -0
- data/lib/generators/case_form/templates/stylesheets/stylesheet_changes.css +1 -0
- data/lib/generators/case_form/uninstall_generator.rb +30 -0
- data/rails/init.rb +1 -0
- data/test/element/button_test.rb +85 -0
- data/test/element/errors/complex_error_test.rb +140 -0
- data/test/element/errors/simple_error_test.rb +92 -0
- data/test/element/fieldset_test.rb +28 -0
- data/test/element/hint_test.rb +81 -0
- data/test/element/input_test.rb +197 -0
- data/test/element/inputs/collection/checkbox_input_test.rb +176 -0
- data/test/element/inputs/collection/radio_input_test.rb +156 -0
- data/test/element/inputs/collection/select_input_test.rb +152 -0
- data/test/element/inputs/datetime/date_input_test.rb +160 -0
- data/test/element/inputs/datetime/datetime_input_test.rb +227 -0
- data/test/element/inputs/datetime/time_input_test.rb +72 -0
- data/test/element/inputs/datetime/time_zone_input_test.rb +42 -0
- data/test/element/inputs/file_input_test.rb +13 -0
- data/test/element/inputs/hidden_input_test.rb +13 -0
- data/test/element/inputs/number_input_test.rb +50 -0
- data/test/element/inputs/search_input_test.rb +13 -0
- data/test/element/inputs/string_input_test.rb +33 -0
- data/test/element/inputs/text_input_test.rb +13 -0
- data/test/element/label_test.rb +62 -0
- data/test/element/nested_model_test.rb +163 -0
- data/test/element/nested_models/handles/destructor_handle_test.rb +35 -0
- data/test/element/nested_models/handles/generator_handle_test.rb +27 -0
- data/test/form_builder_test.rb +25 -0
- data/test/form_helper_test.rb +15 -0
- data/test/lib/models.rb +268 -0
- data/test/test_helper.rb +74 -0
- metadata +235 -0
| @@ -0,0 +1,54 @@ | |
| 1 | 
            +
            module CaseForm
         | 
| 2 | 
            +
              module FormHelper
         | 
| 3 | 
            +
                @@default_field_error_proc = nil
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                # Override the default ActiveRecordHelper behaviour of wrapping the input.
         | 
| 6 | 
            +
                # This gets taken care of semantically by adding an error class to the wrapper tag
         | 
| 7 | 
            +
                # containing the input.
         | 
| 8 | 
            +
                FIELD_ERROR_PROC = proc do |html_tag, instance_tag|
         | 
| 9 | 
            +
                  html_tag
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
                
         | 
| 12 | 
            +
                def with_custom_field_error_proc(&block)
         | 
| 13 | 
            +
                  @@default_field_error_proc = ::ActionView::Base.field_error_proc
         | 
| 14 | 
            +
                  ::ActionView::Base.field_error_proc = FIELD_ERROR_PROC
         | 
| 15 | 
            +
                  result = yield
         | 
| 16 | 
            +
                  ::ActionView::Base.field_error_proc = @@default_field_error_proc
         | 
| 17 | 
            +
                  result
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
                
         | 
| 20 | 
            +
                # Define case_form_for and case_fields_for
         | 
| 21 | 
            +
                [:form_for, :fields_for].each do |helper|
         | 
| 22 | 
            +
                  class_eval <<-METHOD, __FILE__, __LINE__
         | 
| 23 | 
            +
                    def case_#{helper}(record_or_name_or_array, *args, &block)
         | 
| 24 | 
            +
                      options = args.extract_options!
         | 
| 25 | 
            +
                      options[:builder] = CaseForm::FormBuilder
         | 
| 26 | 
            +
                      css_class = case record_or_name_or_array
         | 
| 27 | 
            +
                        when String, Symbol then record_or_name_or_array.to_s
         | 
| 28 | 
            +
                        when Array then dom_class(record_or_name_or_array.last)
         | 
| 29 | 
            +
                        else dom_class(record_or_name_or_array)
         | 
| 30 | 
            +
                      end
         | 
| 31 | 
            +
                      options[:html] ||= {}
         | 
| 32 | 
            +
                      options[:html][:class] = "case_form \#{css_class} \#{options[:html][:class]}".strip
         | 
| 33 | 
            +
                
         | 
| 34 | 
            +
                      with_custom_field_error_proc do
         | 
| 35 | 
            +
                        #{helper}(record_or_name_or_array, *(args << options), &block)
         | 
| 36 | 
            +
                      end
         | 
| 37 | 
            +
                    end
         | 
| 38 | 
            +
                  METHOD
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
                
         | 
| 41 | 
            +
                # Define remote_case_form_for
         | 
| 42 | 
            +
                class_eval <<-METHOD
         | 
| 43 | 
            +
                  def remote_case_form_for(record_or_name_or_array, *args, &block)
         | 
| 44 | 
            +
                    options = args.extract_options!
         | 
| 45 | 
            +
                    options[:remote] = true
         | 
| 46 | 
            +
                      
         | 
| 47 | 
            +
                    case_form_for(record_or_name_or_array, *(args << options), &block)
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
                METHOD
         | 
| 50 | 
            +
              end
         | 
| 51 | 
            +
            end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            # Include CaseForm
         | 
| 54 | 
            +
            ActionView::Helpers.send :include, CaseForm::FormHelper
         | 
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            # coding: utf-8
         | 
| 2 | 
            +
            module CaseForm
         | 
| 3 | 
            +
              module LayoutHelper
         | 
| 4 | 
            +
                def case_form_stylesheet_link_tag
         | 
| 5 | 
            +
                  stylesheet_link_tag("case_form_changes", "case_form")
         | 
| 6 | 
            +
                end
         | 
| 7 | 
            +
                alias_method :case_form_stylesheet, :case_form_stylesheet_link_tag
         | 
| 8 | 
            +
                
         | 
| 9 | 
            +
                def case_form_javascript_include_tag
         | 
| 10 | 
            +
                  javascript_include_tag("case_form")
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
                alias_method :case_form_js, :case_form_javascript_include_tag
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
            end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            ActionView::Base.send :include, CaseForm::LayoutHelper
         | 
| @@ -0,0 +1,38 @@ | |
| 1 | 
            +
            # coding: utf-8
         | 
| 2 | 
            +
            module CaseForm
         | 
| 3 | 
            +
              module SentenceError
         | 
| 4 | 
            +
                # Returns all the full error messages as a sentences in an array.
         | 
| 5 | 
            +
                #
         | 
| 6 | 
            +
                #   class User
         | 
| 7 | 
            +
                #     validates_presence_of :password, :address, :email
         | 
| 8 | 
            +
                #     validates_length_of :password, :in => 5..30
         | 
| 9 | 
            +
                #     validates_confirmation_of :password
         | 
| 10 | 
            +
                #   end
         | 
| 11 | 
            +
                #
         | 
| 12 | 
            +
                #   user = User.create(:address => '123 First St.')
         | 
| 13 | 
            +
                #   user.errors.full_sentences # =>
         | 
| 14 | 
            +
                #     ["Password is too short (minimum is 5 characters), can't be blank and should match confirmation"]
         | 
| 15 | 
            +
                #
         | 
| 16 | 
            +
                def full_sentences(options={})
         | 
| 17 | 
            +
                  full_sentences = []
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  keys.each do |attribute|
         | 
| 20 | 
            +
                    if attribute == :base
         | 
| 21 | 
            +
                      self[attribute].each {|m| full_sentences << m }
         | 
| 22 | 
            +
                    else
         | 
| 23 | 
            +
                      attr_name = attribute.to_s.gsub('.', '_').humanize
         | 
| 24 | 
            +
                      attr_name = @base.class.human_attribute_name(attribute, :default => attr_name)
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                      messages = Array.wrap(self[attribute])
         | 
| 27 | 
            +
                      messages.collect! { |m| I18n.t(:"errors.format", :message => m, :attribute => nil).strip }
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                      full_sentences << (attr_name + " " + messages.to_sentence(options))
         | 
| 30 | 
            +
                    end
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  full_sentences
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
            end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            ActiveModel::Errors.send :include, CaseForm::SentenceError
         | 
| @@ -0,0 +1,40 @@ | |
| 1 | 
            +
             | 
| 2 | 
            +
             | 
| 3 | 
            +
            # coding: utf-8
         | 
| 4 | 
            +
            module CaseForm
         | 
| 5 | 
            +
              module Element
         | 
| 6 | 
            +
                autoload :Base,                  'case_form/element/base'
         | 
| 7 | 
            +
                                                 
         | 
| 8 | 
            +
                autoload :Fieldset,              'case_form/element/fieldset'
         | 
| 9 | 
            +
                                                            
         | 
| 10 | 
            +
                autoload :Input,                 'case_form/element/input'
         | 
| 11 | 
            +
                autoload :StringInput,           'case_form/element/inputs/string_input'
         | 
| 12 | 
            +
                autoload :TextInput,             'case_form/element/inputs/text_input'
         | 
| 13 | 
            +
                autoload :HiddenInput,           'case_form/element/inputs/hidden_input'
         | 
| 14 | 
            +
                autoload :SearchInput,           'case_form/element/inputs/search_input'
         | 
| 15 | 
            +
                autoload :FileInput,             'case_form/element/inputs/file_input'
         | 
| 16 | 
            +
                autoload :DateTimeInput,         'case_form/element/inputs/datetime/date_time_input'
         | 
| 17 | 
            +
                autoload :DateInput,             'case_form/element/inputs/datetime/date_input'
         | 
| 18 | 
            +
                autoload :TimeInput,             'case_form/element/inputs/datetime/time_input'
         | 
| 19 | 
            +
                autoload :TimeZoneInput,         'case_form/element/inputs/datetime/time_zone_input'
         | 
| 20 | 
            +
                autoload :NumberInput,           'case_form/element/inputs/number_input'
         | 
| 21 | 
            +
                autoload :CollectionInput,       'case_form/element/inputs/collection_input'
         | 
| 22 | 
            +
                autoload :SelectInput,           'case_form/element/inputs/collection/select_input'
         | 
| 23 | 
            +
                autoload :CheckboxInput,         'case_form/element/inputs/collection/checkbox_input'
         | 
| 24 | 
            +
                autoload :RadioInput,            'case_form/element/inputs/collection/radio_input'
         | 
| 25 | 
            +
                                                         
         | 
| 26 | 
            +
                autoload :Label,                 'case_form/element/label'
         | 
| 27 | 
            +
                autoload :Hint,                  'case_form/element/hint'
         | 
| 28 | 
            +
                                                            
         | 
| 29 | 
            +
                autoload :Button,                'case_form/element/button'
         | 
| 30 | 
            +
                                                 
         | 
| 31 | 
            +
                autoload :Error,                 'case_form/element/error'
         | 
| 32 | 
            +
                autoload :SimpleError,           'case_form/element/errors/simple_error'
         | 
| 33 | 
            +
                autoload :ComplexError,          'case_form/element/errors/complex_error'
         | 
| 34 | 
            +
                
         | 
| 35 | 
            +
                autoload :NestedModel,           'case_form/element/nested_model'
         | 
| 36 | 
            +
                autoload :Handle,                'case_form/element/nested_models/handle'
         | 
| 37 | 
            +
                autoload :GeneratorHandle,       'case_form/element/nested_models/handles/generator_handle'
         | 
| 38 | 
            +
                autoload :DestructorHandle,      'case_form/element/nested_models/handles/destructor_handle'
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
            end
         | 
| @@ -0,0 +1,95 @@ | |
| 1 | 
            +
            require 'case_form/element_ext/naming'
         | 
| 2 | 
            +
            require 'case_form/element_ext/columnable'
         | 
| 3 | 
            +
            require 'case_form/element_ext/validationable'
         | 
| 4 | 
            +
            require 'case_form/element_ext/associationable'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            # coding: utf-8
         | 
| 7 | 
            +
            module CaseForm
         | 
| 8 | 
            +
              module Element
         | 
| 9 | 
            +
                class Base
         | 
| 10 | 
            +
                  include ElementExt::Naming
         | 
| 11 | 
            +
                  
         | 
| 12 | 
            +
                  HTML_OPTIONS = [:id, :class, :style, :readonly, :disabled, :type, :name,
         | 
| 13 | 
            +
                                  :autofocus, :placeholder, :required, :multiple, :checked, :selected, 
         | 
| 14 | 
            +
                                  :for, :min, :max, :step, :pattern, :size, :maxlength, :cols, :rows]
         | 
| 15 | 
            +
                  
         | 
| 16 | 
            +
                  class_inheritable_accessor :allowed_options
         | 
| 17 | 
            +
                  self.allowed_options = [:custom, :id, :class, :style]
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  attr_accessor :builder, :options
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def initialize(builder, options={})
         | 
| 22 | 
            +
                    @builder, @options = builder, options.symbolize_keys!
         | 
| 23 | 
            +
                    validate_options
         | 
| 24 | 
            +
                    default_options
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  private
         | 
| 28 | 
            +
                    def validate_options #:nodoc same as assert_valid_keys for Hash
         | 
| 29 | 
            +
                      allowed = self.class.allowed_options.flatten
         | 
| 30 | 
            +
                      banned = options.keys - allowed
         | 
| 31 | 
            +
                      raise(ArgumentError, "Unknown option(s): #{banned.join(', ')}. Available options: #{allowed.join(', ')}") unless banned.empty?
         | 
| 32 | 
            +
                    end
         | 
| 33 | 
            +
                    
         | 
| 34 | 
            +
                    def default_options
         | 
| 35 | 
            +
                      options         ||= {}
         | 
| 36 | 
            +
                      options[:class] ||= []
         | 
| 37 | 
            +
                      options[:id]    ||= []
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
                    
         | 
| 40 | 
            +
                    def wrapper_options
         | 
| 41 | 
            +
                      wrapper_options = {}
         | 
| 42 | 
            +
                      wrapper_options[:class] = []
         | 
| 43 | 
            +
                      wrapper_options
         | 
| 44 | 
            +
                    end
         | 
| 45 | 
            +
                    
         | 
| 46 | 
            +
                    def html_options
         | 
| 47 | 
            +
                      options.slice(*HTML_OPTIONS).merge(custom_options)
         | 
| 48 | 
            +
                    end
         | 
| 49 | 
            +
                    
         | 
| 50 | 
            +
                    def custom_options
         | 
| 51 | 
            +
                      custom_options = {}
         | 
| 52 | 
            +
                      return custom_options unless options.has_key?(:custom)
         | 
| 53 | 
            +
                      raise(ArgumentError, "Invalid :custom options! Custom options should be hash with key and value.") unless options[:custom].is_a?(Hash)
         | 
| 54 | 
            +
                      options.delete(:custom).each { |key, value| custom_options[:"data-#{key}"] = value }
         | 
| 55 | 
            +
                      custom_options
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
                    
         | 
| 58 | 
            +
                    def object_name
         | 
| 59 | 
            +
                      @builder.object_name
         | 
| 60 | 
            +
                    end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                    def object
         | 
| 63 | 
            +
                      @builder.object
         | 
| 64 | 
            +
                    end
         | 
| 65 | 
            +
                            
         | 
| 66 | 
            +
                    def template
         | 
| 67 | 
            +
                      builder.template
         | 
| 68 | 
            +
                    end
         | 
| 69 | 
            +
                    
         | 
| 70 | 
            +
                    def required?
         | 
| 71 | 
            +
                      if options.has_key?(:required)
         | 
| 72 | 
            +
                        options[:required]
         | 
| 73 | 
            +
                      elsif respond_to?(:validationable?) && validationable? && method_validations.any? { |v| v.kind == :presence }
         | 
| 74 | 
            +
                        true
         | 
| 75 | 
            +
                      elsif respond_to?(:columnable?) && object_column.present? && object_column.null == false
         | 
| 76 | 
            +
                        true
         | 
| 77 | 
            +
                      else
         | 
| 78 | 
            +
                        CaseForm.all_fields_required
         | 
| 79 | 
            +
                      end
         | 
| 80 | 
            +
                    end
         | 
| 81 | 
            +
                    
         | 
| 82 | 
            +
                    def new?
         | 
| 83 | 
            +
                      object.new_record?
         | 
| 84 | 
            +
                    end
         | 
| 85 | 
            +
                    
         | 
| 86 | 
            +
                    def action
         | 
| 87 | 
            +
                      new? ? :new : :edit
         | 
| 88 | 
            +
                    end
         | 
| 89 | 
            +
                    
         | 
| 90 | 
            +
                    def wrapper_tag
         | 
| 91 | 
            +
                      CaseForm.wrapper_tag
         | 
| 92 | 
            +
                    end
         | 
| 93 | 
            +
                end
         | 
| 94 | 
            +
              end
         | 
| 95 | 
            +
            end
         | 
| @@ -0,0 +1,64 @@ | |
| 1 | 
            +
            # coding: utf-8
         | 
| 2 | 
            +
            module CaseForm
         | 
| 3 | 
            +
              module Element
         | 
| 4 | 
            +
                class Button < Base
         | 
| 5 | 
            +
                  self.allowed_options << [:disabled, :text, :as]
         | 
| 6 | 
            +
                  
         | 
| 7 | 
            +
                  # Generate button with defined text and HTML options
         | 
| 8 | 
            +
                  #
         | 
| 9 | 
            +
                  def generate
         | 
| 10 | 
            +
                    template.content_tag wrapper_tag, button, wrapper_options
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
                  
         | 
| 13 | 
            +
                  private
         | 
| 14 | 
            +
                    # Distribute default options for button.
         | 
| 15 | 
            +
                    #
         | 
| 16 | 
            +
                    def default_options
         | 
| 17 | 
            +
                      options[:as]       ||= :commit
         | 
| 18 | 
            +
                      options[:class]    ||= [:button]
         | 
| 19 | 
            +
                      options[:id]       ||= "#{builder.object_name}_#{button_type}"
         | 
| 20 | 
            +
                      options[:type]     ||= button_type
         | 
| 21 | 
            +
                      options[:name]     ||= button_type
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
                    
         | 
| 24 | 
            +
                    # Distribute wrapper options for button.
         | 
| 25 | 
            +
                    #
         | 
| 26 | 
            +
                    def wrapper_options
         | 
| 27 | 
            +
                      wrapper_options = super
         | 
| 28 | 
            +
                      wrapper_options[:class] << :element
         | 
| 29 | 
            +
                      wrapper_options
         | 
| 30 | 
            +
                    end
         | 
| 31 | 
            +
                    
         | 
| 32 | 
            +
                    # Create submit button
         | 
| 33 | 
            +
                    #
         | 
| 34 | 
            +
                    def button
         | 
| 35 | 
            +
                      builder.submit(text, html_options)
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
                    
         | 
| 38 | 
            +
                    # Generate button text.
         | 
| 39 | 
            +
                    #
         | 
| 40 | 
            +
                    def text
         | 
| 41 | 
            +
                      options.delete(:text) || translated_text
         | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
                    
         | 
| 44 | 
            +
                    # Translate button text
         | 
| 45 | 
            +
                    def translated_text
         | 
| 46 | 
            +
                      lookups = []
         | 
| 47 | 
            +
                      lookups << :"#{builder.object_name}.#{button_type}"
         | 
| 48 | 
            +
                      lookups << :"#{button_type}"
         | 
| 49 | 
            +
                      lookups << default_button_text
         | 
| 50 | 
            +
                      I18n.t(lookups.shift, :scope => :"case_form.buttons", :default => lookups)
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
                    
         | 
| 53 | 
            +
                    # Default button text
         | 
| 54 | 
            +
                    def default_button_text
         | 
| 55 | 
            +
                      button_type == :submit ? (new? ? "Create" : "Update") : "Reset"
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
                    
         | 
| 58 | 
            +
                    # Button type (available: :commit and :reset)
         | 
| 59 | 
            +
                    def button_type
         | 
| 60 | 
            +
                      options[:as]
         | 
| 61 | 
            +
                    end
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
              end
         | 
| 64 | 
            +
            end
         | 
| @@ -0,0 +1,54 @@ | |
| 1 | 
            +
            module CaseForm
         | 
| 2 | 
            +
              module Element
         | 
| 3 | 
            +
                class Error < Base
         | 
| 4 | 
            +
                  self.allowed_options << [:tag, :as, :connector, :last_connector]
         | 
| 5 | 
            +
                  
         | 
| 6 | 
            +
                  private
         | 
| 7 | 
            +
                    # Defined error HTML tag
         | 
| 8 | 
            +
                    #
         | 
| 9 | 
            +
                    def error_tag
         | 
| 10 | 
            +
                      options.delete(:tag) || CaseForm.error_tag
         | 
| 11 | 
            +
                    end
         | 
| 12 | 
            +
                    
         | 
| 13 | 
            +
                    # Defined error type
         | 
| 14 | 
            +
                    #
         | 
| 15 | 
            +
                    # == Allowed types:
         | 
| 16 | 
            +
                    # * :sentence
         | 
| 17 | 
            +
                    # * :list
         | 
| 18 | 
            +
                    #
         | 
| 19 | 
            +
                    def error_type
         | 
| 20 | 
            +
                      options.delete(:as) || CaseForm.error_type
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
                    
         | 
| 23 | 
            +
                    # Defined error connector (default ', ')
         | 
| 24 | 
            +
                    #
         | 
| 25 | 
            +
                    def error_connector
         | 
| 26 | 
            +
                      options.delete(:connector) || CaseForm.error_connector
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
                    
         | 
| 29 | 
            +
                    # Defined last error connector (default ' and '). Used in sentence with many errors on one method. 
         | 
| 30 | 
            +
                    #
         | 
| 31 | 
            +
                    def last_error_connector
         | 
| 32 | 
            +
                      options.delete(:last_connector) || CaseForm.last_error_connector
         | 
| 33 | 
            +
                    end
         | 
| 34 | 
            +
                    
         | 
| 35 | 
            +
                    # Type of error 
         | 
| 36 | 
            +
                    def error_messages
         | 
| 37 | 
            +
                      list? ? translated_list : translated_sentence
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
                    
         | 
| 40 | 
            +
                    def list?
         | 
| 41 | 
            +
                      error_type == :list
         | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
                    
         | 
| 44 | 
            +
                    def sentence?
         | 
| 45 | 
            +
                      error_type == :sentence
         | 
| 46 | 
            +
                    end
         | 
| 47 | 
            +
                    
         | 
| 48 | 
            +
                    # OrderedHash with all errors
         | 
| 49 | 
            +
                    def errors
         | 
| 50 | 
            +
                      object.errors
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
            end
         | 
| @@ -0,0 +1,107 @@ | |
| 1 | 
            +
            module CaseForm
         | 
| 2 | 
            +
              module Element
         | 
| 3 | 
            +
                class ComplexError < Error
         | 
| 4 | 
            +
                  self.allowed_options << [:header_tag, :header_message, :message_tag, :message]
         | 
| 5 | 
            +
                  
         | 
| 6 | 
            +
                  # Generate all error messages as HTML <ul> list with optional header and message.
         | 
| 7 | 
            +
                  # 
         | 
| 8 | 
            +
                  def generate
         | 
| 9 | 
            +
                    contents = []
         | 
| 10 | 
            +
                    contents << template.content_tag(header_tag, header_message) unless options[:header_message] == false
         | 
| 11 | 
            +
                    contents << template.content_tag(message_tag, message)       unless options[:message] == false
         | 
| 12 | 
            +
                    contents << template.content_tag(:ul, error_messages)
         | 
| 13 | 
            +
                    
         | 
| 14 | 
            +
                    template.content_tag(error_tag, contents.join.html_safe, html_options)
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                  
         | 
| 17 | 
            +
                  private
         | 
| 18 | 
            +
                    # Distribute default options for complex errors.
         | 
| 19 | 
            +
                    #
         | 
| 20 | 
            +
                    def default_options
         | 
| 21 | 
            +
                      options[:class] ||= [:errors]
         | 
| 22 | 
            +
                      options[:id]    ||= "#{object_name}_errors"
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
                    
         | 
| 25 | 
            +
                    # Error messages as list.
         | 
| 26 | 
            +
                    #
         | 
| 27 | 
            +
                    # == Example:
         | 
| 28 | 
            +
                    #
         | 
| 29 | 
            +
                    #   # object.errors = { :name => ['can't be blank', 'should be uniq'],
         | 
| 30 | 
            +
                    #                       :price => 'should be more than 10' }
         | 
| 31 | 
            +
                    #
         | 
| 32 | 
            +
                    #   <ul>
         | 
| 33 | 
            +
                    #     <li>Name can't be blank</li>
         | 
| 34 | 
            +
                    #     <li>Name should be uniq</li>
         | 
| 35 | 
            +
                    #     <li>Price should be more than 10</li>
         | 
| 36 | 
            +
                    #   </ul>
         | 
| 37 | 
            +
                    #                 
         | 
| 38 | 
            +
                    def translated_list
         | 
| 39 | 
            +
                      (errors.full_messages.collect { |msg| template.content_tag :li, msg }).join.html_safe
         | 
| 40 | 
            +
                    end
         | 
| 41 | 
            +
                    
         | 
| 42 | 
            +
                    # Error messages as sentence.
         | 
| 43 | 
            +
                    #
         | 
| 44 | 
            +
                    # == Example:
         | 
| 45 | 
            +
                    #
         | 
| 46 | 
            +
                    #   # object.errors = { :name => ['can't be blank', 'should be uniq'],
         | 
| 47 | 
            +
                    #                       :price => 'should be more than 10' }
         | 
| 48 | 
            +
                    #
         | 
| 49 | 
            +
                    #   <ul>
         | 
| 50 | 
            +
                    #     <li>Name can't be blank and should be uniq</li>
         | 
| 51 | 
            +
                    #     <li>Price should be more than 10</li>
         | 
| 52 | 
            +
                    #   </ul>
         | 
| 53 | 
            +
                    #
         | 
| 54 | 
            +
                    def translated_sentence
         | 
| 55 | 
            +
                      (errors.full_sentences(:words_connector     => error_connector, 
         | 
| 56 | 
            +
                                             :last_word_connector => last_error_connector,
         | 
| 57 | 
            +
                                             :two_words_connector => last_error_connector).collect { |msg| template.content_tag :li, msg }).join.html_safe
         | 
| 58 | 
            +
                    end
         | 
| 59 | 
            +
                    
         | 
| 60 | 
            +
                    # Defined error header message HTML tag.
         | 
| 61 | 
            +
                    #
         | 
| 62 | 
            +
                    def header_tag
         | 
| 63 | 
            +
                      options.delete(:header_tag) || CaseForm.complex_error_header_tag
         | 
| 64 | 
            +
                    end
         | 
| 65 | 
            +
                    
         | 
| 66 | 
            +
                    # Defined error header message from option or I18n.
         | 
| 67 | 
            +
                    #
         | 
| 68 | 
            +
                    def header_message
         | 
| 69 | 
            +
                      options.delete(:header_message) || translated_header_message
         | 
| 70 | 
            +
                    end
         | 
| 71 | 
            +
                    
         | 
| 72 | 
            +
                    # Translated error header message by I18n.
         | 
| 73 | 
            +
                    #
         | 
| 74 | 
            +
                    def translated_header_message
         | 
| 75 | 
            +
                      lookups = []
         | 
| 76 | 
            +
                      lookups << :"activemodel.errors.template.header_message"
         | 
| 77 | 
            +
                      lookups << :"activerecord.errors.template.header_message"
         | 
| 78 | 
            +
                      lookups << :"case_form.errors.template.header_message"
         | 
| 79 | 
            +
                      lookups << "Some errors prohibited this object from being saved"
         | 
| 80 | 
            +
                      I18n.t(lookups.shift, :default => lookups)
         | 
| 81 | 
            +
                    end
         | 
| 82 | 
            +
                    
         | 
| 83 | 
            +
                    # Defined error message HTML tag.
         | 
| 84 | 
            +
                    #
         | 
| 85 | 
            +
                    def message_tag
         | 
| 86 | 
            +
                      options.delete(:message_tag) || CaseForm.complex_error_message_tag
         | 
| 87 | 
            +
                    end
         | 
| 88 | 
            +
                    
         | 
| 89 | 
            +
                    # Defined error message from option or I18n.
         | 
| 90 | 
            +
                    #
         | 
| 91 | 
            +
                    def message
         | 
| 92 | 
            +
                      options.delete(:message) || translated_message
         | 
| 93 | 
            +
                    end
         | 
| 94 | 
            +
                    
         | 
| 95 | 
            +
                    # Translated error message by I18n.
         | 
| 96 | 
            +
                    #
         | 
| 97 | 
            +
                    def translated_message
         | 
| 98 | 
            +
                      lookups = []
         | 
| 99 | 
            +
                      lookups << :"activemodel.errors.template.message"
         | 
| 100 | 
            +
                      lookups << :"activerecord.errors.template.message"
         | 
| 101 | 
            +
                      lookups << :"case_form.errors.template.message"
         | 
| 102 | 
            +
                      lookups << "There were problems with the following fields:"
         | 
| 103 | 
            +
                      I18n.t(lookups.shift, :default => lookups)
         | 
| 104 | 
            +
                    end
         | 
| 105 | 
            +
                end
         | 
| 106 | 
            +
              end
         | 
| 107 | 
            +
            end
         |