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.
@@ -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, :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
47
  base.send :include, InstanceMethods
32
- end # self.included
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
- # :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
- #
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
- # Supported options:
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
- # Arguments:
97
- #
98
- # * <tt>name</tt> - column name
99
- # * <tt>query</tt> - a string representing the query to select this column (supports only ActiveRecord)
100
- # * <tt>options</tt> - hash of options
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>:html</tt> - determines if current column should be present in html table and how is it formatted
106
- # * <tt>:order</tt> - determines if this column could be sortable and how.
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>:order_desc</tt> - determines a descending order for given column
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>:order_by_value</tt> - used in case it is easier to perform ordering at ruby level not on database level.
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>:mandatory</tt> - if true, column will never be hidden with #column_names selection
116
- # * <tt>:url</tt> - a proc with one argument, pass this option to easily convert the value into an URL
117
- # * <tt>:before</tt> - determines the position of this column, by adding it before the column passed here
118
- # * <tt>:after</tt> - determines the position of this column, by adding it after the column passed here
119
- # * <tt>:if</tt> - the column is shown if the reult of calling this argument is true
120
- # * <tt>:unless</tt> - the column is shown unless the reult of calling this argument is true
121
- # * <tt>:preload</tt> - spefies which associations of the scope should be preloaded for this column
122
- #
123
- # See: https://github.com/bogdan/datagrid/wiki/Columns for examples
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
- def respond_to(&block) #:nodoc:
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
- def inherited(child_class) #:nodoc:
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
- def filter_columns(columns, *args) #:nodoc:
188
- options = args.extract_options!
189
- args.compact!
190
- args.map!(&:to_sym)
191
- columns.select do |column|
192
- (!options[:data] || column.data?) &&
193
- (!options[:html] || column.html?) &&
194
- (column.mandatory? || args.empty? || args.include?(column.name))
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
- def define_column(columns, name, query = nil, **options, &block) #:nodoc:
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
- def find_column_by_name(columns,name) #:nodoc:
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 # ClassMethods
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
- # 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
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
- # 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
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
- # Returns <tt>Hash</tt> where keys are column names and values are column values for the given asset
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
- # 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
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
- # 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
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
- # 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")
251
+ # @example
252
+ # class MyGrid
253
+ # scope { Model }
254
+ # column(:id)
255
+ # column(:name)
256
+ # end
291
257
  #
292
- # MyGrid.new.data_hash # => [{:name => "One"}, {:name => "Two"}]
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
- # 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:
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(:col_sep => ';')
311
- def to_csv(*column_names)
275
+ # grid.to_csv(col_sep: ';')
276
+ def to_csv(*column_names, **options)
312
277
  require "csv"
313
- options = column_names.extract_options!
314
- options = {:headers => self.header(*column_names), :write_headers => true}.merge!(options)
315
- CSV.generate(**options) do |csv|
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
- # Returns all columns selected in grid instance
324
- #
325
- # Examples:
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(:column_names => [:id, :name])
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(*args)
332
- self.class.filter_columns(columns_array, *args).select {|column| column.enabled?(self)}
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
- # Returns all columns that can be represented in plain data(non-html) way
336
- def data_columns(*names)
337
- options = names.extract_options!
338
- options[:data] = true
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
- # Returns all columns that can be represented in HTML table
344
- def html_columns(*names)
345
- options = names.extract_options!
346
- options[:html] = true
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
- # Example:
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 :partial => "company_with_logo", :locals => {:company => model.company }
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
- # Returns an object representing a grid row.
381
- # Allows to access column values
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
- # See Datagrid::Columns::ClassMethods#column for more info
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
- def initialize(*) #:nodoc:
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
- # Returns all columns that are possible to be displayed for the current grid object
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, :mandatory => true)
419
- # column(:search_match, :if => proc {|grid| grid.search.present? }) do |model, grid|
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
- # Return a cell data value for given column name and asset
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
- # Return a cell HTML value for given column name and asset and view context
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
- # Returns a decorated version of given model if decorator is specified or the model otherwise.
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
- def generic_value(column, model) #:nodoc:
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 # InstanceMethods
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
- 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