datagrid 1.6.2 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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