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