datagrid 1.8.1 → 2.0.0.pre.alpha
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.md +31 -7
- data/{Readme.markdown → README.md} +46 -29
- data/app/assets/stylesheets/datagrid.css +145 -0
- data/app/views/datagrid/_enum_checkboxes.html.erb +5 -3
- data/app/views/datagrid/_form.html.erb +4 -5
- data/app/views/datagrid/_head.html.erb +26 -3
- data/app/views/datagrid/_range_filter.html.erb +5 -3
- data/app/views/datagrid/_row.html.erb +12 -1
- data/app/views/datagrid/_table.html.erb +4 -4
- data/datagrid.gemspec +8 -8
- data/lib/datagrid/active_model.rb +9 -17
- data/lib/datagrid/base.rb +39 -0
- data/lib/datagrid/column_names_attribute.rb +12 -12
- data/lib/datagrid/columns/column.rb +155 -133
- data/lib/datagrid/columns.rb +495 -282
- data/lib/datagrid/configuration.rb +23 -10
- data/lib/datagrid/core.rb +184 -150
- data/lib/datagrid/deprecated_object.rb +20 -0
- data/lib/datagrid/drivers/abstract_driver.rb +13 -25
- data/lib/datagrid/drivers/active_record.rb +24 -26
- data/lib/datagrid/drivers/array.rb +26 -17
- data/lib/datagrid/drivers/mongo_mapper.rb +15 -14
- data/lib/datagrid/drivers/mongoid.rb +16 -18
- data/lib/datagrid/drivers/sequel.rb +14 -19
- data/lib/datagrid/drivers.rb +2 -1
- data/lib/datagrid/engine.rb +11 -3
- data/lib/datagrid/filters/base_filter.rb +166 -142
- data/lib/datagrid/filters/boolean_filter.rb +19 -5
- data/lib/datagrid/filters/date_filter.rb +33 -35
- data/lib/datagrid/filters/date_time_filter.rb +24 -16
- data/lib/datagrid/filters/default_filter.rb +9 -3
- data/lib/datagrid/filters/dynamic_filter.rb +151 -105
- data/lib/datagrid/filters/enum_filter.rb +43 -19
- data/lib/datagrid/filters/extended_boolean_filter.rb +39 -27
- data/lib/datagrid/filters/float_filter.rb +16 -5
- data/lib/datagrid/filters/integer_filter.rb +21 -10
- data/lib/datagrid/filters/ranged_filter.rb +66 -45
- data/lib/datagrid/filters/select_options.rb +58 -49
- data/lib/datagrid/filters/string_filter.rb +9 -4
- data/lib/datagrid/filters.rb +234 -106
- data/lib/datagrid/form_builder.rb +116 -128
- data/lib/datagrid/generators/scaffold.rb +185 -0
- data/lib/datagrid/generators/views.rb +20 -0
- data/lib/datagrid/helper.rb +397 -22
- data/lib/datagrid/ordering.rb +81 -87
- data/lib/datagrid/rspec.rb +8 -12
- data/lib/datagrid/utils.rb +42 -38
- data/lib/datagrid/version.rb +3 -1
- data/lib/datagrid.rb +18 -28
- data/templates/base.rb.erb +33 -7
- data/templates/grid.rb.erb +1 -1
- metadata +18 -19
- data/app/assets/stylesheets/datagrid.sass +0 -134
- data/lib/datagrid/filters/composite_filters.rb +0 -49
- data/lib/datagrid/renderer.rb +0 -157
- data/lib/datagrid/scaffold.rb +0 -129
- data/lib/tasks/datagrid_tasks.rake +0 -15
- data/templates/controller.rb.erb +0 -6
- data/templates/index.html.erb +0 -5
    
        data/lib/datagrid/ordering.rb
    CHANGED
    
    | @@ -1,132 +1,126 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            require "datagrid/columns"
         | 
| 2 4 |  | 
| 3 5 | 
             
            module Datagrid
         | 
| 4 6 | 
             
              # Raised when grid order value is incorrect
         | 
| 5 7 | 
             
              class OrderUnsupported < StandardError
         | 
| 6 8 | 
             
              end
         | 
| 7 | 
            -
              module Ordering
         | 
| 8 9 |  | 
| 10 | 
            +
              # Module adds support for ordering by defined columns for Datagrid.
         | 
| 11 | 
            +
              module Ordering
         | 
| 9 12 | 
             
                # @!visibility private
         | 
| 10 13 | 
             
                def self.included(base)
         | 
| 11 | 
            -
                  base.extend | 
| 14 | 
            +
                  base.extend ClassMethods
         | 
| 12 15 | 
             
                  base.class_eval do
         | 
| 13 16 | 
             
                    include Datagrid::Columns
         | 
| 14 17 |  | 
| 15 18 | 
             
                    datagrid_attribute :order do |value|
         | 
| 16 | 
            -
                      if value.present?
         | 
| 17 | 
            -
                        value.to_sym
         | 
| 18 | 
            -
                      else
         | 
| 19 | 
            -
                        nil
         | 
| 20 | 
            -
                      end
         | 
| 21 | 
            -
             | 
| 19 | 
            +
                      value.to_sym if value.present?
         | 
| 22 20 | 
             
                    end
         | 
| 23 21 |  | 
| 24 22 | 
             
                    datagrid_attribute :descending do |value|
         | 
| 25 23 | 
             
                      Datagrid::Utils.booleanize(value)
         | 
| 26 24 | 
             
                    end
         | 
| 27 | 
            -
                     | 
| 28 | 
            -
             | 
| 25 | 
            +
                    alias_method :descending?, :descending
         | 
| 29 26 | 
             
                  end
         | 
| 30 | 
            -
                  base.include InstanceMethods
         | 
| 31 27 | 
             
                end
         | 
| 32 28 |  | 
| 33 29 | 
             
                # @!visibility private
         | 
| 34 30 | 
             
                module ClassMethods
         | 
| 35 31 | 
             
                  def order_unsupported(name, reason)
         | 
| 36 | 
            -
                    raise Datagrid::OrderUnsupported, "Can not sort #{ | 
| 32 | 
            +
                    raise Datagrid::OrderUnsupported, "Can not sort #{inspect} by ##{name}: #{reason}"
         | 
| 37 33 | 
             
                  end
         | 
| 38 34 | 
             
                end
         | 
| 39 35 |  | 
| 40 | 
            -
                 | 
| 36 | 
            +
                # @!visibility private
         | 
| 37 | 
            +
                def assets
         | 
| 38 | 
            +
                  check_order_valid!
         | 
| 39 | 
            +
                  apply_order(super)
         | 
| 40 | 
            +
                end
         | 
| 41 41 |  | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 42 | 
            +
                # @return [Datagrid::Columns::Column, nil] a column definition that is currently used to order assets
         | 
| 43 | 
            +
                # @example
         | 
| 44 | 
            +
                #   class MyGrid
         | 
| 45 | 
            +
                #     scope { Model }
         | 
| 46 | 
            +
                #     column(:id)
         | 
| 47 | 
            +
                #     column(:name)
         | 
| 48 | 
            +
                #   end
         | 
| 49 | 
            +
                #   MyGrid.new(order: "name").order_column # => #<Column name: "name", ...>
         | 
| 50 | 
            +
                def order_column
         | 
| 51 | 
            +
                  order ? column_by_name(order) : nil
         | 
| 52 | 
            +
                end
         | 
| 47 53 |  | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
                   | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
                  #   MyGrid.new(order: "name").order_column # => #<Column name: "name", ...>
         | 
| 56 | 
            -
                  def order_column
         | 
| 57 | 
            -
                    order ? column_by_name(order) : nil
         | 
| 58 | 
            -
                  end
         | 
| 54 | 
            +
                # @param column [String, Datagrid::Columns::Column]
         | 
| 55 | 
            +
                # @param desc [nil, Boolean] confirm order direction as well if specified
         | 
| 56 | 
            +
                # @return [Boolean] true if given grid is ordered by given column.
         | 
| 57 | 
            +
                def ordered_by?(column, desc = nil)
         | 
| 58 | 
            +
                  order_column == column_by_name(column) &&
         | 
| 59 | 
            +
                    (desc.nil? || (desc ? descending? : !descending?))
         | 
| 60 | 
            +
                end
         | 
| 59 61 |  | 
| 60 | 
            -
             | 
| 61 | 
            -
                  # @return [Boolean] true if given grid is ordered by given column.
         | 
| 62 | 
            -
                  def ordered_by?(column)
         | 
| 63 | 
            -
                    order_column == column_by_name(column)
         | 
| 64 | 
            -
                  end
         | 
| 62 | 
            +
                private
         | 
| 65 63 |  | 
| 66 | 
            -
             | 
| 64 | 
            +
                def apply_order(assets)
         | 
| 65 | 
            +
                  return assets unless order
         | 
| 67 66 |  | 
| 68 | 
            -
                   | 
| 69 | 
            -
                     | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 67 | 
            +
                  if order_column.order_by_value?
         | 
| 68 | 
            +
                    assets = assets.sort_by do |asset|
         | 
| 69 | 
            +
                      order_column.order_by_value(asset, self)
         | 
| 70 | 
            +
                    end
         | 
| 71 | 
            +
                    descending? ? assets.reverse : assets
         | 
| 72 | 
            +
                  elsif descending?
         | 
| 73 | 
            +
                    if order_column.order_desc
         | 
| 74 | 
            +
                      apply_asc_order(assets, order_column.order_desc)
         | 
| 75 75 | 
             
                    else
         | 
| 76 | 
            -
                       | 
| 77 | 
            -
                        if order_column.order_desc
         | 
| 78 | 
            -
                          apply_asc_order(assets, order_column.order_desc)
         | 
| 79 | 
            -
                        else
         | 
| 80 | 
            -
                          apply_desc_order(assets, order_column.order)
         | 
| 81 | 
            -
                        end
         | 
| 82 | 
            -
                      else
         | 
| 83 | 
            -
                        apply_asc_order(assets, order_column.order)
         | 
| 84 | 
            -
                      end
         | 
| 76 | 
            +
                      apply_desc_order(assets, order_column.order)
         | 
| 85 77 | 
             
                    end
         | 
| 78 | 
            +
                  else
         | 
| 79 | 
            +
                    apply_asc_order(assets, order_column.order)
         | 
| 86 80 | 
             
                  end
         | 
| 81 | 
            +
                end
         | 
| 87 82 |  | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
                    column = column_by_name(order)
         | 
| 91 | 
            -
                    unless column
         | 
| 92 | 
            -
                      self.class.order_unsupported(order, "no column #{order} in #{self.class}")
         | 
| 93 | 
            -
                    end
         | 
| 94 | 
            -
                    unless column.supports_order?
         | 
| 95 | 
            -
                      self.class.order_unsupported(column.name, "column don't support order" )
         | 
| 96 | 
            -
                    end
         | 
| 97 | 
            -
                  end
         | 
| 83 | 
            +
                def check_order_valid!
         | 
| 84 | 
            +
                  return unless order
         | 
| 98 85 |  | 
| 99 | 
            -
                   | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
                    else
         | 
| 103 | 
            -
                      driver.asc(assets, order)
         | 
| 104 | 
            -
                    end
         | 
| 105 | 
            -
                  end
         | 
| 86 | 
            +
                  column = column_by_name(order)
         | 
| 87 | 
            +
                  self.class.order_unsupported(order, "no column #{order} in #{self.class}") unless column
         | 
| 88 | 
            +
                  return if column.supports_order?
         | 
| 106 89 |  | 
| 107 | 
            -
                   | 
| 108 | 
            -
             | 
| 109 | 
            -
             | 
| 110 | 
            -
             | 
| 111 | 
            -
             | 
| 112 | 
            -
                     | 
| 90 | 
            +
                  self.class.order_unsupported(column.name, "column don't support order")
         | 
| 91 | 
            +
                end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                def apply_asc_order(assets, order)
         | 
| 94 | 
            +
                  if order.respond_to?(:call)
         | 
| 95 | 
            +
                    apply_block_order(assets, order)
         | 
| 96 | 
            +
                  else
         | 
| 97 | 
            +
                    driver.asc(assets, order)
         | 
| 113 98 | 
             
                  end
         | 
| 99 | 
            +
                end
         | 
| 114 100 |  | 
| 115 | 
            -
             | 
| 116 | 
            -
             | 
| 117 | 
            -
             | 
| 118 | 
            -
             | 
| 101 | 
            +
                def apply_desc_order(assets, order)
         | 
| 102 | 
            +
                  if order.respond_to?(:call)
         | 
| 103 | 
            +
                    reverse_order(apply_asc_order(assets, order))
         | 
| 104 | 
            +
                  else
         | 
| 105 | 
            +
                    driver.desc(assets, order)
         | 
| 119 106 | 
             
                  end
         | 
| 107 | 
            +
                end
         | 
| 120 108 |  | 
| 121 | 
            -
             | 
| 122 | 
            -
             | 
| 123 | 
            -
             | 
| 124 | 
            -
             | 
| 125 | 
            -
                     | 
| 126 | 
            -
             | 
| 127 | 
            -
             | 
| 128 | 
            -
             | 
| 129 | 
            -
             | 
| 109 | 
            +
                def reverse_order(assets)
         | 
| 110 | 
            +
                  driver.reverse_order(assets)
         | 
| 111 | 
            +
                rescue NotImplementedError
         | 
| 112 | 
            +
                  self.class.order_unsupported(order_column.name,
         | 
| 113 | 
            +
                    "Your ORM do not support reverse order: please specify :order_desc option manually",)
         | 
| 114 | 
            +
                end
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                def apply_block_order(assets, order)
         | 
| 117 | 
            +
                  case order.arity
         | 
| 118 | 
            +
                  when -1, 0
         | 
| 119 | 
            +
                    assets.instance_eval(&order)
         | 
| 120 | 
            +
                  when 1
         | 
| 121 | 
            +
                    order.call(assets)
         | 
| 122 | 
            +
                  else
         | 
| 123 | 
            +
                    self.class.order_unsupported(order_column.name, "Order option proc can not handle more than one argument")
         | 
| 130 124 | 
             
                  end
         | 
| 131 125 | 
             
                end
         | 
| 132 126 | 
             
              end
         | 
    
        data/lib/datagrid/rspec.rb
    CHANGED
    
    | @@ -1,16 +1,16 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            require "datagrid"
         | 
| 2 4 |  | 
| 3 | 
            -
            #TODO: refactor this experimental shit
         | 
| 5 | 
            +
            # TODO: refactor this experimental shit
         | 
| 4 6 | 
             
            shared_examples_for "Datagrid" do
         | 
| 5 7 | 
             
              describe "as Datagrid" do
         | 
| 6 | 
            -
             | 
| 7 8 | 
             
                it "should have at least one entry if assets" do
         | 
| 8 9 | 
             
                  subject.assets.should_not be_empty
         | 
| 9 10 | 
             
                end
         | 
| 10 11 |  | 
| 11 | 
            -
                described_class.columns(: | 
| 12 | 
            +
                described_class.columns(data: true).each do |column|
         | 
| 12 13 | 
             
                  describe "column ##{column.name}" do
         | 
| 13 | 
            -
             | 
| 14 14 | 
             
                    it "should has value in #data_hash" do
         | 
| 15 15 | 
             
                      subject.data_hash.first.should have_key(column.name)
         | 
| 16 16 | 
             
                    end
         | 
| @@ -25,14 +25,11 @@ shared_examples_for "Datagrid" do | |
| 25 25 | 
             
                      subject.assets.first.should_not be_nil
         | 
| 26 26 | 
             
                    end
         | 
| 27 27 | 
             
                  end
         | 
| 28 | 
            -
             | 
| 29 28 | 
             
                end
         | 
| 30 29 |  | 
| 31 30 | 
             
                described_class.filters.each do |filter|
         | 
| 32 31 | 
             
                  describe "filter ##{filter.name}" do
         | 
| 33 | 
            -
             | 
| 34 32 | 
             
                    let(:filter_value) do
         | 
| 35 | 
            -
             | 
| 36 33 | 
             
                      case Datagrid::Filters::FILTER_TYPES.invert[filter.class]
         | 
| 37 34 | 
             
                      when :default, :string
         | 
| 38 35 | 
             
                        "text"
         | 
| @@ -46,23 +43,22 @@ shared_examples_for "Datagrid" do | |
| 46 43 | 
             
                        1
         | 
| 47 44 | 
             
                      when :enum
         | 
| 48 45 | 
             
                        select = subject.select_options(filter)
         | 
| 49 | 
            -
                        select.first | 
| 46 | 
            +
                        select.first&.last
         | 
| 50 47 | 
             
                      else
         | 
| 51 48 | 
             
                        raise "unknown filter type: #{filter.class}"
         | 
| 52 49 | 
             
                      end.to_s
         | 
| 53 50 | 
             
                    end
         | 
| 54 51 |  | 
| 55 52 | 
             
                    before(:each) do
         | 
| 56 | 
            -
                      subject.attributes = {filter.name => filter_value}
         | 
| 57 | 
            -
                      subject. | 
| 53 | 
            +
                      subject.attributes = { filter.name => filter_value }
         | 
| 54 | 
            +
                      subject.public_send(filter.name).should_not be_nil
         | 
| 58 55 | 
             
                    end
         | 
| 59 56 |  | 
| 60 57 | 
             
                    it "should be supported" do
         | 
| 61 58 | 
             
                      subject.assets.should_not be_nil
         | 
| 62 | 
            -
                      #TODO: better matcher.
         | 
| 59 | 
            +
                      # TODO: better matcher.
         | 
| 63 60 | 
             
                    end
         | 
| 64 61 | 
             
                  end
         | 
| 65 62 | 
             
                end
         | 
| 66 | 
            -
             | 
| 67 63 | 
             
              end
         | 
| 68 64 | 
             
            end
         | 
    
        data/lib/datagrid/utils.rb
    CHANGED
    
    | @@ -1,52 +1,54 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            module Datagrid
         | 
| 2 4 | 
             
              # @!visibility private
         | 
| 3 | 
            -
              module Utils | 
| 5 | 
            +
              module Utils
         | 
| 4 6 | 
             
                class << self
         | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
                  TRUTH = [true, 1, "1", "true", "yes", "on"]
         | 
| 7 | 
            +
                  TRUTH = [true, 1, "1", "true", "yes", "on"].freeze
         | 
| 8 8 |  | 
| 9 9 | 
             
                  def booleanize(value)
         | 
| 10 | 
            -
                    if value.respond_to?(:downcase)
         | 
| 11 | 
            -
                      value = value.downcase
         | 
| 12 | 
            -
                    end
         | 
| 10 | 
            +
                    value = value.downcase if value.respond_to?(:downcase)
         | 
| 13 11 | 
             
                    TRUTH.include?(value)
         | 
| 14 12 | 
             
                  end
         | 
| 15 13 |  | 
| 16 14 | 
             
                  def translate_from_namespace(namespace, grid_class, key)
         | 
| 17 | 
            -
             | 
| 18 15 | 
             
                    lookups = []
         | 
| 19 16 | 
             
                    namespaced_key = "#{namespace}.#{key}"
         | 
| 20 17 |  | 
| 21 18 | 
             
                    grid_class.ancestors.each do |ancestor|
         | 
| 22 | 
            -
                      if ancestor.respond_to?(:model_name)
         | 
| 23 | 
            -
                        lookups << :"datagrid.#{ancestor.model_name.i18n_key}.#{namespaced_key}"
         | 
| 24 | 
            -
                      end
         | 
| 19 | 
            +
                      lookups << :"datagrid.#{ancestor.model_name.i18n_key}.#{namespaced_key}" if ancestor.respond_to?(:model_name)
         | 
| 25 20 | 
             
                    end
         | 
| 26 21 | 
             
                    lookups << :"datagrid.defaults.#{namespaced_key}"
         | 
| 27 22 | 
             
                    lookups << key.to_s.humanize
         | 
| 28 23 | 
             
                    I18n.t(lookups.shift, default: lookups).presence
         | 
| 29 24 | 
             
                  end
         | 
| 30 25 |  | 
| 26 | 
            +
                  def deprecator
         | 
| 27 | 
            +
                    if defined?(Rails) && Rails.version >= "7.1.0"
         | 
| 28 | 
            +
                      Rails.deprecator
         | 
| 29 | 
            +
                    else
         | 
| 30 | 
            +
                      ActiveSupport::Deprecation
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
             | 
| 31 34 | 
             
                  def warn_once(message, delay = 5)
         | 
| 32 35 | 
             
                    @warnings ||= {}
         | 
| 33 36 | 
             
                    timestamp = @warnings[message]
         | 
| 34 37 | 
             
                    return false if timestamp && timestamp >= Time.now - delay
         | 
| 35 | 
            -
             | 
| 38 | 
            +
             | 
| 39 | 
            +
                    deprecator.warn(message)
         | 
| 36 40 | 
             
                    @warnings[message] = Time.now
         | 
| 37 41 | 
             
                    true
         | 
| 38 42 | 
             
                  end
         | 
| 39 43 |  | 
| 40 44 | 
             
                  def add_html_classes(options, *classes)
         | 
| 45 | 
            +
                    return options if classes.empty?
         | 
| 46 | 
            +
             | 
| 41 47 | 
             
                    options = options.clone
         | 
| 42 | 
            -
                    options[:class] ||=  | 
| 43 | 
            -
                     | 
| 44 | 
            -
             | 
| 45 | 
            -
                     | 
| 46 | 
            -
                      # suppose that it is a String
         | 
| 47 | 
            -
                      options[:class] += " " unless options[:class].blank?
         | 
| 48 | 
            -
                      options[:class] += classes.join(" ")
         | 
| 49 | 
            -
                    end
         | 
| 48 | 
            +
                    options[:class] ||= []
         | 
| 49 | 
            +
                    array = options[:class].is_a?(Array)
         | 
| 50 | 
            +
                    value = [*options[:class], *classes]
         | 
| 51 | 
            +
                    options[:class] = array ? value : value.join(" ")
         | 
| 50 52 | 
             
                    options
         | 
| 51 53 | 
             
                  end
         | 
| 52 54 |  | 
| @@ -55,41 +57,42 @@ module Datagrid | |
| 55 57 | 
             
                  end
         | 
| 56 58 |  | 
| 57 59 | 
             
                  def extract_position_from_options(array, options)
         | 
| 58 | 
            -
                    before | 
| 59 | 
            -
                     | 
| 60 | 
            -
             | 
| 61 | 
            -
                    end
         | 
| 60 | 
            +
                    before = options[:before]
         | 
| 61 | 
            +
                    after = options[:after]
         | 
| 62 | 
            +
                    raise Datagrid::ConfigurationError, "Options :before and :after can not be used together" if before && after
         | 
| 62 63 | 
             
                    # Consider as before all
         | 
| 63 64 | 
             
                    return 0 if before == true
         | 
| 65 | 
            +
             | 
| 64 66 | 
             
                    if before
         | 
| 65 67 | 
             
                      before = before.to_sym
         | 
| 66 | 
            -
                      array.index {|c| c.name.to_sym == before }
         | 
| 68 | 
            +
                      array.index { |c| c.name.to_sym == before }
         | 
| 67 69 | 
             
                    elsif after
         | 
| 68 70 | 
             
                      after = after.to_sym
         | 
| 69 | 
            -
                      array.index {|c| c.name.to_sym == after } + 1
         | 
| 71 | 
            +
                      array.index { |c| c.name.to_sym == after } + 1
         | 
| 70 72 | 
             
                    else
         | 
| 71 73 | 
             
                      -1
         | 
| 72 74 | 
             
                    end
         | 
| 73 75 | 
             
                  end
         | 
| 74 76 |  | 
| 75 77 | 
             
                  def apply_args(*args, &block)
         | 
| 76 | 
            -
                    size = block.arity  | 
| 78 | 
            +
                    size = block.arity.negative? ? args.size : block.arity
         | 
| 77 79 | 
             
                    block.call(*args.slice(0, size))
         | 
| 78 80 | 
             
                  end
         | 
| 79 81 |  | 
| 80 82 | 
             
                  def parse_date(value)
         | 
| 81 83 | 
             
                    return nil if value.blank?
         | 
| 82 84 | 
             
                    return value if value.is_a?(Range)
         | 
| 85 | 
            +
             | 
| 83 86 | 
             
                    if value.is_a?(String)
         | 
| 84 87 | 
             
                      Array(Datagrid.configuration.date_formats).each do |format|
         | 
| 85 | 
            -
                         | 
| 86 | 
            -
             | 
| 87 | 
            -
                         | 
| 88 | 
            -
                        end
         | 
| 88 | 
            +
                        return Date.strptime(value, format)
         | 
| 89 | 
            +
                      rescue ::ArgumentError
         | 
| 90 | 
            +
                        nil
         | 
| 89 91 | 
             
                      end
         | 
| 90 92 | 
             
                    end
         | 
| 91 93 | 
             
                    return Date.parse(value) if value.is_a?(String)
         | 
| 92 94 | 
             
                    return value.to_date if value.respond_to?(:to_date)
         | 
| 95 | 
            +
             | 
| 93 96 | 
             
                    value
         | 
| 94 97 | 
             
                  rescue ::ArgumentError
         | 
| 95 98 | 
             
                    nil
         | 
| @@ -98,16 +101,18 @@ module Datagrid | |
| 98 101 | 
             
                  def parse_datetime(value)
         | 
| 99 102 | 
             
                    return nil if value.blank?
         | 
| 100 103 | 
             
                    return value if value.is_a?(Range)
         | 
| 104 | 
            +
                    return value if defined?(ActiveSupport::TimeWithZone) && value.is_a?(ActiveSupport::TimeWithZone)
         | 
| 105 | 
            +
             | 
| 101 106 | 
             
                    if value.is_a?(String)
         | 
| 102 107 | 
             
                      Array(Datagrid.configuration.datetime_formats).each do |format|
         | 
| 103 | 
            -
                         | 
| 104 | 
            -
             | 
| 105 | 
            -
                         | 
| 106 | 
            -
                        end
         | 
| 108 | 
            +
                        return Time.strptime(value, format)
         | 
| 109 | 
            +
                      rescue ::ArgumentError
         | 
| 110 | 
            +
                        nil
         | 
| 107 111 | 
             
                      end
         | 
| 108 112 | 
             
                    end
         | 
| 109 113 | 
             
                    return Time.parse(value) if value.is_a?(String)
         | 
| 110 114 | 
             
                    return value.to_time if value.respond_to?(:to_time)
         | 
| 115 | 
            +
             | 
| 111 116 | 
             
                    value
         | 
| 112 117 | 
             
                  rescue ::ArgumentError
         | 
| 113 118 | 
             
                    nil
         | 
| @@ -116,10 +121,8 @@ module Datagrid | |
| 116 121 | 
             
                  def format_date_as_timestamp(value)
         | 
| 117 122 | 
             
                    if !value
         | 
| 118 123 | 
             
                      value
         | 
| 119 | 
            -
                    elsif value.is_a?(Array)
         | 
| 120 | 
            -
                      [value.first.try(:beginning_of_day), value.last.try(:end_of_day)]
         | 
| 121 124 | 
             
                    elsif value.is_a?(Range)
         | 
| 122 | 
            -
                       | 
| 125 | 
            +
                      value.begin&.beginning_of_day..value.end&.end_of_day
         | 
| 123 126 | 
             
                    else
         | 
| 124 127 | 
             
                      value.beginning_of_day..value.end_of_day
         | 
| 125 128 | 
             
                    end
         | 
| @@ -135,6 +138,7 @@ module Datagrid | |
| 135 138 | 
             
                  end
         | 
| 136 139 |  | 
| 137 140 | 
             
                  protected
         | 
| 141 | 
            +
             | 
| 138 142 | 
             
                  def property_availability(grid, option, default)
         | 
| 139 143 | 
             
                    case option
         | 
| 140 144 | 
             
                    when nil
         | 
    
        data/lib/datagrid/version.rb
    CHANGED
    
    
    
        data/lib/datagrid.rb
    CHANGED
    
    | @@ -1,49 +1,39 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            require "action_view"
         | 
| 2 4 | 
             
            require "datagrid/configuration"
         | 
| 5 | 
            +
            require "datagrid/engine"
         | 
| 3 6 |  | 
| 7 | 
            +
            # @main README.md
         | 
| 4 8 | 
             
            module Datagrid
         | 
| 5 | 
            -
             | 
| 6 | 
            -
              extend ActiveSupport::Autoload
         | 
| 7 | 
            -
             | 
| 8 | 
            -
              autoload :Core
         | 
| 9 | 
            -
              autoload :ActiveModel
         | 
| 10 | 
            -
              autoload :Filters
         | 
| 11 | 
            -
              autoload :Columns
         | 
| 12 | 
            -
              autoload :ColumnNamesAttribute
         | 
| 13 | 
            -
              autoload :Ordering
         | 
| 14 | 
            -
              autoload :Configuration
         | 
| 15 | 
            -
             | 
| 16 | 
            -
              autoload :Helper
         | 
| 17 | 
            -
              ActionView::Base.send(:include, Datagrid::Helper)
         | 
| 18 | 
            -
             | 
| 19 | 
            -
              autoload :FormBuilder
         | 
| 20 | 
            -
              ActionView::Helpers::FormBuilder.send(:include, Datagrid::FormBuilder)
         | 
| 21 | 
            -
             | 
| 22 | 
            -
              autoload :Renderer
         | 
| 23 | 
            -
             | 
| 24 | 
            -
              autoload :Engine
         | 
| 25 | 
            -
             | 
| 26 9 | 
             
              # @!visibility private
         | 
| 27 10 | 
             
              def self.included(base)
         | 
| 11 | 
            +
                Utils.warn_once("Including Datagrid is deprecated. Inherit Datagrid::Base instead.")
         | 
| 28 12 | 
             
                base.class_eval do
         | 
| 29 | 
            -
             | 
| 30 13 | 
             
                  include ::Datagrid::Core
         | 
| 31 14 | 
             
                  include ::Datagrid::ActiveModel
         | 
| 32 15 | 
             
                  include ::Datagrid::Filters
         | 
| 33 16 | 
             
                  include ::Datagrid::Columns
         | 
| 34 17 | 
             
                  include ::Datagrid::ColumnNamesAttribute
         | 
| 35 18 | 
             
                  include ::Datagrid::Ordering
         | 
| 36 | 
            -
             | 
| 37 19 | 
             
                end
         | 
| 38 20 | 
             
              end
         | 
| 39 21 |  | 
| 22 | 
            +
              def self.configuration
         | 
| 23 | 
            +
                @configuration ||= Configuration.new
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              # Configure
         | 
| 27 | 
            +
              def self.configure(&block)
         | 
| 28 | 
            +
                block.call(configuration)
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
             | 
| 40 31 | 
             
              class ConfigurationError < StandardError; end
         | 
| 41 32 | 
             
              class ArgumentError < ::ArgumentError; end
         | 
| 42 33 | 
             
              class ColumnUnavailableError < StandardError; end
         | 
| 43 | 
            -
             | 
| 44 34 | 
             
            end
         | 
| 45 35 |  | 
| 46 | 
            -
            require "datagrid/ | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 36 | 
            +
            require "datagrid/base"
         | 
| 37 | 
            +
            require "datagrid/generators/scaffold"
         | 
| 38 | 
            +
            require "datagrid/generators/views"
         | 
| 39 | 
            +
            I18n.load_path << File.expand_path("datagrid/locale/en.yml", __dir__)
         | 
    
        data/templates/base.rb.erb
    CHANGED
    
    | @@ -1,7 +1,4 @@ | |
| 1 | 
            -
            class  | 
| 2 | 
            -
             | 
| 3 | 
            -
              include Datagrid
         | 
| 4 | 
            -
             | 
| 1 | 
            +
            class ApplicationGrid < Datagrid::Base
         | 
| 5 2 | 
             
              self.default_column_options = {
         | 
| 6 3 | 
             
                # Uncomment to disable the default order
         | 
| 7 4 | 
             
                # order: false,
         | 
| @@ -11,11 +8,40 @@ class BaseGrid | |
| 11 8 | 
             
              # Enable forbidden attributes protection
         | 
| 12 9 | 
             
              # self.forbidden_attributes_protection = true
         | 
| 13 10 |  | 
| 14 | 
            -
               | 
| 11 | 
            +
              # Makes a date column
         | 
| 12 | 
            +
              # @param name [Symbol] Column name
         | 
| 13 | 
            +
              # @param args [Array] Other column helper arguments
         | 
| 14 | 
            +
              # @example
         | 
| 15 | 
            +
              #   date_column(:created_at)
         | 
| 16 | 
            +
              #   date_column(:owner_registered_at) do |model|
         | 
| 17 | 
            +
              #     model.owner.registered_at
         | 
| 18 | 
            +
              #   end
         | 
| 19 | 
            +
              def self.date_column(name, *args, &block)
         | 
| 15 20 | 
             
                column(name, *args) do |model|
         | 
| 16 | 
            -
                  format( | 
| 17 | 
            -
                    date | 
| 21 | 
            +
                  format(block ? block.call(model) : model.public_send(name)) do |date|
         | 
| 22 | 
            +
                    date&.strftime("%m/%d/%Y") || "—".html_safe
         | 
| 18 23 | 
             
                  end
         | 
| 19 24 | 
             
                end
         | 
| 20 25 | 
             
              end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              # Makes a boolean YES/NO column
         | 
| 28 | 
            +
              # @param name [Symbol] Column name
         | 
| 29 | 
            +
              # @param args [Array] Other column helper arguments
         | 
| 30 | 
            +
              # @example
         | 
| 31 | 
            +
              #   boolean_column(:approved)
         | 
| 32 | 
            +
              #   boolean_column(:has_tasks, preload: :tasks) do |model|
         | 
| 33 | 
            +
              #     model.tasks.unfinished.any?
         | 
| 34 | 
            +
              #   end
         | 
| 35 | 
            +
              def self.boolean_column(name, *args, &block)
         | 
| 36 | 
            +
                column(name, *args) do |model|
         | 
| 37 | 
            +
                  value = block ? block.call(model) : model.public_send(name)
         | 
| 38 | 
            +
                  value ? "Yes" : "No"
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              # Uncomment to shorten URL query string for all grids.
         | 
| 43 | 
            +
              # May cause collisions if multiple grids are used on the same page.
         | 
| 44 | 
            +
              # def param_name
         | 
| 45 | 
            +
              #   'grid'
         | 
| 46 | 
            +
              # end
         | 
| 21 47 | 
             
            end
         | 
    
        data/templates/grid.rb.erb
    CHANGED