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