active_scaffold 3.4.43 → 3.5.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.
- checksums.yaml +4 -4
- data/CHANGELOG +39 -0
- data/{LICENSE → LICENSE.md} +1 -1
- data/README.md +27 -19
- data/app/assets/javascripts/active_scaffold.js.erb +1 -1
- data/app/assets/javascripts/jquery/active_scaffold.js +95 -43
- data/app/assets/javascripts/jquery/tiny_mce_bridge.js +30 -6
- data/app/assets/javascripts/prototype/tiny_mce_bridge.js +11 -1
- data/app/assets/stylesheets/active_scaffold_colors.scss +2 -2
- data/app/assets/stylesheets/active_scaffold_layout.css +36 -28
- data/app/views/active_scaffold_overrides/_base_form.html.erb +2 -3
- data/app/views/active_scaffold_overrides/_field_search.html.erb +8 -7
- data/app/views/active_scaffold_overrides/_form_association.html.erb +9 -9
- data/app/views/active_scaffold_overrides/_form_association_footer.html.erb +6 -6
- data/app/views/active_scaffold_overrides/_form_association_record.html.erb +52 -50
- data/app/views/active_scaffold_overrides/_horizontal_subform.html.erb +1 -1
- data/app/views/active_scaffold_overrides/_horizontal_subform_header.html.erb +1 -1
- data/app/views/active_scaffold_overrides/_human_conditions.html.erb +3 -1
- data/app/views/active_scaffold_overrides/_list_calculations.html.erb +1 -1
- data/app/views/active_scaffold_overrides/_list_column_headings.html.erb +2 -0
- data/app/views/active_scaffold_overrides/_list_messages.html.erb +5 -3
- data/app/views/active_scaffold_overrides/_list_record.html.erb +3 -1
- data/app/views/active_scaffold_overrides/_list_with_header.html.erb +9 -9
- data/app/views/active_scaffold_overrides/_messages.html.erb +1 -1
- data/app/views/active_scaffold_overrides/_refresh_list.js.erb +18 -10
- data/app/views/active_scaffold_overrides/_render_field.js.erb +3 -3
- data/app/views/active_scaffold_overrides/_search.html.erb +7 -6
- data/app/views/active_scaffold_overrides/_show_actions.html.erb +14 -0
- data/app/views/active_scaffold_overrides/_show_association.html.erb +1 -1
- data/app/views/active_scaffold_overrides/_update_actions.html.erb +6 -2
- data/app/views/active_scaffold_overrides/_update_column.js.erb +1 -1
- data/app/views/active_scaffold_overrides/_update_form.html.erb +1 -1
- data/app/views/active_scaffold_overrides/destroy.js.erb +2 -3
- data/app/views/active_scaffold_overrides/edit_associated.js.erb +4 -3
- data/app/views/active_scaffold_overrides/on_action_update.js.erb +5 -3
- data/app/views/active_scaffold_overrides/on_create.js.erb +4 -4
- data/app/views/active_scaffold_overrides/on_update.js.erb +6 -6
- data/app/views/active_scaffold_overrides/show.html.erb +6 -0
- data/app/views/active_scaffold_overrides/update.html.erb +1 -1
- data/app/views/active_scaffold_overrides/update_column.js.erb +1 -1
- data/config/brakeman.ignore +26 -0
- data/config/brakeman.yml +3 -0
- data/config/i18n-tasks.yml +121 -0
- data/config/locales/de.yml +81 -70
- data/config/locales/en.yml +83 -74
- data/config/locales/es.yml +82 -73
- data/config/locales/fr.yml +86 -75
- data/config/locales/hu.yml +81 -70
- data/config/locales/ja.yml +71 -60
- data/config/locales/ru.yml +85 -74
- data/lib/active_scaffold.rb +3 -0
- data/lib/active_scaffold/actions/common_search.rb +11 -7
- data/lib/active_scaffold/actions/core.rb +119 -47
- data/lib/active_scaffold/actions/create.rb +1 -1
- data/lib/active_scaffold/actions/delete.rb +11 -8
- data/lib/active_scaffold/actions/field_search.rb +104 -6
- data/lib/active_scaffold/actions/list.rb +25 -21
- data/lib/active_scaffold/actions/mark.rb +12 -4
- data/lib/active_scaffold/actions/nested.rb +26 -26
- data/lib/active_scaffold/actions/search.rb +2 -2
- data/lib/active_scaffold/actions/show.rb +4 -5
- data/lib/active_scaffold/actions/subform.rb +9 -7
- data/lib/active_scaffold/actions/update.rb +20 -13
- data/lib/active_scaffold/active_record_permissions.rb +24 -5
- data/lib/active_scaffold/attribute_params.rb +68 -49
- data/lib/active_scaffold/bridges.rb +1 -1
- data/lib/active_scaffold/bridges/ancestry/ancestry_bridge.rb +15 -19
- data/lib/active_scaffold/bridges/bitfields.rb +1 -1
- data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +10 -14
- data/lib/active_scaffold/bridges/calendar_date_select.rb +0 -7
- data/lib/active_scaffold/bridges/calendar_date_select/as_cds_bridge.rb +19 -22
- data/lib/active_scaffold/bridges/cancan.rb +4 -3
- data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +11 -21
- data/lib/active_scaffold/bridges/carrierwave.rb +2 -1
- data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge.rb +2 -6
- data/lib/active_scaffold/bridges/carrierwave/form_ui.rb +6 -39
- data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +1 -1
- data/lib/active_scaffold/bridges/chosen.rb +4 -1
- data/lib/active_scaffold/bridges/chosen/helpers.rb +3 -2
- data/lib/active_scaffold/bridges/country_select/country_select_bridge_helper.rb +2 -2
- data/lib/active_scaffold/bridges/date_picker.rb +3 -0
- data/lib/active_scaffold/bridges/date_picker/ext.rb +43 -38
- data/lib/active_scaffold/bridges/date_picker/helper.rb +24 -23
- data/lib/active_scaffold/bridges/dragonfly.rb +1 -1
- data/lib/active_scaffold/bridges/dragonfly/dragonfly_bridge.rb +3 -7
- data/lib/active_scaffold/bridges/dragonfly/form_ui.rb +3 -25
- data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +2 -2
- data/lib/active_scaffold/bridges/file_column/as_file_column_bridge.rb +6 -8
- data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +1 -1
- data/lib/active_scaffold/bridges/file_column/form_ui.rb +0 -2
- data/lib/active_scaffold/bridges/file_column/list_ui.rb +2 -1
- data/lib/active_scaffold/bridges/file_column/test/test_helper.rb +1 -1
- data/lib/active_scaffold/bridges/paper_trail/actions.rb +1 -1
- data/lib/active_scaffold/bridges/paper_trail/helper.rb +1 -2
- data/lib/active_scaffold/bridges/paper_trail/paper_trail_bridge.rb +3 -7
- data/lib/active_scaffold/bridges/paperclip.rb +1 -1
- data/lib/active_scaffold/bridges/paperclip/form_ui.rb +3 -28
- data/lib/active_scaffold/bridges/paperclip/list_ui.rb +1 -1
- data/lib/active_scaffold/bridges/paperclip/paperclip_bridge.rb +3 -7
- data/lib/active_scaffold/bridges/record_select.rb +2 -0
- data/lib/active_scaffold/bridges/record_select/helpers.rb +14 -18
- data/lib/active_scaffold/bridges/semantic_attributes/column.rb +4 -8
- data/lib/active_scaffold/bridges/shared/date_bridge.rb +20 -20
- data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +7 -22
- data/lib/active_scaffold/bridges/usa_state_select/usa_state_select_helper.rb +14 -14
- data/lib/active_scaffold/config/base.rb +9 -6
- data/lib/active_scaffold/config/core.rb +30 -21
- data/lib/active_scaffold/config/create.rb +2 -1
- data/lib/active_scaffold/config/delete.rb +2 -2
- data/lib/active_scaffold/config/field_search.rb +9 -3
- data/lib/active_scaffold/config/form.rb +4 -4
- data/lib/active_scaffold/config/list.rb +27 -23
- data/lib/active_scaffold/config/nested.rb +4 -4
- data/lib/active_scaffold/config/search.rb +6 -6
- data/lib/active_scaffold/config/show.rb +11 -1
- data/lib/active_scaffold/config/subform.rb +1 -1
- data/lib/active_scaffold/config/update.rb +4 -2
- data/lib/active_scaffold/constraints.rb +39 -36
- data/lib/active_scaffold/core.rb +36 -15
- data/lib/active_scaffold/data_structures/action_columns.rb +14 -9
- data/lib/active_scaffold/data_structures/action_link.rb +4 -5
- data/lib/active_scaffold/data_structures/action_links.rb +5 -4
- data/lib/active_scaffold/data_structures/actions.rb +2 -2
- data/lib/active_scaffold/data_structures/association.rb +8 -0
- data/lib/active_scaffold/data_structures/association/abstract.rb +147 -0
- data/lib/active_scaffold/data_structures/association/active_mongoid.rb +42 -0
- data/lib/active_scaffold/data_structures/association/active_record.rb +94 -0
- data/lib/active_scaffold/data_structures/association/mongoid.rb +45 -0
- data/lib/active_scaffold/data_structures/bridge.rb +3 -6
- data/lib/active_scaffold/data_structures/column.rb +100 -82
- data/lib/active_scaffold/data_structures/columns.rb +21 -3
- data/lib/active_scaffold/data_structures/nested_info.rb +22 -37
- data/lib/active_scaffold/data_structures/set.rb +4 -4
- data/lib/active_scaffold/data_structures/sorting.rb +29 -15
- data/lib/active_scaffold/engine.rb +3 -1
- data/lib/active_scaffold/extensions/action_controller_rendering.rb +10 -5
- data/lib/active_scaffold/extensions/action_view_rendering.rb +65 -59
- data/lib/active_scaffold/extensions/left_outer_joins.rb +48 -53
- data/lib/active_scaffold/extensions/localize.rb +3 -4
- data/lib/active_scaffold/extensions/name_option_for_datetime.rb +7 -11
- data/lib/active_scaffold/extensions/paginator_extensions.rb +20 -18
- data/lib/active_scaffold/extensions/routing_mapper.rb +104 -40
- data/lib/active_scaffold/extensions/to_label.rb +1 -1
- data/lib/active_scaffold/extensions/unsaved_associated.rb +4 -13
- data/lib/active_scaffold/extensions/unsaved_record.rb +12 -1
- data/lib/active_scaffold/finder.rb +200 -134
- data/lib/active_scaffold/helpers/action_link_helpers.rb +398 -0
- data/lib/active_scaffold/helpers/association_helpers.rb +12 -30
- data/lib/active_scaffold/helpers/controller_helpers.rb +74 -24
- data/lib/active_scaffold/helpers/form_column_helpers.rb +205 -112
- data/lib/active_scaffold/helpers/human_condition_helpers.rb +21 -11
- data/lib/active_scaffold/helpers/id_helpers.rb +1 -1
- data/lib/active_scaffold/helpers/list_column_helpers.rb +117 -39
- data/lib/active_scaffold/helpers/pagination_helpers.rb +11 -14
- data/lib/active_scaffold/helpers/search_column_helpers.rb +69 -32
- data/lib/active_scaffold/helpers/show_column_helpers.rb +9 -3
- data/lib/active_scaffold/helpers/view_helpers.rb +41 -426
- data/lib/active_scaffold/orm_checks.rb +109 -0
- data/lib/active_scaffold/paginator.rb +1 -1
- data/lib/active_scaffold/responds_to_parent.rb +12 -10
- data/lib/active_scaffold/tableless.rb +81 -43
- data/lib/active_scaffold/version.rb +2 -2
- data/lib/generators/active_scaffold/controller_generator.rb +49 -0
- data/lib/generators/active_scaffold/install_generator.rb +45 -0
- data/lib/generators/active_scaffold/resource_generator.rb +56 -0
- data/lib/generators/{active_scaffold_controller/templates → templates}/controller.rb +0 -0
- data/lib/generators/{active_scaffold_controller/templates → templates}/helper.rb +0 -0
- data/shoulda_macros/macros.rb +3 -3
- data/test/active_scaffold_config_mock.rb +33 -0
- data/test/bridges/bridge_test.rb +9 -9
- data/test/bridges/date_picker_test.rb +3 -1
- data/test/bridges/paper_trail_test.rb +2 -3
- data/test/bridges/paperclip_test.rb +21 -10
- data/test/bridges/tiny_mce_test.rb +20 -21
- data/test/class_with_finder.rb +42 -0
- data/test/company.rb +6 -4
- data/test/config/core_test.rb +1 -1
- data/test/config/create_test.rb +1 -1
- data/test/config/list_test.rb +3 -3
- data/test/config/update_test.rb +3 -3
- data/test/data_structures/action_columns_test.rb +3 -3
- data/test/data_structures/association_column_test.rb +5 -5
- data/test/data_structures/column_test.rb +14 -14
- data/test/data_structures/columns_test.rb +2 -2
- data/test/data_structures/set_test.rb +2 -2
- data/test/data_structures/sorting_test.rb +6 -4
- data/test/extensions/active_record_test.rb +1 -1
- data/test/extensions/routing_mapper_test.rb +64 -13
- data/test/helpers/form_column_helpers_test.rb +6 -6
- data/test/helpers/list_column_helpers_test.rb +9 -5
- data/test/helpers/pagination_helpers_test.rb +1 -0
- data/test/misc/active_record_permissions_test.rb +18 -1
- data/test/misc/attribute_params_test.rb +26 -17
- data/test/misc/calculation_test.rb +8 -31
- data/test/misc/configurable_test.rb +3 -2
- data/test/misc/constraints_test.rb +33 -22
- data/test/misc/convert_numbers_format_test.rb +28 -10
- data/test/misc/finder_test.rb +6 -29
- data/test/misc/parse_datetime_test.rb +160 -0
- data/test/misc/render_test.rb +1 -1
- data/test/misc/tableless_test.rb +24 -0
- data/test/mock_app/app/models/building.rb +2 -1
- data/test/mock_app/config.ru +1 -1
- data/test/mock_app/config/environments/test.rb +1 -1
- data/test/mock_app/config/routes.rb +11 -3
- data/test/model_stub.rb +11 -6
- data/test/run_all.rb +1 -1
- data/test/test_helper.rb +19 -4
- metadata +42 -23
- data/lib/active_scaffold/data_structures/error_message.rb +0 -22
- data/lib/active_scaffold/extensions/reverse_associations.rb +0 -119
- data/lib/generators/active_scaffold/USAGE +0 -29
- data/lib/generators/active_scaffold/active_scaffold_generator.rb +0 -21
- data/lib/generators/active_scaffold_controller/USAGE +0 -19
- data/lib/generators/active_scaffold_controller/active_scaffold_controller_generator.rb +0 -29
- data/test/data_structures/error_message_test.rb +0 -25
| @@ -15,9 +15,17 @@ module ActiveScaffold | |
| 15 15 | 
             
                    end
         | 
| 16 16 | 
             
                  end
         | 
| 17 17 |  | 
| 18 | 
            +
                  def active_scaffold_grouped_by_label
         | 
| 19 | 
            +
                    text, = active_scaffold_config.field_search.group_options.find do |text, value|
         | 
| 20 | 
            +
                      (value || text).to_s == field_search_params['active_scaffold_group']
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
                    active_scaffold_translated_option(active_scaffold_group_column, text).first if text
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 18 25 | 
             
                  def format_human_condition(column, opt, from = nil, to = nil)
         | 
| 19 26 | 
             
                    attribute = column.active_record_class.human_attribute_name(column.name)
         | 
| 20 | 
            -
                    opt ||=  | 
| 27 | 
            +
                    opt ||= :between if from && to
         | 
| 28 | 
            +
                    opt ||= from ? '>=' : '<='
         | 
| 21 29 | 
             
                    "#{attribute} #{as_(opt).downcase} #{from} #{to}"
         | 
| 22 30 | 
             
                  end
         | 
| 23 31 |  | 
| @@ -26,8 +34,8 @@ module ActiveScaffold | |
| 26 34 | 
             
                    to = "- #{format_number_value(controller.class.condition_value_for_numeric(column, value['to']), column.options)}" if value['opt'] == 'BETWEEN'
         | 
| 27 35 | 
             
                    format_human_condition column, value['opt'].downcase, from, to
         | 
| 28 36 | 
             
                  end
         | 
| 29 | 
            -
                   | 
| 30 | 
            -
                   | 
| 37 | 
            +
                  alias active_scaffold_human_condition_decimal active_scaffold_human_condition_integer
         | 
| 38 | 
            +
                  alias active_scaffold_human_condition_float active_scaffold_human_condition_integer
         | 
| 31 39 |  | 
| 32 40 | 
             
                  def active_scaffold_human_condition_string(column, value)
         | 
| 33 41 | 
             
                    opt = ActiveScaffold::Finder::STRING_COMPARATORS.key(value['opt']) || value['opt']
         | 
| @@ -43,16 +51,16 @@ module ActiveScaffold | |
| 43 51 | 
             
                    to = "- #{I18n.l to}" if to
         | 
| 44 52 | 
             
                    format_human_condition column, value['opt'], from, to
         | 
| 45 53 | 
             
                  end
         | 
| 46 | 
            -
                   | 
| 47 | 
            -
                   | 
| 48 | 
            -
                   | 
| 54 | 
            +
                  alias active_scaffold_human_condition_time active_scaffold_human_condition_date
         | 
| 55 | 
            +
                  alias active_scaffold_human_condition_datetime active_scaffold_human_condition_date
         | 
| 56 | 
            +
                  alias active_scaffold_human_condition_timestamp active_scaffold_human_condition_date
         | 
| 49 57 |  | 
| 50 58 | 
             
                  def active_scaffold_human_condition_boolean(column, value)
         | 
| 51 59 | 
             
                    attribute = column.active_record_class.human_attribute_name(column.name)
         | 
| 52 60 | 
             
                    label = as_(ActiveScaffold::Core.column_type_cast(value, column.column) ? :true : :false)
         | 
| 53 61 | 
             
                    as_(:boolean, :scope => :human_conditions, :column => attribute, :value => label)
         | 
| 54 62 | 
             
                  end
         | 
| 55 | 
            -
                   | 
| 63 | 
            +
                  alias active_scaffold_human_condition_checkbox active_scaffold_human_condition_boolean
         | 
| 56 64 |  | 
| 57 65 | 
             
                  def active_scaffold_human_condition_null(column, value)
         | 
| 58 66 | 
             
                    format_human_condition column, value.to_sym
         | 
| @@ -66,21 +74,23 @@ module ActiveScaffold | |
| 66 74 | 
             
                      associated = column.association.klass.where(:id => associated.map(&:to_i)).map(&method)
         | 
| 67 75 | 
             
                    elsif column.options[:options]
         | 
| 68 76 | 
             
                      associated = associated.collect do |value|
         | 
| 69 | 
            -
                        text, val = column.options[:options].find { | | 
| 77 | 
            +
                        text, val = column.options[:options].find { |t, v| (v.nil? ? t : v).to_s == value.to_s }
         | 
| 70 78 | 
             
                        value = active_scaffold_translated_option(column, text, val).first if text
         | 
| 71 79 | 
             
                        value
         | 
| 72 80 | 
             
                      end
         | 
| 73 81 | 
             
                    end
         | 
| 74 82 | 
             
                    as_(:association, :scope => :human_conditions, :column => attribute, :value => associated.join(', '))
         | 
| 75 83 | 
             
                  end
         | 
| 76 | 
            -
                   | 
| 77 | 
            -
                   | 
| 84 | 
            +
                  alias active_scaffold_human_condition_multi_select active_scaffold_human_condition_select
         | 
| 85 | 
            +
                  alias active_scaffold_human_condition_record_select active_scaffold_human_condition_select
         | 
| 86 | 
            +
                  alias active_scaffold_human_condition_chosen active_scaffold_human_condition_select
         | 
| 87 | 
            +
                  alias active_scaffold_human_condition_multi_chosen active_scaffold_human_condition_select
         | 
| 78 88 |  | 
| 79 89 | 
             
                  # the naming convention for overriding form fields with helpers
         | 
| 80 90 | 
             
                  def override_human_condition_column(column)
         | 
| 81 91 | 
             
                    override_helper column, 'human_condition_column'
         | 
| 82 92 | 
             
                  end
         | 
| 83 | 
            -
                   | 
| 93 | 
            +
                  alias override_human_condition_column? override_human_condition_column
         | 
| 84 94 |  | 
| 85 95 | 
             
                  def override_human_condition?(search_ui)
         | 
| 86 96 | 
             
                    respond_to?(override_human_condition(search_ui))
         | 
| @@ -1,11 +1,15 @@ | |
| 1 | 
            -
            # coding: utf-8
         | 
| 2 1 | 
             
            module ActiveScaffold
         | 
| 3 2 | 
             
              module Helpers
         | 
| 4 3 | 
             
                # Helpers that assist with the rendering of a List Column
         | 
| 5 4 | 
             
                module ListColumnHelpers
         | 
| 6 5 | 
             
                  def get_column_value(record, column)
         | 
| 7 | 
            -
                     | 
| 8 | 
            -
                     | 
| 6 | 
            +
                    record = record.send(column.delegated_association.name) if column.delegated_association
         | 
| 7 | 
            +
                    if record
         | 
| 8 | 
            +
                      method = get_column_method(record, column)
         | 
| 9 | 
            +
                      value = send(method, record, column)
         | 
| 10 | 
            +
                    else
         | 
| 11 | 
            +
                      value = nil
         | 
| 12 | 
            +
                    end
         | 
| 9 13 | 
             
                    value = ' '.html_safe if value.nil? || value.blank? # fix for IE 6
         | 
| 10 14 | 
             
                    return value
         | 
| 11 15 | 
             
                  rescue StandardError => e
         | 
| @@ -38,7 +42,9 @@ module ActiveScaffold | |
| 38 42 | 
             
                    if column.link && !skip_action_link?(column.link, record)
         | 
| 39 43 | 
             
                      link = column.link
         | 
| 40 44 | 
             
                      associated = record.send(column.association.name) if column.association
         | 
| 41 | 
            -
                       | 
| 45 | 
            +
                      authorized = link.action.nil?
         | 
| 46 | 
            +
                      authorized, reason = column_link_authorized?(link, column, record, associated) unless authorized
         | 
| 47 | 
            +
                      render_action_link(link, record, :link => text, :authorized => authorized, :not_authorized_reason => reason)
         | 
| 42 48 | 
             
                    elsif inplace_edit?(record, column)
         | 
| 43 49 | 
             
                      active_scaffold_inplace_edit(record, column, :formatted_column => text)
         | 
| 44 50 | 
             
                    elsif active_scaffold_config.actions.include?(:list) && active_scaffold_config.list.wrap_tag
         | 
| @@ -84,7 +90,7 @@ module ActiveScaffold | |
| 84 90 | 
             
                    options.delete(:disabled) if inplace_edit?(record, column)
         | 
| 85 91 | 
             
                    check_box(:record, column.name, options)
         | 
| 86 92 | 
             
                  end
         | 
| 87 | 
            -
             | 
| 93 | 
            +
             | 
| 88 94 | 
             
                  def active_scaffold_column_percentage(record, column)
         | 
| 89 95 | 
             
                    options = column.options[:slider] || {}
         | 
| 90 96 | 
             
                    options = options.merge(min: record.send(options[:min_method])) if options[:min_method]
         | 
| @@ -93,10 +99,31 @@ module ActiveScaffold | |
| 93 99 | 
             
                    as_slider options.merge(value: value || record.send(column.name))
         | 
| 94 100 | 
             
                  end
         | 
| 95 101 |  | 
| 102 | 
            +
                  def active_scaffold_column_month(record, column)
         | 
| 103 | 
            +
                    l record.send(column.name), format: :year_month
         | 
| 104 | 
            +
                  end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                  def active_scaffold_column_week(record, column)
         | 
| 107 | 
            +
                    l record.send(column.name), format: :week
         | 
| 108 | 
            +
                  end
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                  def tel_to(text)
         | 
| 111 | 
            +
                    groups = text.to_s.scan(/(?:^\+)?\d+/)
         | 
| 112 | 
            +
                    extension = groups.pop if text.to_s =~ /\s*[^\d\s]+\s*\d+$/
         | 
| 113 | 
            +
                    link_to text, "tel:#{[groups.join('-'), extension].compact.join(',')}"
         | 
| 114 | 
            +
                  end
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                  def active_scaffold_column_telephone(record, column)
         | 
| 117 | 
            +
                    phone = record.send column.name
         | 
| 118 | 
            +
                    return if phone.blank?
         | 
| 119 | 
            +
                    phone = number_to_phone(phone) unless column.options[:format] == false
         | 
| 120 | 
            +
                    tel_to phone
         | 
| 121 | 
            +
                  end
         | 
| 122 | 
            +
             | 
| 96 123 | 
             
                  def column_override(column)
         | 
| 97 124 | 
             
                    override_helper column, 'column'
         | 
| 98 125 | 
             
                  end
         | 
| 99 | 
            -
                   | 
| 126 | 
            +
                  alias column_override? column_override
         | 
| 100 127 |  | 
| 101 128 | 
             
                  # the naming convention for overriding column types with helpers
         | 
| 102 129 | 
             
                  def override_column_ui(list_ui)
         | 
| @@ -105,7 +132,7 @@ module ActiveScaffold | |
| 105 132 | 
             
                    method = "active_scaffold_column_#{list_ui}"
         | 
| 106 133 | 
             
                    @_column_ui_overrides[list_ui] = (method if respond_to? method)
         | 
| 107 134 | 
             
                  end
         | 
| 108 | 
            -
                   | 
| 135 | 
            +
                  alias override_column_ui? override_column_ui
         | 
| 109 136 |  | 
| 110 137 | 
             
                  ##
         | 
| 111 138 | 
             
                  ## Formatting
         | 
| @@ -113,19 +140,23 @@ module ActiveScaffold | |
| 113 140 | 
             
                  def format_column_value(record, column, value = nil)
         | 
| 114 141 | 
             
                    value ||= record.send(column.name) unless record.nil?
         | 
| 115 142 | 
             
                    if column.association.nil?
         | 
| 116 | 
            -
                      if [ | 
| 117 | 
            -
                        text, val = column.options[:options].find { | | 
| 143 | 
            +
                      if %i[select radio].include?(column.form_ui) && column.options[:options]
         | 
| 144 | 
            +
                        text, val = column.options[:options].find { |t, v| (v.nil? ? t : v).to_s == value.to_s }
         | 
| 118 145 | 
             
                        value = active_scaffold_translated_option(column, text, val).first if text
         | 
| 119 146 | 
             
                      end
         | 
| 120 | 
            -
                      if  | 
| 147 | 
            +
                      if grouped_search? && column == search_group_column && search_group_function
         | 
| 148 | 
            +
                        format_grouped_search_column(value, column.options)
         | 
| 149 | 
            +
                      elsif value.is_a? Numeric
         | 
| 121 150 | 
             
                        format_number_value(value, column.options)
         | 
| 122 151 | 
             
                      else
         | 
| 123 152 | 
             
                        format_value(value, column.options)
         | 
| 124 153 | 
             
                      end
         | 
| 125 154 | 
             
                    else
         | 
| 126 | 
            -
                      if column. | 
| 155 | 
            +
                      if column.association.collection?
         | 
| 127 156 | 
             
                        associated_size = value.size if column.associated_number? # get count before cache association
         | 
| 128 | 
            -
                         | 
| 157 | 
            +
                        if column.association.respond_to_target? && !value.loaded?
         | 
| 158 | 
            +
                          cache_association(record.association(column.name), column, associated_size)
         | 
| 159 | 
            +
                        end
         | 
| 129 160 | 
             
                      end
         | 
| 130 161 | 
             
                      format_association_value(value, column, associated_size)
         | 
| 131 162 | 
             
                    end
         | 
| @@ -134,38 +165,55 @@ module ActiveScaffold | |
| 134 165 | 
             
                  def format_number_value(value, options = {})
         | 
| 135 166 | 
             
                    if value
         | 
| 136 167 | 
             
                      value = case options[:format]
         | 
| 137 | 
            -
             | 
| 138 | 
            -
             | 
| 139 | 
            -
             | 
| 140 | 
            -
             | 
| 141 | 
            -
             | 
| 142 | 
            -
             | 
| 143 | 
            -
             | 
| 144 | 
            -
             | 
| 145 | 
            -
             | 
| 146 | 
            -
             | 
| 168 | 
            +
                              when :size
         | 
| 169 | 
            +
                                number_to_human_size(value, options[:i18n_options] || {})
         | 
| 170 | 
            +
                              when :percentage
         | 
| 171 | 
            +
                                number_to_percentage(value, options[:i18n_options] || {})
         | 
| 172 | 
            +
                              when :currency
         | 
| 173 | 
            +
                                number_to_currency(value, options[:i18n_options] || {})
         | 
| 174 | 
            +
                              when :i18n_number
         | 
| 175 | 
            +
                                send("number_with_#{value.is_a?(Integer) ? 'delimiter' : 'precision'}", value, options[:i18n_options] || {})
         | 
| 176 | 
            +
                              else
         | 
| 177 | 
            +
                                value
         | 
| 147 178 | 
             
                      end
         | 
| 148 179 | 
             
                    end
         | 
| 149 180 | 
             
                    clean_column_value(value)
         | 
| 150 181 | 
             
                  end
         | 
| 151 182 |  | 
| 183 | 
            +
                  def format_grouped_search_column(value, options = {})
         | 
| 184 | 
            +
                    case search_group_function
         | 
| 185 | 
            +
                    when 'year_month'
         | 
| 186 | 
            +
                      year, month = value.to_s.scan(/(\d*)(\d{2})/)[0]
         | 
| 187 | 
            +
                      I18n.l(Date.new(year.to_i, month.to_i, 1), format: options[:group_format] || search_group_function.to_sym)
         | 
| 188 | 
            +
                    when 'year_quarter'
         | 
| 189 | 
            +
                      year, quarter = value.to_s.scan(/(\d*)(\d)/)[0]
         | 
| 190 | 
            +
                      I18n.t(options[:group_format] || search_group_function, scope: 'date.formats', year: year, quarter: quarter)
         | 
| 191 | 
            +
                    when 'quarter'
         | 
| 192 | 
            +
                      I18n.t(options[:group_format] || search_group_function, scope: 'date.formats', num: value)
         | 
| 193 | 
            +
                    when 'month'
         | 
| 194 | 
            +
                      I18n.l(Date.new(Time.zone.today.year, value, 1), format: options[:group_format] || search_group_function.to_sym)
         | 
| 195 | 
            +
                    else value
         | 
| 196 | 
            +
                    end
         | 
| 197 | 
            +
                  end
         | 
| 198 | 
            +
             | 
| 152 199 | 
             
                  def format_collection_association_value(value, column, label_method, size)
         | 
| 153 200 | 
             
                    if column.associated_limit.nil?
         | 
| 154 201 | 
             
                      firsts = value.collect(&label_method)
         | 
| 155 | 
            -
             | 
| 202 | 
            +
                      safe_join firsts, active_scaffold_config.list.association_join_text
         | 
| 203 | 
            +
                    elsif column.associated_limit.zero?
         | 
| 156 204 | 
             
                      size if column.associated_number?
         | 
| 157 205 | 
             
                    else
         | 
| 158 | 
            -
                      firsts = value. | 
| 159 | 
            -
                      firsts. | 
| 206 | 
            +
                      firsts = value.loaded? ? value[0, column.associated_limit] : value.limit(column.associated_limit)
         | 
| 207 | 
            +
                      firsts = firsts.map(&label_method)
         | 
| 160 208 | 
             
                      firsts << '…' if value.size > column.associated_limit
         | 
| 161 | 
            -
                      text = firsts | 
| 209 | 
            +
                      text = safe_join firsts, active_scaffold_config.list.association_join_text
         | 
| 162 210 | 
             
                      text << " (#{size})" if column.associated_number? && column.associated_limit && value.size > column.associated_limit
         | 
| 163 211 | 
             
                      text
         | 
| 164 212 | 
             
                    end
         | 
| 165 213 | 
             
                  end
         | 
| 166 214 |  | 
| 167 215 | 
             
                  def format_singular_association_value(value, column, label_method)
         | 
| 168 | 
            -
                    if column. | 
| 216 | 
            +
                    if column.association.polymorphic?
         | 
| 169 217 | 
             
                      "#{value.class.model_name.human}: #{value.send(label_method)}"
         | 
| 170 218 | 
             
                    else
         | 
| 171 219 | 
             
                      value.send(label_method)
         | 
| @@ -215,7 +263,14 @@ module ActiveScaffold | |
| 215 263 |  | 
| 216 264 | 
             
                  def inplace_edit?(record, column)
         | 
| 217 265 | 
             
                    return unless column.inplace_edit
         | 
| 218 | 
            -
                     | 
| 266 | 
            +
                    if controller.respond_to?(:update_authorized?, true)
         | 
| 267 | 
            +
                      if controller.method(:update_authorized?).parameters.size == 2
         | 
| 268 | 
            +
                        return Array(controller.send(:update_authorized?, record, column.name))[0]
         | 
| 269 | 
            +
                      else
         | 
| 270 | 
            +
                        ActiveSupport::Deprecation.warn 'add column = nil parameter to update_authorized? on your controller'
         | 
| 271 | 
            +
                        editable = Array(controller.send(:update_authorized?, record))[0]
         | 
| 272 | 
            +
                      end
         | 
| 273 | 
            +
                    end
         | 
| 219 274 | 
             
                    editable || record.authorized_for?(:crud_type => :update, :column => column.name)
         | 
| 220 275 | 
             
                  end
         | 
| 221 276 |  | 
| @@ -239,17 +294,14 @@ module ActiveScaffold | |
| 239 294 |  | 
| 240 295 | 
             
                  def inplace_edit_control(column)
         | 
| 241 296 | 
             
                    return unless inplace_edit?(active_scaffold_config.model, column) && inplace_edit_cloning?(column)
         | 
| 242 | 
            -
                    old_record, @record = @record, active_scaffold_config.model.new # TODO: remove when relying on @record is removed
         | 
| 243 297 | 
             
                    column = column.clone
         | 
| 244 298 | 
             
                    column.options = column.options.clone
         | 
| 245 299 | 
             
                    column.form_ui = :select if column.association && column.form_ui.nil?
         | 
| 246 | 
            -
                    options = active_scaffold_input_options(column).merge(:object =>  | 
| 300 | 
            +
                    options = active_scaffold_input_options(column).merge(:object => column.active_record_class.new)
         | 
| 247 301 | 
             
                    options[:class] = "#{options[:class]} inplace_field"
         | 
| 248 302 | 
             
                    options[:"data-id"] = options[:id]
         | 
| 249 303 | 
             
                    options[:id] = nil
         | 
| 250 | 
            -
                    content_tag(:div, active_scaffold_input_for(column, nil, options), :style => 'display:none;', :class => inplace_edit_control_css_class) | 
| 251 | 
            -
                      @record = old_record # TODO: remove when relying on @record is removed
         | 
| 252 | 
            -
                    end
         | 
| 304 | 
            +
                    content_tag(:div, active_scaffold_input_for(column, nil, options), :style => 'display:none;', :class => inplace_edit_control_css_class)
         | 
| 253 305 | 
             
                  end
         | 
| 254 306 |  | 
| 255 307 | 
             
                  def inplace_edit_control_css_class
         | 
| @@ -273,8 +325,8 @@ module ActiveScaffold | |
| 273 325 | 
             
                    elsif inplace_edit_cloning?(column)
         | 
| 274 326 | 
             
                      data[:ie_mode] = :clone
         | 
| 275 327 | 
             
                    elsif column.inplace_edit == :ajax
         | 
| 276 | 
            -
                      url = url_for(:controller => params_for[:controller], :action => 'render_field', :id => '__id__', :update_column => column.name)
         | 
| 277 | 
            -
                      plural = column. | 
| 328 | 
            +
                      url = url_for(params_for(:controller => params_for[:controller], :action => 'render_field', :id => '__id__', :update_column => column.name))
         | 
| 329 | 
            +
                      plural = column.association.try(:collection?) && !override_form_field?(column) && %i[select record_select].include?(column.form_ui)
         | 
| 278 330 | 
             
                      data[:ie_render_url] = url
         | 
| 279 331 | 
             
                      data[:ie_mode] = :ajax
         | 
| 280 332 | 
             
                      data[:ie_plural] = plural
         | 
| @@ -282,6 +334,8 @@ module ActiveScaffold | |
| 282 334 | 
             
                    data
         | 
| 283 335 | 
             
                  end
         | 
| 284 336 |  | 
| 337 | 
            +
                  # MARK
         | 
| 338 | 
            +
             | 
| 285 339 | 
             
                  def all_marked?
         | 
| 286 340 | 
             
                    if active_scaffold_config.mark.mark_all_mode == :page
         | 
| 287 341 | 
             
                      @page.items.detect { |record| !marked_records.include?(record.id) }.nil?
         | 
| @@ -298,6 +352,8 @@ module ActiveScaffold | |
| 298 352 | 
             
                    content_tag(:span, check_box_tag("#{controller_id}_mark_heading_span_input", '1', all_marked?), tag_options)
         | 
| 299 353 | 
             
                  end
         | 
| 300 354 |  | 
| 355 | 
            +
                  # COLUMN HEADINGS
         | 
| 356 | 
            +
             | 
| 301 357 | 
             
                  def column_heading_attributes(column, sorting, sort_direction)
         | 
| 302 358 | 
             
                    {:id => active_scaffold_column_header_id(column), :class => column_heading_class(column, sorting), :title => strip_tags(column.description).presence}
         | 
| 303 359 | 
             
                  end
         | 
| @@ -322,11 +378,12 @@ module ActiveScaffold | |
| 322 378 | 
             
                      options = {:id => nil, :class => 'as_sort',
         | 
| 323 379 | 
             
                                 'data-page-history' => controller_id,
         | 
| 324 380 | 
             
                                 :remote => true, :method => :get}
         | 
| 325 | 
            -
                       | 
| 326 | 
            -
                       | 
| 327 | 
            -
             | 
| 381 | 
            +
                      url_options = {action: :index, page: 1, sort: column.name, sort_direction: sort_direction}
         | 
| 382 | 
            +
                      # :id needed because rails reuse it even if it was deleted from params (like do_refresh_list does)
         | 
| 383 | 
            +
                      url_options[:id] = nil if @remove_id_from_list_links
         | 
| 384 | 
            +
                      url_options = params_for(url_options)
         | 
| 328 385 | 
             
                      unless active_scaffold_config.store_user_settings
         | 
| 329 | 
            -
                        url_options | 
| 386 | 
            +
                        url_options[:search] = search_params if respond_to?(:search_params) && search_params.present?
         | 
| 330 387 | 
             
                      end
         | 
| 331 388 | 
             
                      link_to column_heading_label(column), url_options, options
         | 
| 332 389 | 
             
                    else
         | 
| @@ -337,6 +394,27 @@ module ActiveScaffold | |
| 337 394 | 
             
                  def column_heading_label(column)
         | 
| 338 395 | 
             
                    column.label
         | 
| 339 396 | 
             
                  end
         | 
| 397 | 
            +
             | 
| 398 | 
            +
                  # CALCULATIONS
         | 
| 399 | 
            +
             | 
| 400 | 
            +
                  def column_calculation(column)
         | 
| 401 | 
            +
                    if column.calculate.instance_of? Proc
         | 
| 402 | 
            +
                      column.calculate.call(@records)
         | 
| 403 | 
            +
                    else
         | 
| 404 | 
            +
                      calculate_query.calculate(column.calculate, column.name)
         | 
| 405 | 
            +
                    end
         | 
| 406 | 
            +
                  end
         | 
| 407 | 
            +
             | 
| 408 | 
            +
                  def render_column_calculation(column)
         | 
| 409 | 
            +
                    calculation = column_calculation(column)
         | 
| 410 | 
            +
                    override_formatter = "render_#{column.name}_#{column.calculate.is_a?(Proc) ? :calculate : column.calculate}"
         | 
| 411 | 
            +
                    calculation = send(override_formatter, calculation) if respond_to? override_formatter
         | 
| 412 | 
            +
                    format_column_calculation(column, calculation)
         | 
| 413 | 
            +
                  end
         | 
| 414 | 
            +
             | 
| 415 | 
            +
                  def format_column_calculation(column, calculation)
         | 
| 416 | 
            +
                    "#{"#{as_(column.calculate)}: " unless column.calculate.is_a? Proc}#{format_column_value nil, column, calculation}"
         | 
| 417 | 
            +
                  end
         | 
| 340 418 | 
             
                end
         | 
| 341 419 | 
             
              end
         | 
| 342 420 | 
             
            end
         | 
| @@ -6,14 +6,11 @@ module ActiveScaffold | |
| 6 6 | 
             
                  end
         | 
| 7 7 |  | 
| 8 8 | 
             
                  def pagination_url_options(url_options = nil)
         | 
| 9 | 
            -
                     | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
                      url_options | 
| 13 | 
            -
                       | 
| 14 | 
            -
                        column, direction = active_scaffold_config.list.user.sorting.first
         | 
| 15 | 
            -
                        url_options.merge!(:sort => column.name, :sort_direction => direction)
         | 
| 16 | 
            -
                      end
         | 
| 9 | 
            +
                    if url_options.nil?
         | 
| 10 | 
            +
                      url_options = {action: @pagination_action || :index}
         | 
| 11 | 
            +
                      # :id needed because rails reuse it even if it was deleted from params (like do_refresh_list does)
         | 
| 12 | 
            +
                      url_options[:id] = nil if @remove_id_from_list_links
         | 
| 13 | 
            +
                      url_options = params_for(url_options)
         | 
| 17 14 | 
             
                    end
         | 
| 18 15 | 
             
                    url_options
         | 
| 19 16 | 
             
                  end
         | 
| @@ -51,11 +48,11 @@ module ActiveScaffold | |
| 51 48 | 
             
                    html << '..' if start_number > last_page + 1
         | 
| 52 49 |  | 
| 53 50 | 
             
                    [start_number, last_page + 1].max.upto(end_number) do |num|
         | 
| 54 | 
            -
                      if current_page.number == num
         | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 51 | 
            +
                      html << if current_page.number == num
         | 
| 52 | 
            +
                                content_tag(:span, num.to_s, :class => 'as_paginate current')
         | 
| 53 | 
            +
                              else
         | 
| 54 | 
            +
                                pagination_ajax_link(num, url_options, options)
         | 
| 55 | 
            +
                              end
         | 
| 59 56 | 
             
                    end
         | 
| 60 57 |  | 
| 61 58 | 
             
                    if current_page.pager.infinite?
         | 
| @@ -68,7 +65,7 @@ module ActiveScaffold | |
| 68 65 | 
             
                        html << pagination_ajax_link(num, url_options, options)
         | 
| 69 66 | 
             
                      end
         | 
| 70 67 | 
             
                    end
         | 
| 71 | 
            -
                    html | 
| 68 | 
            +
                    safe_join html, ' '
         | 
| 72 69 | 
             
                  end
         | 
| 73 70 | 
             
                end
         | 
| 74 71 | 
             
              end
         | 
| @@ -7,8 +7,10 @@ module ActiveScaffold | |
| 7 7 | 
             
                  def active_scaffold_search_for(column, options = nil)
         | 
| 8 8 | 
             
                    options ||= active_scaffold_search_options(column)
         | 
| 9 9 | 
             
                    record = options[:object]
         | 
| 10 | 
            -
                     | 
| 11 | 
            -
             | 
| 10 | 
            +
                    if column.delegated_association
         | 
| 11 | 
            +
                      record = record.send(column.delegated_association.name) || column.active_record_class.new
         | 
| 12 | 
            +
                      options[:object] = record
         | 
| 13 | 
            +
                    end
         | 
| 12 14 |  | 
| 13 15 | 
             
                    # first, check if the dev has created an override for this specific field for search
         | 
| 14 16 | 
             
                    if (method = override_search_field(column))
         | 
| @@ -41,7 +43,7 @@ module ActiveScaffold | |
| 41 43 | 
             
                        # final ultimate fallback: use rails' generic input method
         | 
| 42 44 | 
             
                        else
         | 
| 43 45 | 
             
                          # for textual fields we pass different options
         | 
| 44 | 
            -
                          text_types = [ | 
| 46 | 
            +
                          text_types = %i[text string integer float decimal]
         | 
| 45 47 | 
             
                          options = active_scaffold_input_text_options(options) if text_types.include?(column.column.type)
         | 
| 46 48 | 
             
                          text_field(:record, column.name, options.merge(column.options))
         | 
| 47 49 | 
             
                        end
         | 
| @@ -64,7 +66,7 @@ module ActiveScaffold | |
| 64 66 | 
             
                  end
         | 
| 65 67 |  | 
| 66 68 | 
             
                  def search_label_for(column, options)
         | 
| 67 | 
            -
                    options[:id] unless [ | 
| 69 | 
            +
                    options[:id] unless %i[range integer decimal float string date_picker datetime_picker calendar_date_select].include? column.search_ui
         | 
| 68 70 | 
             
                  end
         | 
| 69 71 |  | 
| 70 72 | 
             
                  ##
         | 
| @@ -73,8 +75,6 @@ module ActiveScaffold | |
| 73 75 |  | 
| 74 76 | 
             
                  def active_scaffold_search_multi_select(column, options)
         | 
| 75 77 | 
             
                    record = options.delete(:object)
         | 
| 76 | 
            -
                    ActiveSupport::Deprecation.warn 'Relying on @record is deprecated, include :object in options with record.', caller if record.nil? # TODO: Remove when relying on @record is removed
         | 
| 77 | 
            -
                    record ||= @record # TODO: Remove when relying on @record is removed
         | 
| 78 78 | 
             
                    associated = options.delete :value
         | 
| 79 79 | 
             
                    associated = [associated].compact unless associated.is_a? Array
         | 
| 80 80 |  | 
| @@ -96,12 +96,10 @@ module ActiveScaffold | |
| 96 96 |  | 
| 97 97 | 
             
                  def active_scaffold_search_select(column, html_options, options = {})
         | 
| 98 98 | 
             
                    record = html_options.delete(:object)
         | 
| 99 | 
            -
                    ActiveSupport::Deprecation.warn 'Relying on @record is deprecated, include :object in html_options with record.', caller if record.nil? # TODO: Remove when relying on @record is removed
         | 
| 100 | 
            -
                    record ||= @record # TODO: Remove when relying on @record is removed
         | 
| 101 99 | 
             
                    associated = html_options.delete :value
         | 
| 102 100 | 
             
                    if column.association
         | 
| 103 101 | 
             
                      associated = associated.is_a?(Array) ? associated.map(&:to_i) : associated.to_i unless associated.nil?
         | 
| 104 | 
            -
                      method = column.association. | 
| 102 | 
            +
                      method = column.association.belongs_to? ? column.association.foreign_key : column.name
         | 
| 105 103 | 
             
                      select_options = sorted_association_options_find(column.association, false, record)
         | 
| 106 104 | 
             
                    else
         | 
| 107 105 | 
             
                      method = column.name
         | 
| @@ -113,7 +111,7 @@ module ActiveScaffold | |
| 113 111 | 
             
                    options = options.merge(:selected => associated).merge column.options
         | 
| 114 112 | 
             
                    html_options.merge! column.options[:html_options] || {}
         | 
| 115 113 | 
             
                    if html_options[:multiple]
         | 
| 116 | 
            -
                      html_options | 
| 114 | 
            +
                      active_scaffold_select_name_with_multiple html_options
         | 
| 117 115 | 
             
                    else
         | 
| 118 116 | 
             
                      options[:include_blank] ||= as_(:_select_)
         | 
| 119 117 | 
             
                      active_scaffold_translate_select_options(options)
         | 
| @@ -143,7 +141,27 @@ module ActiveScaffold | |
| 143 141 | 
             
                    select_tag(options[:name], options_for_select(select_options, ActiveScaffold::Core.column_type_cast(options[:value], column.column)), :id => options[:id])
         | 
| 144 142 | 
             
                  end
         | 
| 145 143 | 
             
                  # we can't use checkbox ui because it's not possible to decide whether search for this field or not
         | 
| 146 | 
            -
                   | 
| 144 | 
            +
                  alias active_scaffold_search_checkbox active_scaffold_search_boolean
         | 
| 145 | 
            +
             | 
| 146 | 
            +
                  def active_scaffold_group_search_column(record, options)
         | 
| 147 | 
            +
                    select_tag 'search[active_scaffold_group]', options_for_select(active_scaffold_group_search_options, selected: field_search_params['active_scaffold_group'])
         | 
| 148 | 
            +
                  end
         | 
| 149 | 
            +
             | 
| 150 | 
            +
                  def active_scaffold_group_search_options
         | 
| 151 | 
            +
                    options = active_scaffold_config.field_search.group_options.collect do |text, value|
         | 
| 152 | 
            +
                      active_scaffold_translated_option(active_scaffold_group_column, text, value)
         | 
| 153 | 
            +
                    end
         | 
| 154 | 
            +
                    [[as_(:no_group), '']].concat options
         | 
| 155 | 
            +
                  end
         | 
| 156 | 
            +
             | 
| 157 | 
            +
                  def active_scaffold_group_column
         | 
| 158 | 
            +
                    return if active_scaffold_config.field_search.group_options.blank?
         | 
| 159 | 
            +
                    @_active_scaffold_group_column ||= begin
         | 
| 160 | 
            +
                      column = ActiveScaffold::DataStructures::Column.new(:active_scaffold_group, active_scaffold_config.model)
         | 
| 161 | 
            +
                      column.label = :group_by
         | 
| 162 | 
            +
                      column
         | 
| 163 | 
            +
                    end
         | 
| 164 | 
            +
                  end
         | 
| 147 165 |  | 
| 148 166 | 
             
                  def active_scaffold_search_null(column, options)
         | 
| 149 167 | 
             
                    select_options = []
         | 
| @@ -165,10 +183,11 @@ module ActiveScaffold | |
| 165 183 | 
             
                  def active_scaffold_search_range_comparator_options(column)
         | 
| 166 184 | 
             
                    select_options = ActiveScaffold::Finder::NUMERIC_COMPARATORS.collect { |comp| [as_(comp.downcase.to_sym), comp] }
         | 
| 167 185 | 
             
                    if active_scaffold_search_range_string?(column)
         | 
| 168 | 
            -
                       | 
| 186 | 
            +
                      comparators = ActiveScaffold::Finder::STRING_COMPARATORS.collect { |title, comp| [as_(title), comp] }
         | 
| 187 | 
            +
                      select_options.unshift(*comparators)
         | 
| 169 188 | 
             
                    end
         | 
| 170 189 | 
             
                    if include_null_comparators? column
         | 
| 171 | 
            -
                      select_options  | 
| 190 | 
            +
                      select_options.concat ActiveScaffold::Finder::NULL_COMPARATORS.collect { |comp| [as_(comp), comp] }
         | 
| 172 191 | 
             
                    end
         | 
| 173 192 | 
             
                    select_options
         | 
| 174 193 | 
             
                  end
         | 
| @@ -176,13 +195,13 @@ module ActiveScaffold | |
| 176 195 | 
             
                  def include_null_comparators?(column)
         | 
| 177 196 | 
             
                    return column.options[:null_comparators] if column.options.key? :null_comparators
         | 
| 178 197 | 
             
                    if column.association
         | 
| 179 | 
            -
                      column.association. | 
| 198 | 
            +
                      !column.association.belongs_to? || active_scaffold_config.columns[column.association.foreign_key].column.try(:null)
         | 
| 180 199 | 
             
                    else
         | 
| 181 200 | 
             
                      column.column.try(:null)
         | 
| 182 201 | 
             
                    end
         | 
| 183 202 | 
             
                  end
         | 
| 184 203 |  | 
| 185 | 
            -
                  def active_scaffold_search_range(column, options)
         | 
| 204 | 
            +
                  def active_scaffold_search_range(column, options, input_method = :text_field_tag, input_options = {})
         | 
| 186 205 | 
             
                    opt_value, from_value, to_value = field_search_params_range_values(column)
         | 
| 187 206 |  | 
| 188 207 | 
             
                    select_options = active_scaffold_search_range_comparator_options(column)
         | 
| @@ -199,34 +218,48 @@ module ActiveScaffold | |
| 199 218 | 
             
                    to_value = format_number_value(to_value, column.options) if to_value.is_a?(Numeric)
         | 
| 200 219 | 
             
                    html = select_tag("#{options[:name]}[opt]", options_for_select(select_options, opt_value),
         | 
| 201 220 | 
             
                                      :id => "#{options[:id]}_opt", :class => 'as_search_range_option')
         | 
| 221 | 
            +
                    from_options = active_scaffold_input_text_options(input_options.merge(:id => options[:id], :size => text_field_size))
         | 
| 222 | 
            +
                    to_options = from_options.merge(:id => "#{options[:id]}_to")
         | 
| 202 223 | 
             
                    html << content_tag('span', :id => "#{options[:id]}_numeric", :style => ActiveScaffold::Finder::NULL_COMPARATORS.include?(opt_value) ? 'display: none' : nil) do
         | 
| 203 | 
            -
                       | 
| 224 | 
            +
                      send(input_method, "#{options[:name]}[from]", from_value, input_options) <<
         | 
| 204 225 | 
             
                        content_tag(
         | 
| 205 | 
            -
                          :span, | 
| 206 | 
            -
             | 
| 207 | 
            -
                                                   active_scaffold_input_text_options(:id => "#{options[:id]}_to", :size => text_field_size))
         | 
| 208 | 
            -
                          ).html_safe,
         | 
| 226 | 
            +
                          :span,
         | 
| 227 | 
            +
                          safe_join([' - ', send(input_method, "#{options[:name]}[to]", to_value, to_options)]),
         | 
| 209 228 | 
             
                          :id => "#{options[:id]}_between", :class => 'as_search_range_between', :style => (opt_value == 'BETWEEN') ? nil : 'display: none'
         | 
| 210 229 | 
             
                        )
         | 
| 211 230 | 
             
                    end
         | 
| 212 231 | 
             
                    content_tag :span, html, :class => 'search_range'
         | 
| 213 232 | 
             
                  end
         | 
| 214 | 
            -
                   | 
| 215 | 
            -
             | 
| 216 | 
            -
                   | 
| 217 | 
            -
             | 
| 233 | 
            +
                  alias active_scaffold_search_string active_scaffold_search_range
         | 
| 234 | 
            +
             | 
| 235 | 
            +
                  def active_scaffold_search_integer(column, options)
         | 
| 236 | 
            +
                    active_scaffold_search_range(column, options, :number_field_tag, step: '1')
         | 
| 237 | 
            +
                  end
         | 
| 238 | 
            +
             | 
| 239 | 
            +
                  def active_scaffold_search_decimal(column, options)
         | 
| 240 | 
            +
                    active_scaffold_search_range(column, options, :number_field_tag, step: :any)
         | 
| 241 | 
            +
                  end
         | 
| 242 | 
            +
                  alias active_scaffold_search_float active_scaffold_search_decimal
         | 
| 218 243 |  | 
| 219 244 | 
             
                  def field_search_datetime_value(value)
         | 
| 220 | 
            -
                     | 
| 245 | 
            +
                    Time.zone.local(value[:year].to_i, value[:month].to_i, value[:day].to_i, value[:hour].to_i, value[:minute].to_i, value[:second].to_i) unless value.nil? || value[:year].blank?
         | 
| 221 246 | 
             
                  end
         | 
| 222 247 |  | 
| 223 248 | 
             
                  def active_scaffold_search_datetime(column, options)
         | 
| 224 249 | 
             
                    _, from_value, to_value = field_search_params_range_values(column)
         | 
| 225 250 | 
             
                    options = column.options.merge(options)
         | 
| 226 | 
            -
                     | 
| 251 | 
            +
                    type = "#{'date' unless options[:discard_date]}#{'time' unless options[:discard_time]}"
         | 
| 252 | 
            +
                    use_select = options.delete(:use_select)
         | 
| 253 | 
            +
                    helper = use_select ? "select_#{type}" : "#{type}#{'_local' if type == 'datetime'}_field"
         | 
| 254 | 
            +
                    if use_select
         | 
| 255 | 
            +
                      default_from_options = {include_blank: true, prefix: "#{options[:name]}[from]"}
         | 
| 256 | 
            +
                      default_to_options = {include_blank: true, prefix: "#{options[:name]}[to]"}
         | 
| 257 | 
            +
                    end
         | 
| 227 258 |  | 
| 228 | 
            -
                     | 
| 229 | 
            -
                       | 
| 259 | 
            +
                    safe_join [
         | 
| 260 | 
            +
                      send(helper, field_search_datetime_value(from_value), options.reverse_merge(default_from_options || {})),
         | 
| 261 | 
            +
                      send(helper, field_search_datetime_value(to_value), options.reverse_merge(default_to_options || {}))
         | 
| 262 | 
            +
                    ], ' - '
         | 
| 230 263 | 
             
                  end
         | 
| 231 264 |  | 
| 232 265 | 
             
                  def active_scaffold_search_date(column, options)
         | 
| @@ -236,7 +269,7 @@ module ActiveScaffold | |
| 236 269 | 
             
                  def active_scaffold_search_time(column, options)
         | 
| 237 270 | 
             
                    active_scaffold_search_datetime(column, options.merge!(:discard_date => true))
         | 
| 238 271 | 
             
                  end
         | 
| 239 | 
            -
                   | 
| 272 | 
            +
                  alias active_scaffold_search_timestamp active_scaffold_search_datetime
         | 
| 240 273 |  | 
| 241 274 | 
             
                  ##
         | 
| 242 275 | 
             
                  ## Search column override signatures
         | 
| @@ -267,16 +300,20 @@ module ActiveScaffold | |
| 267 300 | 
             
                        visibles << column
         | 
| 268 301 | 
             
                      end
         | 
| 269 302 | 
             
                    end
         | 
| 303 | 
            +
                    if active_scaffold_group_column
         | 
| 304 | 
            +
                      columns = grouped_search? || search_config.optional_columns.empty? ? visibles : hiddens
         | 
| 305 | 
            +
                      columns << active_scaffold_group_column
         | 
| 306 | 
            +
                    end
         | 
| 270 307 | 
             
                    [visibles, hiddens]
         | 
| 271 308 | 
             
                  end
         | 
| 272 309 |  | 
| 273 310 | 
             
                  def searched_by?(column)
         | 
| 274 | 
            -
                    value = field_search_params[column.name]
         | 
| 311 | 
            +
                    value = field_search_params[column.name.to_s]
         | 
| 275 312 | 
             
                    case value
         | 
| 276 313 | 
             
                    when Hash
         | 
| 277 | 
            -
                       | 
| 314 | 
            +
                      value['from'].present?
         | 
| 278 315 | 
             
                    when String
         | 
| 279 | 
            -
                       | 
| 316 | 
            +
                      value.present?
         | 
| 280 317 | 
             
                    else
         | 
| 281 318 | 
             
                      false
         | 
| 282 319 | 
             
                    end
         |