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,76 @@ | |
| 1 | 
            +
            module CaseForm
         | 
| 2 | 
            +
              module Element
         | 
| 3 | 
            +
                class SimpleError < Error
         | 
| 4 | 
            +
                  include ElementExt::Associationable
         | 
| 5 | 
            +
                  
         | 
| 6 | 
            +
                  attr_accessor :method
         | 
| 7 | 
            +
                  
         | 
| 8 | 
            +
                  # Initialize error object
         | 
| 9 | 
            +
                  # 
         | 
| 10 | 
            +
                  def initialize(builder, method, options={})
         | 
| 11 | 
            +
                    @method = method
         | 
| 12 | 
            +
                    super(builder, options)
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
                  
         | 
| 15 | 
            +
                  # Generate simple errors for method with HTML options
         | 
| 16 | 
            +
                  #
         | 
| 17 | 
            +
                  def generate
         | 
| 18 | 
            +
                    template.content_tag error_tag, error_messages, html_options
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                    
         | 
| 21 | 
            +
                  private
         | 
| 22 | 
            +
                    # Distribute default options for simple error.
         | 
| 23 | 
            +
                    #
         | 
| 24 | 
            +
                    def default_options
         | 
| 25 | 
            +
                      options[:class] ||= [:error]
         | 
| 26 | 
            +
                      options[:id]    ||= "#{sanitized_object_name}_#{method}_error"
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
                    
         | 
| 29 | 
            +
                    # Return all errors on method. If method is association than it takes also errors on association.
         | 
| 30 | 
            +
                    # == Example:
         | 
| 31 | 
            +
                    #   
         | 
| 32 | 
            +
                    #   # Get errors both on :country and :country_id attribute
         | 
| 33 | 
            +
                    #
         | 
| 34 | 
            +
                    #   class User
         | 
| 35 | 
            +
                    #     belongs_to :country
         | 
| 36 | 
            +
                    #     validates_presence_of :country_id
         | 
| 37 | 
            +
                    #     validates_inclusion_of :country, :in => Country.priority
         | 
| 38 | 
            +
                    #   end
         | 
| 39 | 
            +
                    #
         | 
| 40 | 
            +
                    def method_errors
         | 
| 41 | 
            +
                      association ? errors[method] + errors[association_method] : errors[method]
         | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
                    
         | 
| 44 | 
            +
                    # Error messages as list.
         | 
| 45 | 
            +
                    #
         | 
| 46 | 
            +
                    # == Example:
         | 
| 47 | 
            +
                    #
         | 
| 48 | 
            +
                    #   # object.errors[:name] = ['can't be blank', 'should be uniq']
         | 
| 49 | 
            +
                    #
         | 
| 50 | 
            +
                    #   <ul>
         | 
| 51 | 
            +
                    #     <li>can't be blank</li>
         | 
| 52 | 
            +
                    #     <li>should be uniq</li>
         | 
| 53 | 
            +
                    #   </ul>
         | 
| 54 | 
            +
                    #
         | 
| 55 | 
            +
                    def translated_list
         | 
| 56 | 
            +
                      template.content_tag :ul, (method_errors.collect { |msg| template.content_tag :li, msg }).join.html_safe
         | 
| 57 | 
            +
                    end
         | 
| 58 | 
            +
                    
         | 
| 59 | 
            +
                    # Error messages as sentence.
         | 
| 60 | 
            +
                    #
         | 
| 61 | 
            +
                    # == Example:
         | 
| 62 | 
            +
                    #
         | 
| 63 | 
            +
                    #   # object.errors[:name] = ['can't be blank', 'should be uniq']
         | 
| 64 | 
            +
                    #
         | 
| 65 | 
            +
                    #   <div>
         | 
| 66 | 
            +
                    #     can't be blank and should be uniq
         | 
| 67 | 
            +
                    #   </div>
         | 
| 68 | 
            +
                    #
         | 
| 69 | 
            +
                    def translated_sentence
         | 
| 70 | 
            +
                      method_errors.to_sentence(:words_connector     => error_connector, 
         | 
| 71 | 
            +
                                                :last_word_connector => last_error_connector,
         | 
| 72 | 
            +
                                                :two_words_connector => last_error_connector)
         | 
| 73 | 
            +
                    end
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
              end
         | 
| 76 | 
            +
            end
         | 
| @@ -0,0 +1,35 @@ | |
| 1 | 
            +
            # coding: utf-8
         | 
| 2 | 
            +
            module CaseForm
         | 
| 3 | 
            +
              module Element
         | 
| 4 | 
            +
                class Fieldset < Base
         | 
| 5 | 
            +
                  self.allowed_options << [:text]
         | 
| 6 | 
            +
                  
         | 
| 7 | 
            +
                  # Generate fieldset with defined arguments or block.
         | 
| 8 | 
            +
                  # Optional add legend tag if determined in options.
         | 
| 9 | 
            +
                  #
         | 
| 10 | 
            +
                  def generate(*args, &block)
         | 
| 11 | 
            +
                    contents, legend = [], text
         | 
| 12 | 
            +
                    contents << template.content_tag(:legend, legend) if legend
         | 
| 13 | 
            +
                    contents << if block_given? 
         | 
| 14 | 
            +
                      template.capture(&block) 
         | 
| 15 | 
            +
                    else
         | 
| 16 | 
            +
                      args
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
                    template.content_tag(:fieldset, contents.join.html_safe, html_options)
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                  
         | 
| 21 | 
            +
                  private
         | 
| 22 | 
            +
                    # Distribute default options for fieldset.
         | 
| 23 | 
            +
                    #
         | 
| 24 | 
            +
                    def default_options
         | 
| 25 | 
            +
                      options[:class] ||= [:fieldset]
         | 
| 26 | 
            +
                    end
         | 
| 27 | 
            +
                    
         | 
| 28 | 
            +
                    # Fieldset legend text.
         | 
| 29 | 
            +
                    #
         | 
| 30 | 
            +
                    def text
         | 
| 31 | 
            +
                      options.delete(:text)
         | 
| 32 | 
            +
                    end
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
            end
         | 
| @@ -0,0 +1,54 @@ | |
| 1 | 
            +
            module CaseForm
         | 
| 2 | 
            +
              module Element
         | 
| 3 | 
            +
                class Hint < Base
         | 
| 4 | 
            +
                  self.allowed_options << [:text, :tag]
         | 
| 5 | 
            +
                  
         | 
| 6 | 
            +
                  attr_accessor :method
         | 
| 7 | 
            +
                  
         | 
| 8 | 
            +
                  # Initialize hint's object
         | 
| 9 | 
            +
                  #
         | 
| 10 | 
            +
                  def initialize(builder, method, options={})
         | 
| 11 | 
            +
                    @method = method
         | 
| 12 | 
            +
                    super(builder, options)
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
                  
         | 
| 15 | 
            +
                  # Generate hint with defined text and HTML options
         | 
| 16 | 
            +
                  #   
         | 
| 17 | 
            +
                  def generate
         | 
| 18 | 
            +
                    template.content_tag(hint_tag, text, html_options)
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                  
         | 
| 21 | 
            +
                  private
         | 
| 22 | 
            +
                    # Distribute default options for hint.
         | 
| 23 | 
            +
                    #
         | 
| 24 | 
            +
                    def default_options
         | 
| 25 | 
            +
                      options[:class] ||= [:hint]
         | 
| 26 | 
            +
                      options[:id]    ||= "#{sanitized_object_name}_#{method.to_s.underscore}_hint"
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
                    
         | 
| 29 | 
            +
                    # Generate hint's text. By default it use :text option, entered string or translated with I18n method. 
         | 
| 30 | 
            +
                    #
         | 
| 31 | 
            +
                    def text
         | 
| 32 | 
            +
                      if options[:text]
         | 
| 33 | 
            +
                        options.delete(:text)
         | 
| 34 | 
            +
                      elsif method.is_a?(String)
         | 
| 35 | 
            +
                        method
         | 
| 36 | 
            +
                      else
         | 
| 37 | 
            +
                        translated_text
         | 
| 38 | 
            +
                      end
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
                    
         | 
| 41 | 
            +
                    # Translate hint's text with I18n.
         | 
| 42 | 
            +
                    #
         | 
| 43 | 
            +
                    def translated_text
         | 
| 44 | 
            +
                      I18n.t(:"#{object_name}.#{method}", :scope => :"case_form.hints")
         | 
| 45 | 
            +
                    end
         | 
| 46 | 
            +
                    
         | 
| 47 | 
            +
                    # Default hint's tag
         | 
| 48 | 
            +
                    #
         | 
| 49 | 
            +
                    def hint_tag
         | 
| 50 | 
            +
                      options.delete(:tag) || CaseForm.hint_tag
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
            end
         | 
| @@ -0,0 +1,106 @@ | |
| 1 | 
            +
            # coding: utf-8
         | 
| 2 | 
            +
            module CaseForm
         | 
| 3 | 
            +
              module Element
         | 
| 4 | 
            +
                class Input < Base
         | 
| 5 | 
            +
                  include ElementExt::Validationable
         | 
| 6 | 
            +
                  include ElementExt::Columnable
         | 
| 7 | 
            +
                  
         | 
| 8 | 
            +
                  self.allowed_options << [:autofocus, :required, :label, :error, :hint]
         | 
| 9 | 
            +
                  
         | 
| 10 | 
            +
                  attr_accessor :method
         | 
| 11 | 
            +
                  
         | 
| 12 | 
            +
                  def initialize(builder, method, options={})
         | 
| 13 | 
            +
                    @method = method
         | 
| 14 | 
            +
                    super(builder, options)
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                  
         | 
| 17 | 
            +
                  def generate
         | 
| 18 | 
            +
                    template.content_tag wrapper_tag, contents, wrapper_options
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                  
         | 
| 21 | 
            +
                  private
         | 
| 22 | 
            +
                    def default_options
         | 
| 23 | 
            +
                      options[:class]    ||= [:input]
         | 
| 24 | 
            +
                      options[:required] ||= required?
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
                    
         | 
| 27 | 
            +
                    def wrapper_options
         | 
| 28 | 
            +
                      wrapper_options = super
         | 
| 29 | 
            +
                      wrapper_options[:class] << :element
         | 
| 30 | 
            +
                      wrapper_options
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
                    
         | 
| 33 | 
            +
                    def input_elements
         | 
| 34 | 
            +
                      CaseForm.input_elements
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
                    
         | 
| 37 | 
            +
                    def contents
         | 
| 38 | 
            +
                      contents = []
         | 
| 39 | 
            +
                      input_elements.each do |element| 
         | 
| 40 | 
            +
                        if options[element] == false
         | 
| 41 | 
            +
                          options.delete(element)
         | 
| 42 | 
            +
                          next
         | 
| 43 | 
            +
                        else
         | 
| 44 | 
            +
                          contents << send(element)
         | 
| 45 | 
            +
                        end
         | 
| 46 | 
            +
                      end
         | 
| 47 | 
            +
                      contents.join.html_safe
         | 
| 48 | 
            +
                    end
         | 
| 49 | 
            +
                    
         | 
| 50 | 
            +
                    def label
         | 
| 51 | 
            +
                      Element::Label.new(builder, method, label_options.merge(:required => required?)).generate
         | 
| 52 | 
            +
                    end
         | 
| 53 | 
            +
                    
         | 
| 54 | 
            +
                    def label_options
         | 
| 55 | 
            +
                      label_options = options.delete(:label) || {}
         | 
| 56 | 
            +
                      label_options.is_a?(String) ? { :text => label_options } : label_options
         | 
| 57 | 
            +
                    end
         | 
| 58 | 
            +
                    
         | 
| 59 | 
            +
                    def input
         | 
| 60 | 
            +
                      raise(NotImplementedInput)
         | 
| 61 | 
            +
                    end
         | 
| 62 | 
            +
                    
         | 
| 63 | 
            +
                    def input_options
         | 
| 64 | 
            +
                      options.except(:label, :error, :hint)
         | 
| 65 | 
            +
                    end
         | 
| 66 | 
            +
                    
         | 
| 67 | 
            +
                    def error
         | 
| 68 | 
            +
                      Element::SimpleError.new(builder, method, error_options).generate if error?
         | 
| 69 | 
            +
                    end
         | 
| 70 | 
            +
                    
         | 
| 71 | 
            +
                    def error?
         | 
| 72 | 
            +
                      object.errors[method].any? || object.errors[specific_method].any?
         | 
| 73 | 
            +
                    end
         | 
| 74 | 
            +
                    
         | 
| 75 | 
            +
                    def error_options
         | 
| 76 | 
            +
                      options.delete(:error) || {}
         | 
| 77 | 
            +
                    end
         | 
| 78 | 
            +
                    
         | 
| 79 | 
            +
                    def hint
         | 
| 80 | 
            +
                      Element::Hint.new(builder, method, hint_options).generate if hint?
         | 
| 81 | 
            +
                    end
         | 
| 82 | 
            +
                    
         | 
| 83 | 
            +
                    def hint?
         | 
| 84 | 
            +
                      options[:hint].present? || !I18n.t(:"#{object_name}.#{method}", :scope => :"case_form.hints", :default => '').blank?
         | 
| 85 | 
            +
                    end
         | 
| 86 | 
            +
                    
         | 
| 87 | 
            +
                    def hint_options
         | 
| 88 | 
            +
                      hint_options = options.delete(:hint) || {}
         | 
| 89 | 
            +
                      hint_options.is_a?(String) ? { :text => hint_options } : hint_options
         | 
| 90 | 
            +
                    end
         | 
| 91 | 
            +
                    
         | 
| 92 | 
            +
                    def input_size
         | 
| 93 | 
            +
                      validations = object.class.validators_on(method).select { |v| v.kind == :length }
         | 
| 94 | 
            +
                      if validations.any?
         | 
| 95 | 
            +
                        validations.first.options[:maximum]
         | 
| 96 | 
            +
                      else
         | 
| 97 | 
            +
                        CaseForm.input_size
         | 
| 98 | 
            +
                      end
         | 
| 99 | 
            +
                    end
         | 
| 100 | 
            +
                    
         | 
| 101 | 
            +
                    def input_type
         | 
| 102 | 
            +
                      options[:as]
         | 
| 103 | 
            +
                    end
         | 
| 104 | 
            +
                end
         | 
| 105 | 
            +
              end
         | 
| 106 | 
            +
            end
         | 
| @@ -0,0 +1,36 @@ | |
| 1 | 
            +
            # coding: utf-8
         | 
| 2 | 
            +
            module CaseForm
         | 
| 3 | 
            +
              module Element
         | 
| 4 | 
            +
                class CheckboxInput < CollectionInput
         | 
| 5 | 
            +
                  self.allowed_options << [:unchecked_value, :allow_multiple]
         | 
| 6 | 
            +
                  
         | 
| 7 | 
            +
                  private
         | 
| 8 | 
            +
                    def default_options
         | 
| 9 | 
            +
                      super
         | 
| 10 | 
            +
                      options[:unchecked_value] ||= ''
         | 
| 11 | 
            +
                      options[:checked]           = checked_values
         | 
| 12 | 
            +
                      options[:allow_multiple]  ||= multiple_collection?
         | 
| 13 | 
            +
                      options[:multiple]          = true if options[:allow_multiple] == true
         | 
| 14 | 
            +
                    end
         | 
| 15 | 
            +
                    
         | 
| 16 | 
            +
                    def input
         | 
| 17 | 
            +
                      collection.map do |element|
         | 
| 18 | 
            +
                        label, value  = element.first, element.last
         | 
| 19 | 
            +
                        checkbox_id   = "#{sanitized_object_name}_#{specific_method}_#{value}"
         | 
| 20 | 
            +
                        label_options = { :text     => label, 
         | 
| 21 | 
            +
                                          :required => false,
         | 
| 22 | 
            +
                                          :id       => "#{checkbox_id}_label", 
         | 
| 23 | 
            +
                                          :class    => :inline_label,
         | 
| 24 | 
            +
                                          :for      => checkbox_id }
         | 
| 25 | 
            +
                        
         | 
| 26 | 
            +
                        builder.check_box(specific_method, html_options.merge(html_options_for_value(value).merge!(:id => checkbox_id)), value, options[:unchecked_value]) <<
         | 
| 27 | 
            +
                          builder.label(specific_method, label_options)
         | 
| 28 | 
            +
                      end.join.html_safe
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
                    
         | 
| 31 | 
            +
                    def boolean_collection
         | 
| 32 | 
            +
                      [super.first]
         | 
| 33 | 
            +
                    end
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
            end
         | 
| @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            # coding: utf-8
         | 
| 2 | 
            +
            module CaseForm
         | 
| 3 | 
            +
              module Element
         | 
| 4 | 
            +
                class RadioInput < CollectionInput
         | 
| 5 | 
            +
                  private
         | 
| 6 | 
            +
                    def default_options
         | 
| 7 | 
            +
                      super
         | 
| 8 | 
            +
                      options[:checked] = checked_values
         | 
| 9 | 
            +
                    end
         | 
| 10 | 
            +
                    
         | 
| 11 | 
            +
                    def input
         | 
| 12 | 
            +
                      collection.map do |element|
         | 
| 13 | 
            +
                        label, value  = element.first, element.last
         | 
| 14 | 
            +
                        radio_id      = "#{sanitized_object_name}_#{specific_method}_#{value}"
         | 
| 15 | 
            +
                        label_options = { :text     => label, 
         | 
| 16 | 
            +
                                          :required => false,
         | 
| 17 | 
            +
                                          :id       => "#{radio_id}_label", 
         | 
| 18 | 
            +
                                          :class    => :inline_label, 
         | 
| 19 | 
            +
                                          :for      => radio_id }
         | 
| 20 | 
            +
                        
         | 
| 21 | 
            +
                        builder.radio_button(specific_method, value, html_options.merge(html_options_for_value(value)).merge!(:id => radio_id)) << 
         | 
| 22 | 
            +
                          builder.label(specific_method, label_options)
         | 
| 23 | 
            +
                      end.join.html_safe
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
            end
         | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            # coding: utf-8
         | 
| 2 | 
            +
            module CaseForm
         | 
| 3 | 
            +
              module Element
         | 
| 4 | 
            +
                class SelectInput < CollectionInput
         | 
| 5 | 
            +
                  self.allowed_options << [:prompt, :blank, :allow_multiple, :size]
         | 
| 6 | 
            +
                  
         | 
| 7 | 
            +
                  private
         | 
| 8 | 
            +
                    def default_options
         | 
| 9 | 
            +
                      super
         | 
| 10 | 
            +
                      options[:selected]         = checked_values
         | 
| 11 | 
            +
                      options[:allow_multiple] ||= multiple_collection?
         | 
| 12 | 
            +
                      options[:multiple]         = true if options[:allow_multiple] == true
         | 
| 13 | 
            +
                      options[:blank]          ||= true
         | 
| 14 | 
            +
                      options[:include_blank]    = options.delete(:blank)
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
                    
         | 
| 17 | 
            +
                    def input
         | 
| 18 | 
            +
                      template.select(object_name, specific_method, collection, options, html_options)
         | 
| 19 | 
            +
                    end
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
            end
         | 
| @@ -0,0 +1,89 @@ | |
| 1 | 
            +
            # coding: utf-8
         | 
| 2 | 
            +
            module CaseForm
         | 
| 3 | 
            +
              module Element
         | 
| 4 | 
            +
                class CollectionInput < Input
         | 
| 5 | 
            +
                  include ElementExt::Associationable
         | 
| 6 | 
            +
                  
         | 
| 7 | 
            +
                  self.allowed_options << [:disabled, :checked, :selected, :readonly, 
         | 
| 8 | 
            +
                                           :collection, :label_method, :value_method]
         | 
| 9 | 
            +
                                           
         | 
| 10 | 
            +
                  private
         | 
| 11 | 
            +
                    def default_options
         | 
| 12 | 
            +
                      super
         | 
| 13 | 
            +
                      options[:collection] ||= default_collection
         | 
| 14 | 
            +
                    end
         | 
| 15 | 
            +
                    
         | 
| 16 | 
            +
                    def html_options
         | 
| 17 | 
            +
                      super.except(:disabled, :selected, :checked)
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
                    
         | 
| 20 | 
            +
                    def default_collection
         | 
| 21 | 
            +
                      association ? extract_from_association_array(association_class.all) : boolean_collection
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
                    
         | 
| 24 | 
            +
                    def boolean_collection
         | 
| 25 | 
            +
                      [[I18n.t(:"case_form.yes", :default => "Yes"), true], 
         | 
| 26 | 
            +
                       [I18n.t(:"case_form.no", :default => "No"), false]]
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
                    
         | 
| 29 | 
            +
                    def collection_is_association_class?
         | 
| 30 | 
            +
                      association && options[:collection] == association.klass
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
                    
         | 
| 33 | 
            +
                    def collection
         | 
| 34 | 
            +
                      @collection ||= if collection_is_association_class? #:nodoc only class defined, example: :collection => User
         | 
| 35 | 
            +
                        association_class.all
         | 
| 36 | 
            +
                      else
         | 
| 37 | 
            +
                        options[:collection].to_a
         | 
| 38 | 
            +
                      end
         | 
| 39 | 
            +
                      extract_collection(@collection)
         | 
| 40 | 
            +
                    end
         | 
| 41 | 
            +
                    
         | 
| 42 | 
            +
                    def extract_collection(collection)
         | 
| 43 | 
            +
                      return case collection.first
         | 
| 44 | 
            +
                      when String, Integer, Symbol
         | 
| 45 | 
            +
                        Array.new(collection).collect! { |c| [c, c] }
         | 
| 46 | 
            +
                      when association_class
         | 
| 47 | 
            +
                        extract_from_association_array(collection)
         | 
| 48 | 
            +
                      else 
         | 
| 49 | 
            +
                        collection
         | 
| 50 | 
            +
                      end
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
                    
         | 
| 53 | 
            +
                    def extract_from_association_array(array)
         | 
| 54 | 
            +
                      if sample = array.first
         | 
| 55 | 
            +
                        label_method ||= options[:label_method] || collection_methods(:label, sample)
         | 
| 56 | 
            +
                        value_method ||= options[:value_method] || collection_methods(:value, sample)
         | 
| 57 | 
            +
                        array.map { |o| [o.send(label_method), o.send(value_method)] }
         | 
| 58 | 
            +
                      else
         | 
| 59 | 
            +
                        [[I18n.t(:"case_form.no_items", :default => "No #{sample.class.to_s.pluralize}"), '']]
         | 
| 60 | 
            +
                      end
         | 
| 61 | 
            +
                    end
         | 
| 62 | 
            +
                    
         | 
| 63 | 
            +
                    def collection_methods(type, sample)
         | 
| 64 | 
            +
                      CaseForm.send(:"collection_#{type}_methods").find { |m| sample.respond_to?(m.to_sym) }
         | 
| 65 | 
            +
                    end
         | 
| 66 | 
            +
                    
         | 
| 67 | 
            +
                    def multiple_collection?
         | 
| 68 | 
            +
                      association ? (association_type?(:belongs_to) ? false : true) : false
         | 
| 69 | 
            +
                    end
         | 
| 70 | 
            +
                    
         | 
| 71 | 
            +
                    def html_options_for_value(value)
         | 
| 72 | 
            +
                      new_options = {}
         | 
| 73 | 
            +
                      [:checked, :selected, :disabled].each do |option|
         | 
| 74 | 
            +
                        next unless options[option]
         | 
| 75 | 
            +
                        new_options[option] = [options[option]].flatten.include?(value) ? true : false
         | 
| 76 | 
            +
                      end
         | 
| 77 | 
            +
                      new_options
         | 
| 78 | 
            +
                    end
         | 
| 79 | 
            +
                    
         | 
| 80 | 
            +
                    def object_input_ids
         | 
| 81 | 
            +
                      @input_ids ||= (association ? object.send(association_method) : [])
         | 
| 82 | 
            +
                    end
         | 
| 83 | 
            +
                    
         | 
| 84 | 
            +
                    def checked_values
         | 
| 85 | 
            +
                      [options.delete(:checked), options.delete(:selected), object_input_ids].flatten.uniq
         | 
| 86 | 
            +
                    end
         | 
| 87 | 
            +
                end
         | 
| 88 | 
            +
              end
         | 
| 89 | 
            +
            end
         |