datagrid 1.6.2 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/Readme.markdown +5 -4
- data/datagrid.gemspec +10 -14
- data/lib/datagrid/active_model.rb +25 -29
- data/lib/datagrid/column_names_attribute.rb +21 -20
- data/lib/datagrid/columns/column.rb +7 -1
- data/lib/datagrid/columns.rb +157 -189
- data/lib/datagrid/configuration.rb +6 -1
- data/lib/datagrid/core.rb +43 -22
- data/lib/datagrid/drivers/abstract_driver.rb +2 -1
- data/lib/datagrid/drivers/active_record.rb +2 -1
- data/lib/datagrid/drivers/array.rb +2 -1
- data/lib/datagrid/drivers/mongo_mapper.rb +2 -1
- data/lib/datagrid/drivers/mongoid.rb +3 -2
- data/lib/datagrid/drivers/sequel.rb +2 -1
- data/lib/datagrid/drivers.rb +2 -1
- data/lib/datagrid/engine.rb +3 -2
- data/lib/datagrid/filters/base_filter.rb +5 -2
- data/lib/datagrid/filters/boolean_enum_filter.rb +5 -3
- data/lib/datagrid/filters/boolean_filter.rb +2 -1
- data/lib/datagrid/filters/composite_filters.rb +9 -15
- data/lib/datagrid/filters/extended_boolean_filter.rb +2 -1
- data/lib/datagrid/filters/select_options.rb +34 -1
- data/lib/datagrid/filters.rb +38 -15
- data/lib/datagrid/form_builder.rb +17 -8
- data/lib/datagrid/helper.rb +49 -23
- data/lib/datagrid/ordering.rb +14 -14
- data/lib/datagrid/renderer.rb +3 -4
- data/lib/datagrid/scaffold.rb +1 -1
- data/lib/datagrid/utils.rb +1 -0
- data/lib/datagrid/version.rb +1 -1
- data/lib/datagrid.rb +2 -1
- metadata +8 -8
    
        data/lib/datagrid/columns.rb
    CHANGED
    
    | @@ -6,142 +6,116 @@ module Datagrid | |
| 6 6 | 
             
              module Columns
         | 
| 7 7 | 
             
                require "datagrid/columns/column"
         | 
| 8 8 |  | 
| 9 | 
            +
                # @!method default_column_options=
         | 
| 10 | 
            +
                # @param value [Hash] default options passed to #column method call
         | 
| 11 | 
            +
                # @return [Hash] default options passed to #column method call
         | 
| 12 | 
            +
                # @example
         | 
| 13 | 
            +
                #   # Disable default order
         | 
| 14 | 
            +
                #   self.default_column_options = { order: false }
         | 
| 15 | 
            +
                #   # Makes entire report HTML
         | 
| 16 | 
            +
                #   self.default_column_options = { html: true }
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                # @!method default_column_options
         | 
| 19 | 
            +
                # @return [Hash]
         | 
| 20 | 
            +
                # @see #default_column_options=
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                # @!method batch_size=
         | 
| 23 | 
            +
                # @param value [Integer] Specify a default batch size when generating CSV or just data. Default: 1000
         | 
| 24 | 
            +
                # @return [Integer] Specify a default batch size when generating CSV or just data.
         | 
| 25 | 
            +
                # @example
         | 
| 26 | 
            +
                #   self.batch_size = 500
         | 
| 27 | 
            +
                #   # Disable batches
         | 
| 28 | 
            +
                #   self.batch_size = nil
         | 
| 29 | 
            +
                #
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                # @!method batch_size
         | 
| 32 | 
            +
                # @return [Integer]
         | 
| 33 | 
            +
                # @see #batch_size=
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                # @visibility private
         | 
| 9 36 | 
             
                def self.included(base)
         | 
| 10 37 | 
             
                  base.extend         ClassMethods
         | 
| 11 38 | 
             
                  base.class_eval do
         | 
| 12 | 
            -
             | 
| 13 39 | 
             
                    include Datagrid::Core
         | 
| 14 40 |  | 
| 15 | 
            -
                    class_attribute :default_column_options, : | 
| 16 | 
            -
                     | 
| 17 | 
            -
             | 
| 18 | 
            -
                    class_attribute : | 
| 19 | 
            -
                    self.batch_size = 1000
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                    class_attribute :columns_array
         | 
| 22 | 
            -
                    self.columns_array = []
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                    class_attribute :cached
         | 
| 25 | 
            -
                    self.cached = false
         | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 41 | 
            +
                    class_attribute :default_column_options, instance_writer: false, default: {}
         | 
| 42 | 
            +
                    class_attribute :batch_size, default: 1000
         | 
| 43 | 
            +
                    class_attribute :columns_array, default: []
         | 
| 44 | 
            +
                    class_attribute :cached, default: false
         | 
| 28 45 | 
             
                    class_attribute :decorator, instance_writer: false
         | 
| 29 | 
            -
             | 
| 30 46 | 
             
                  end
         | 
| 31 47 | 
             
                  base.send :include, InstanceMethods
         | 
| 32 | 
            -
                end | 
| 48 | 
            +
                end
         | 
| 33 49 |  | 
| 34 50 | 
             
                module ClassMethods
         | 
| 35 51 |  | 
| 36 | 
            -
                  ##
         | 
| 37 | 
            -
                  # :method: batch_size=
         | 
| 38 | 
            -
                  #
         | 
| 39 | 
            -
                  # :call-seq: batch_size=(size)
         | 
| 40 | 
            -
                  #
         | 
| 41 | 
            -
                  # Specify a default batch size when generating CSV or just data
         | 
| 42 | 
            -
                  # Default: 1000
         | 
| 43 | 
            -
                  #
         | 
| 44 | 
            -
                  #   self.batch_size = 500
         | 
| 45 | 
            -
                  #   # Disable batches
         | 
| 46 | 
            -
                  #   self.batch_size = nil
         | 
| 47 | 
            -
                  #
         | 
| 48 52 |  | 
| 49 | 
            -
                  ##
         | 
| 50 | 
            -
                  # :method: batch_size
         | 
| 51 | 
            -
                  #
         | 
| 52 | 
            -
                  # :call-seq: batch_size
         | 
| 53 | 
            -
                  #
         | 
| 54 | 
            -
                  # Returns specified batch_size configuration variable
         | 
| 55 | 
            -
                  # See <tt>batch_size=</tt> for more information
         | 
| 56 | 
            -
                  #
         | 
| 57 53 |  | 
| 58 | 
            -
                   | 
| 59 | 
            -
                  # : | 
| 60 | 
            -
                  #
         | 
| 61 | 
            -
                  #  | 
| 62 | 
            -
                  #
         | 
| 63 | 
            -
                  # Specifies default options for `column` method.
         | 
| 64 | 
            -
                  # They still can be overwritten at column level.
         | 
| 65 | 
            -
                  #
         | 
| 66 | 
            -
                  #   # Disable default order
         | 
| 67 | 
            -
                  #   self.default_column_options = { :order => false }
         | 
| 68 | 
            -
                  #   # Makes entire report HTML
         | 
| 69 | 
            -
                  #   self.default_column_options = { :html => true }
         | 
| 70 | 
            -
                  #
         | 
| 71 | 
            -
             | 
| 72 | 
            -
                  ##
         | 
| 73 | 
            -
                  # :method: default_column_options
         | 
| 74 | 
            -
                  #
         | 
| 75 | 
            -
                  # :call-seq: default_column_options
         | 
| 76 | 
            -
                  #
         | 
| 77 | 
            -
                  # Returns specified default column options hash
         | 
| 78 | 
            -
                  # See <tt>default_column_options=</tt> for more information
         | 
| 79 | 
            -
                  #
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                  # Returns a list of columns defined.
         | 
| 82 | 
            -
                  # All column definistion are returned by default
         | 
| 83 | 
            -
                  # You can limit the output with only columns you need like:
         | 
| 84 | 
            -
                  #
         | 
| 54 | 
            +
                  # @param data [Boolean] if true returns only columns with data representation. Default: false.
         | 
| 55 | 
            +
                  # @param html [Boolean] if true returns only columns with html columns. Default: false.
         | 
| 56 | 
            +
                  # @param column_names [Array<String>] list of column names if you want to limit data only to specified columns
         | 
| 57 | 
            +
                  # @return [Array<Datagrid::Columns::Column>] column definition objects
         | 
| 58 | 
            +
                  # @example
         | 
| 85 59 | 
             
                  #   GridClass.columns(:id, :name)
         | 
| 86 | 
            -
                   | 
| 87 | 
            -
             | 
| 88 | 
            -
                  #
         | 
| 89 | 
            -
                  # * :data - if true returns only non-html columns. Default: false.
         | 
| 90 | 
            -
                  def columns(*args)
         | 
| 91 | 
            -
                    filter_columns(columns_array, *args)
         | 
| 60 | 
            +
                  def columns(*column_names, data: false, html: false)
         | 
| 61 | 
            +
                    filter_columns(columns_array, *column_names, data: data, html: html)
         | 
| 92 62 | 
             
                  end
         | 
| 93 63 |  | 
| 94 64 | 
             
                  # Defines new datagrid column
         | 
| 95 65 | 
             
                  #
         | 
| 96 | 
            -
                  #  | 
| 97 | 
            -
                  #
         | 
| 98 | 
            -
                  #  | 
| 99 | 
            -
                  #  | 
| 100 | 
            -
                  #  | 
| 101 | 
            -
                  # * <tt>block</tt> - proc to calculate a column value
         | 
| 66 | 
            +
                  # @param name [Symbol] column name
         | 
| 67 | 
            +
                  # @param query [String, nil] a string representing the query to select this column (supports only ActiveRecord)
         | 
| 68 | 
            +
                  # @param options [Hash<Symbol, Object>] hash of options
         | 
| 69 | 
            +
                  # @param block [Block] proc to calculate a column value
         | 
| 70 | 
            +
                  # @return [Datagrid::Columns::Column]
         | 
| 102 71 | 
             
                  #
         | 
| 103 72 | 
             
                  # Available options:
         | 
| 104 73 | 
             
                  #
         | 
| 105 | 
            -
                  # * <tt | 
| 106 | 
            -
                  # * <tt | 
| 74 | 
            +
                  # * <tt>html</tt> - determines if current column should be present in html table and how is it formatted
         | 
| 75 | 
            +
                  # * <tt>order</tt> - determines if this column could be sortable and how.
         | 
| 107 76 | 
             
                  #   The value of order is explicitly passed to ORM ordering method.
         | 
| 108 77 | 
             
                  #   Ex: <tt>"created_at, id"</tt> for ActiveRecord, <tt>[:created_at, :id]</tt> for Mongoid
         | 
| 109 | 
            -
                  # * <tt | 
| 78 | 
            +
                  # * <tt>order_desc</tt> - determines a descending order for given column
         | 
| 110 79 | 
             
                  #   (only in case when <tt>:order</tt> can not be easily reversed by ORM)
         | 
| 111 | 
            -
                  # * <tt | 
| 80 | 
            +
                  # * <tt>order_by_value</tt> - used in case it is easier to perform ordering at ruby level not on database level.
         | 
| 112 81 | 
             
                  #   Warning: using ruby to order large datasets is very unrecommended.
         | 
| 113 82 | 
             
                  #   If set to true - datagrid will use column value to order by this column
         | 
| 114 83 | 
             
                  #   If block is given - datagrid will use value returned from block
         | 
| 115 | 
            -
                  # * <tt | 
| 116 | 
            -
                  # * <tt | 
| 117 | 
            -
                  # * <tt | 
| 118 | 
            -
                  # * <tt | 
| 119 | 
            -
                  # * <tt | 
| 120 | 
            -
                  # * <tt | 
| 121 | 
            -
                  # * <tt | 
| 122 | 
            -
                  #
         | 
| 123 | 
            -
                  #  | 
| 84 | 
            +
                  # * <tt>mandatory</tt> - if true, column will never be hidden with #column_names selection
         | 
| 85 | 
            +
                  # * <tt>url</tt> - a proc with one argument, pass this option to easily convert the value into an URL
         | 
| 86 | 
            +
                  # * <tt>before</tt> - determines the position of this column, by adding it before the column passed here
         | 
| 87 | 
            +
                  # * <tt>after</tt> - determines the position of this column, by adding it after the column passed here
         | 
| 88 | 
            +
                  # * <tt>if</tt> - the column is shown if the reult of calling this argument is true
         | 
| 89 | 
            +
                  # * <tt>unless</tt> - the column is shown unless the reult of calling this argument is true
         | 
| 90 | 
            +
                  # * <tt>preload</tt> - spefies which associations of the scope should be preloaded for this column
         | 
| 91 | 
            +
                  #
         | 
| 92 | 
            +
                  # @see https://github.com/bogdan/datagrid/wiki/Columns
         | 
| 124 93 | 
             
                  def column(name, query = nil, **options, &block)
         | 
| 125 | 
            -
                    define_column(columns_array, name, query, options, &block)
         | 
| 94 | 
            +
                    define_column(columns_array, name, query, **options, &block)
         | 
| 126 95 | 
             
                  end
         | 
| 127 96 |  | 
| 128 97 | 
             
                  # Returns column definition with given name
         | 
| 98 | 
            +
                  # @return [Datagrid::Columns::Column, nil]
         | 
| 129 99 | 
             
                  def column_by_name(name)
         | 
| 130 100 | 
             
                    find_column_by_name(columns_array, name)
         | 
| 131 101 | 
             
                  end
         | 
| 132 102 |  | 
| 133 103 | 
             
                  # Returns an array of all defined column names
         | 
| 104 | 
            +
                  # @return [Array<Datagrid::Columns::Column>]
         | 
| 134 105 | 
             
                  def column_names
         | 
| 135 106 | 
             
                    columns.map(&:name)
         | 
| 136 107 | 
             
                  end
         | 
| 137 108 |  | 
| 138 | 
            -
                   | 
| 109 | 
            +
                  # @!visibility private
         | 
| 110 | 
            +
                  def respond_to(&block)
         | 
| 139 111 | 
             
                    Datagrid::Columns::Column::ResponseFormat.new(&block)
         | 
| 140 112 | 
             
                  end
         | 
| 141 113 |  | 
| 142 114 | 
             
                  # Formats column value for HTML.
         | 
| 143 115 | 
             
                  # Helps to distinguish formatting as plain data and HTML
         | 
| 144 | 
            -
                  #
         | 
| 116 | 
            +
                  # @param value [Object] Value to be formatted
         | 
| 117 | 
            +
                  # @return [Datagrid::Columns::Column::ResponseFormat] Format object
         | 
| 118 | 
            +
                  # @example
         | 
| 145 119 | 
             
                  #   column(:name) do |model|
         | 
| 146 120 | 
             
                  #     format(model.name) do |value|
         | 
| 147 121 | 
             
                  #       content_tag(:strong, value)
         | 
| @@ -164,7 +138,8 @@ module Datagrid | |
| 164 138 |  | 
| 165 139 | 
             
                  # Defines a model decorator that will be used to define a column value.
         | 
| 166 140 | 
             
                  # All column blocks will be given a decorated version of the model.
         | 
| 167 | 
            -
                  #
         | 
| 141 | 
            +
                  # @return [void]
         | 
| 142 | 
            +
                  # @example
         | 
| 168 143 | 
             
                  #   decorate { |user| UserPresenter.new(user) }
         | 
| 169 144 | 
             
                  #
         | 
| 170 145 | 
             
                  #   decorate { UserPresenter } # a shortcut
         | 
| @@ -179,23 +154,25 @@ module Datagrid | |
| 179 154 | 
             
                    block_given? ? yield(presenter) : presenter
         | 
| 180 155 | 
             
                  end
         | 
| 181 156 |  | 
| 182 | 
            -
                   | 
| 157 | 
            +
                  # @!visibility private
         | 
| 158 | 
            +
                  def inherited(child_class)
         | 
| 183 159 | 
             
                    super(child_class)
         | 
| 184 160 | 
             
                    child_class.columns_array = self.columns_array.clone
         | 
| 185 161 | 
             
                  end
         | 
| 186 162 |  | 
| 187 | 
            -
                   | 
| 188 | 
            -
             | 
| 189 | 
            -
                     | 
| 190 | 
            -
                     | 
| 191 | 
            -
                     | 
| 192 | 
            -
                      (! | 
| 193 | 
            -
                        (! | 
| 194 | 
            -
                        (column.mandatory? ||  | 
| 163 | 
            +
                  # @!visibility private
         | 
| 164 | 
            +
                  def filter_columns(columns_array, *names, data: false, html: false)
         | 
| 165 | 
            +
                    names.compact!
         | 
| 166 | 
            +
                    names.map!(&:to_sym)
         | 
| 167 | 
            +
                    columns_array.select do |column|
         | 
| 168 | 
            +
                      (!data || column.data?) &&
         | 
| 169 | 
            +
                        (!html || column.html?) &&
         | 
| 170 | 
            +
                        (column.mandatory? || names.empty? || names.include?(column.name))
         | 
| 195 171 | 
             
                    end
         | 
| 196 172 | 
             
                  end
         | 
| 197 173 |  | 
| 198 | 
            -
                   | 
| 174 | 
            +
                  # @!visibility private
         | 
| 175 | 
            +
                  def define_column(columns, name, query = nil, **options, &block)
         | 
| 199 176 | 
             
                    check_scope_defined!("Scope should be defined before columns")
         | 
| 200 177 | 
             
                    block ||= lambda do |model|
         | 
| 201 178 | 
             
                      model.send(name)
         | 
| @@ -205,19 +182,22 @@ module Datagrid | |
| 205 182 | 
             
                      self, name, query, default_column_options.merge(options), &block
         | 
| 206 183 | 
             
                    )
         | 
| 207 184 | 
             
                    columns.insert(position, column)
         | 
| 185 | 
            +
                    column
         | 
| 208 186 | 
             
                  end
         | 
| 209 187 |  | 
| 210 | 
            -
                   | 
| 188 | 
            +
                  # @!visibility private
         | 
| 189 | 
            +
                  def find_column_by_name(columns,name)
         | 
| 211 190 | 
             
                    return name if name.is_a?(Datagrid::Columns::Column)
         | 
| 212 191 | 
             
                    columns.find do |col|
         | 
| 213 192 | 
             
                      col.name.to_sym == name.to_sym
         | 
| 214 193 | 
             
                    end
         | 
| 215 194 | 
             
                  end
         | 
| 216 195 |  | 
| 217 | 
            -
                end | 
| 196 | 
            +
                end
         | 
| 218 197 |  | 
| 219 198 | 
             
                module InstanceMethods
         | 
| 220 199 |  | 
| 200 | 
            +
                  # @!visibility private
         | 
| 221 201 | 
             
                  def assets
         | 
| 222 202 | 
             
                    append_column_preload(
         | 
| 223 203 | 
             
                      driver.append_column_queries(
         | 
| @@ -226,27 +206,23 @@ module Datagrid | |
| 226 206 | 
             
                    )
         | 
| 227 207 | 
             
                  end
         | 
| 228 208 |  | 
| 229 | 
            -
                  #  | 
| 230 | 
            -
                  #
         | 
| 231 | 
            -
                  # Arguments:
         | 
| 232 | 
            -
                  #
         | 
| 233 | 
            -
                  #   * <tt>column_names</tt> - list of column names if you want to limit data only to specified columns
         | 
| 209 | 
            +
                  # @param column_names [Array<String>] list of column names if you want to limit data only to specified columns
         | 
| 210 | 
            +
                  # @return [Array<String>] human readable column names. See also "Localization" section
         | 
| 234 211 | 
             
                  def header(*column_names)
         | 
| 235 212 | 
             
                    data_columns(*column_names).map(&:header)
         | 
| 236 213 | 
             
                  end
         | 
| 237 214 |  | 
| 238 | 
            -
                  #  | 
| 239 | 
            -
                  #
         | 
| 240 | 
            -
                  #  | 
| 241 | 
            -
                  #
         | 
| 242 | 
            -
                  #   * <tt>column_names</tt> - list of column names if you want to limit data only to specified columns
         | 
| 215 | 
            +
                  # @param asset [Object] asset from datagrid scope
         | 
| 216 | 
            +
                  # @param column_names [Array<String>] list of column names if you want to limit data only to specified columns
         | 
| 217 | 
            +
                  # @return [Array<Object>] column values for given asset
         | 
| 243 218 | 
             
                  def row_for(asset, *column_names)
         | 
| 244 219 | 
             
                    data_columns(*column_names).map do |column|
         | 
| 245 220 | 
             
                      data_value(column, asset)
         | 
| 246 221 | 
             
                    end
         | 
| 247 222 | 
             
                  end
         | 
| 248 223 |  | 
| 249 | 
            -
                  #  | 
| 224 | 
            +
                  # @param asset [Object] asset from datagrid scope
         | 
| 225 | 
            +
                  # @return [Hash] A mapping where keys are column names and values are column values for the given asset
         | 
| 250 226 | 
             
                  def hash_for(asset)
         | 
| 251 227 | 
             
                    result = {}
         | 
| 252 228 | 
             
                    self.data_columns.each do |column|
         | 
| @@ -255,22 +231,16 @@ module Datagrid | |
| 255 231 | 
             
                    result
         | 
| 256 232 | 
             
                  end
         | 
| 257 233 |  | 
| 258 | 
            -
                  #  | 
| 259 | 
            -
                  #
         | 
| 260 | 
            -
                  # Arguments:
         | 
| 261 | 
            -
                  #
         | 
| 262 | 
            -
                  #   * <tt>column_names</tt> - list of column names if you want to limit data only to specified columns
         | 
| 234 | 
            +
                  # @param column_names [Array<String>] list of column names if you want to limit data only to specified columns
         | 
| 235 | 
            +
                  # @return [Array<Array<Object>>] with data for each row in datagrid assets without header
         | 
| 263 236 | 
             
                  def rows(*column_names)
         | 
| 264 237 | 
             
                    map_with_batches do |asset|
         | 
| 265 238 | 
             
                      self.row_for(asset, *column_names)
         | 
| 266 239 | 
             
                    end
         | 
| 267 240 | 
             
                  end
         | 
| 268 241 |  | 
| 269 | 
            -
                  #  | 
| 270 | 
            -
                  #
         | 
| 271 | 
            -
                  # Arguments:
         | 
| 272 | 
            -
                  #
         | 
| 273 | 
            -
                  #   * <tt>column_names</tt> - list of column names if you want to limit data only to specified columns
         | 
| 242 | 
            +
                  # @param column_names [Array<String>] list of column names if you want to limit data only to specified columns
         | 
| 243 | 
            +
                  # @return [Array<Array<Object>>] data for each row in datagrid assets with header.
         | 
| 274 244 | 
             
                  def data(*column_names)
         | 
| 275 245 | 
             
                    self.rows(*column_names).unshift(self.header(*column_names))
         | 
| 276 246 | 
             
                  end
         | 
| @@ -278,41 +248,38 @@ module Datagrid | |
| 278 248 | 
             
                  # Return Array of Hashes where keys are column names and values are column values
         | 
| 279 249 | 
             
                  # for each row in filtered datagrid relation.
         | 
| 280 250 | 
             
                  #
         | 
| 281 | 
            -
                  #  | 
| 282 | 
            -
                  #
         | 
| 283 | 
            -
                  #      | 
| 284 | 
            -
                  # | 
| 285 | 
            -
                  # | 
| 286 | 
            -
                  # | 
| 287 | 
            -
                  #     end
         | 
| 288 | 
            -
                  #
         | 
| 289 | 
            -
                  #     Model.create!(:name => "One")
         | 
| 290 | 
            -
                  #     Model.create!(:name => "Two")
         | 
| 251 | 
            +
                  # @example
         | 
| 252 | 
            +
                  #   class MyGrid
         | 
| 253 | 
            +
                  #     scope { Model }
         | 
| 254 | 
            +
                  #     column(:id)
         | 
| 255 | 
            +
                  #     column(:name)
         | 
| 256 | 
            +
                  #   end
         | 
| 291 257 | 
             
                  #
         | 
| 292 | 
            -
                  # | 
| 258 | 
            +
                  #   Model.create!(name: "One")
         | 
| 259 | 
            +
                  #   Model.create!(name: "Two")
         | 
| 293 260 | 
             
                  #
         | 
| 261 | 
            +
                  #   MyGrid.new.data_hash # => [{name: "One"}, {name: "Two"}]
         | 
| 294 262 | 
             
                  def data_hash
         | 
| 295 263 | 
             
                    map_with_batches do |asset|
         | 
| 296 264 | 
             
                      hash_for(asset)
         | 
| 297 265 | 
             
                    end
         | 
| 298 266 | 
             
                  end
         | 
| 299 267 |  | 
| 300 | 
            -
                  #  | 
| 301 | 
            -
                  #  | 
| 302 | 
            -
                  #  | 
| 303 | 
            -
                  # Also you can specify options hash as last argument that is proxied to
         | 
| 304 | 
            -
                  # Ruby CSV library.
         | 
| 305 | 
            -
                  #
         | 
| 306 | 
            -
                  # Example:
         | 
| 268 | 
            +
                  # @param column_names [Array<String>]
         | 
| 269 | 
            +
                  # @param options [Hash] CSV generation options
         | 
| 270 | 
            +
                  # @return [String] a CSV representation of the data in the grid
         | 
| 307 271 | 
             
                  #
         | 
| 272 | 
            +
                  # @example
         | 
| 308 273 | 
             
                  #   grid.to_csv
         | 
| 309 274 | 
             
                  #   grid.to_csv(:id, :name)
         | 
| 310 | 
            -
                  #   grid.to_csv(: | 
| 311 | 
            -
                  def to_csv(*column_names)
         | 
| 275 | 
            +
                  #   grid.to_csv(col_sep: ';')
         | 
| 276 | 
            +
                  def to_csv(*column_names, **options)
         | 
| 312 277 | 
             
                    require "csv"
         | 
| 313 | 
            -
                     | 
| 314 | 
            -
             | 
| 315 | 
            -
             | 
| 278 | 
            +
                    CSV.generate(
         | 
| 279 | 
            +
                      headers: self.header(*column_names),
         | 
| 280 | 
            +
                      write_headers: true,
         | 
| 281 | 
            +
                      **options
         | 
| 282 | 
            +
                    ) do |csv|
         | 
| 316 283 | 
             
                      each_with_batches do |asset|
         | 
| 317 284 | 
             
                        csv << row_for(asset, *column_names)
         | 
| 318 285 | 
             
                      end
         | 
| @@ -320,43 +287,43 @@ module Datagrid | |
| 320 287 | 
             
                  end
         | 
| 321 288 |  | 
| 322 289 |  | 
| 323 | 
            -
                  #  | 
| 324 | 
            -
                  #
         | 
| 325 | 
            -
                  #  | 
| 326 | 
            -
                  #
         | 
| 290 | 
            +
                  # @param column_names [Array<Symbol, String>]
         | 
| 291 | 
            +
                  # @return [Array<Datagrid::Columns::Column>] all columns selected in grid instance
         | 
| 292 | 
            +
                  # @example
         | 
| 327 293 | 
             
                  #   MyGrid.new.columns # => all defined columns
         | 
| 328 | 
            -
                  #   grid = MyGrid.new(: | 
| 294 | 
            +
                  #   grid = MyGrid.new(column_names: [:id, :name])
         | 
| 329 295 | 
             
                  #   grid.columns # => id and name columns
         | 
| 330 296 | 
             
                  #   grid.columns(:id, :category) # => id and category column
         | 
| 331 | 
            -
                  def columns(* | 
| 332 | 
            -
                    self.class.filter_columns( | 
| 297 | 
            +
                  def columns(*column_names, data: false, html: false)
         | 
| 298 | 
            +
                    self.class.filter_columns(
         | 
| 299 | 
            +
                      columns_array, *column_names, data: data, html: html
         | 
| 300 | 
            +
                    ).select do |column|
         | 
| 301 | 
            +
                      column.enabled?(self)
         | 
| 302 | 
            +
                    end
         | 
| 333 303 | 
             
                  end
         | 
| 334 304 |  | 
| 335 | 
            -
                  #  | 
| 336 | 
            -
                   | 
| 337 | 
            -
             | 
| 338 | 
            -
                    options | 
| 339 | 
            -
                    names << options
         | 
| 340 | 
            -
                    self.columns(*names)
         | 
| 305 | 
            +
                  # @param column_names [Array<String, Symbol>] list of column names if you want to limit data only to specified columns
         | 
| 306 | 
            +
                  # @return columns that can be represented in plain data(non-html) way
         | 
| 307 | 
            +
                  def data_columns(*column_names, **options)
         | 
| 308 | 
            +
                    self.columns(*column_names, **options, data: true)
         | 
| 341 309 | 
             
                  end
         | 
| 342 310 |  | 
| 343 | 
            -
                  #  | 
| 344 | 
            -
                   | 
| 345 | 
            -
             | 
| 346 | 
            -
                    options | 
| 347 | 
            -
                    names << options
         | 
| 348 | 
            -
                    self.columns(*names)
         | 
| 311 | 
            +
                  # @param column_names [Array<String>] list of column names if you want to limit data only to specified columns
         | 
| 312 | 
            +
                  # @return all columns that can be represented in HTML table
         | 
| 313 | 
            +
                  def html_columns(*column_names, **options)
         | 
| 314 | 
            +
                    self.columns(*column_names, **options, html: true)
         | 
| 349 315 | 
             
                  end
         | 
| 350 316 |  | 
| 351 317 | 
             
                  # Finds a column definition by name
         | 
| 318 | 
            +
                  # @param name [String, Symbol] column name to be found
         | 
| 319 | 
            +
                  # @return [Datagrid::Columns::Column, nil]
         | 
| 352 320 | 
             
                  def column_by_name(name)
         | 
| 353 321 | 
             
                    self.class.find_column_by_name(columns_array, name)
         | 
| 354 322 | 
             
                  end
         | 
| 355 323 |  | 
| 356 324 | 
             
                  # Gives ability to have a different formatting for CSV and HTML column value.
         | 
| 357 325 | 
             
                  #
         | 
| 358 | 
            -
                  #  | 
| 359 | 
            -
                  #
         | 
| 326 | 
            +
                  # @example
         | 
| 360 327 | 
             
                  #   column(:name) do |model|
         | 
| 361 328 | 
             
                  #     format(model.name) do |value|
         | 
| 362 329 | 
             
                  #       content_tag(:strong, value)
         | 
| @@ -365,9 +332,10 @@ module Datagrid | |
| 365 332 | 
             
                  #
         | 
| 366 333 | 
             
                  #   column(:company) do |model|
         | 
| 367 334 | 
             
                  #     format(model.company.name) do
         | 
| 368 | 
            -
                  #       render : | 
| 335 | 
            +
                  #       render partial: "company_with_logo", locals: {company: model.company }
         | 
| 369 336 | 
             
                  #     end
         | 
| 370 337 | 
             
                  #   end
         | 
| 338 | 
            +
                  # @return [Datagrid::Columns::Column::ResponseFormat] Format object
         | 
| 371 339 | 
             
                  def format(value, &block)
         | 
| 372 340 | 
             
                    if block_given?
         | 
| 373 341 | 
             
                      self.class.format(value, &block)
         | 
| @@ -377,11 +345,8 @@ module Datagrid | |
| 377 345 | 
             
                    end
         | 
| 378 346 | 
             
                  end
         | 
| 379 347 |  | 
| 380 | 
            -
                  #  | 
| 381 | 
            -
                  #  | 
| 382 | 
            -
                  #
         | 
| 383 | 
            -
                  # Example:
         | 
| 384 | 
            -
                  #
         | 
| 348 | 
            +
                  # @return [Datagrid::Columns::DataRow] an object representing a grid row.
         | 
| 349 | 
            +
                  # @example
         | 
| 385 350 | 
             
                  #  class MyGrid
         | 
| 386 351 | 
             
                  #    scope { User }
         | 
| 387 352 | 
             
                  #    column(:id)
         | 
| @@ -400,23 +365,25 @@ module Datagrid | |
| 400 365 |  | 
| 401 366 | 
             
                  # Defines a column at instance level
         | 
| 402 367 | 
             
                  #
         | 
| 403 | 
            -
                  #  | 
| 368 | 
            +
                  # @see Datagrid::Columns::ClassMethods#column
         | 
| 404 369 | 
             
                  def column(name, query = nil, **options, &block)
         | 
| 405 | 
            -
                    self.class.define_column(columns_array, name, query, options, &block)
         | 
| 370 | 
            +
                    self.class.define_column(columns_array, name, query, **options, &block)
         | 
| 406 371 | 
             
                  end
         | 
| 407 372 |  | 
| 408 | 
            -
                   | 
| 373 | 
            +
                  # @!visibility private
         | 
| 374 | 
            +
                  def initialize(*)
         | 
| 409 375 | 
             
                    self.columns_array = self.class.columns_array.clone
         | 
| 410 376 | 
             
                    super
         | 
| 411 377 | 
             
                  end
         | 
| 412 378 |  | 
| 413 | 
            -
                  #  | 
| 379 | 
            +
                  # @return [Array<Datagrid::Columns::Column>] all columns that are possible to be displayed for the current grid object
         | 
| 414 380 | 
             
                  #
         | 
| 381 | 
            +
                  # @example
         | 
| 415 382 | 
             
                  #   class MyGrid
         | 
| 416 383 | 
             
                  #     filter(:search) {|scope, value| scope.full_text_search(value)}
         | 
| 417 384 | 
             
                  #     column(:id)
         | 
| 418 | 
            -
                  #     column(:name, : | 
| 419 | 
            -
                  #     column(:search_match, : | 
| 385 | 
            +
                  #     column(:name, mandatory: true)
         | 
| 386 | 
            +
                  #     column(:search_match, if: proc {|grid| grid.search.present? }) do |model, grid|
         | 
| 420 387 | 
             
                  #       search_match_line(model.searchable_content, grid.search)
         | 
| 421 388 | 
             
                  #     end
         | 
| 422 389 | 
             
                  #   end
         | 
| @@ -426,14 +393,13 @@ module Datagrid | |
| 426 393 | 
             
                  #   grid.available_columns # => [ #<Column:id>, #<Column:name> ]
         | 
| 427 394 | 
             
                  #   grid.search = "keyword"
         | 
| 428 395 | 
             
                  #   grid.available_columns # => [ #<Column:id>, #<Column:name>, #<Column:search_match> ]
         | 
| 429 | 
            -
                  #
         | 
| 430 396 | 
             
                  def available_columns
         | 
| 431 397 | 
             
                    columns_array.select do |column|
         | 
| 432 398 | 
             
                      column.enabled?(self)
         | 
| 433 399 | 
             
                    end
         | 
| 434 400 | 
             
                  end
         | 
| 435 401 |  | 
| 436 | 
            -
                  #  | 
| 402 | 
            +
                  # @return [Object] a cell data value for given column name and asset
         | 
| 437 403 | 
             
                  def data_value(column_name, asset)
         | 
| 438 404 | 
             
                    column = column_by_name(column_name)
         | 
| 439 405 | 
             
                    cache(column, asset, :data_value) do
         | 
| @@ -443,7 +409,7 @@ module Datagrid | |
| 443 409 | 
             
                    end
         | 
| 444 410 | 
             
                  end
         | 
| 445 411 |  | 
| 446 | 
            -
                  #  | 
| 412 | 
            +
                  # @return [Object] a cell HTML value for given column name and asset and view context
         | 
| 447 413 | 
             
                  def html_value(column_name, context, asset)
         | 
| 448 414 | 
             
                    column  = column_by_name(column_name)
         | 
| 449 415 | 
             
                    cache(column, asset, :html_value) do
         | 
| @@ -456,12 +422,13 @@ module Datagrid | |
| 456 422 | 
             
                    end
         | 
| 457 423 | 
             
                  end
         | 
| 458 424 |  | 
| 459 | 
            -
                  #  | 
| 425 | 
            +
                  # @return [Object] a decorated version of given model if decorator is specified or the model otherwise.
         | 
| 460 426 | 
             
                  def decorate(model)
         | 
| 461 427 | 
             
                    self.class.decorate(model)
         | 
| 462 428 | 
             
                  end
         | 
| 463 429 |  | 
| 464 | 
            -
                   | 
| 430 | 
            +
                  # @!visibility private
         | 
| 431 | 
            +
                  def generic_value(column, model)
         | 
| 465 432 | 
             
                    cache(column, model, :generic_value) do
         | 
| 466 433 | 
             
                      presenter = decorate(model)
         | 
| 467 434 | 
             
                      unless column.enabled?(self)
         | 
| @@ -544,10 +511,11 @@ module Datagrid | |
| 544 511 |  | 
| 545 512 | 
             
                    context.instance_exec(*args, &column.html_block)
         | 
| 546 513 | 
             
                  end
         | 
| 547 | 
            -
                end | 
| 548 | 
            -
             | 
| 549 | 
            -
                class DataRow
         | 
| 514 | 
            +
                end
         | 
| 550 515 |  | 
| 516 | 
            +
                # Object representing a single row of data when building a datagrid table
         | 
| 517 | 
            +
                # @see Datagrid::Columns::InstanceMethods#data_row
         | 
| 518 | 
            +
                class DataRow < BasicObject
         | 
| 551 519 | 
             
                  def initialize(grid, model)
         | 
| 552 520 | 
             
                    @grid = grid
         | 
| 553 521 | 
             
                    @model = model
         | 
| @@ -8,6 +8,11 @@ module Datagrid | |
| 8 8 | 
             
                yield(configuration)
         | 
| 9 9 | 
             
              end
         | 
| 10 10 |  | 
| 11 | 
            -
               | 
| 11 | 
            +
              # Datagrid configuration object
         | 
| 12 | 
            +
              class Configuration
         | 
| 13 | 
            +
                # @return [Array<String>] Date parsing formats
         | 
| 14 | 
            +
                attr_accessor :date_formats
         | 
| 15 | 
            +
                # @return [Array<String>] Timestamp parsing formats
         | 
| 16 | 
            +
                attr_accessor :datetime_formats
         | 
| 12 17 | 
             
              end
         | 
| 13 18 | 
             
            end
         |