Skip to content

Commit 287e677

Browse files
committedJan 27, 2025·
Merge branch 'main' of github.com:bogdan/datagrid
2 parents 6577577 + a47950d commit 287e677

File tree

8 files changed

+132
-8
lines changed

8 files changed

+132
-8
lines changed
 

‎lib/datagrid/columns.rb

+13-4
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,10 @@ module Datagrid
155155
#
156156
# self.default_column_options = { order: false }
157157
#
158+
# It can also accept a proc with the column instance as an argument:
159+
#
160+
# self.default_column_options = ->(column) { { order: column.name == :id } }
161+
#
158162
# ## Columns Visibility
159163
#
160164
# Columns can be dynamically shown or hidden based on the grid's `column_names` accessor.
@@ -201,15 +205,19 @@ module Datagrid
201205
# end
202206
module Columns
203207
# @!method default_column_options=(value)
204-
# @param [Hash] value default options passed to {#column} method call
205-
# @return [Hash] default options passed to {#column} method call
208+
# @param [Hash,Proc] value default options passed to {#column} method call.
209+
# When a proc is passed, it will be called with the column instance as an argument,
210+
# and expected to produce the options hash.
211+
# @return [Hash,Proc] default options passed to {#column} method call, or a proc that returns them.
206212
# @example Disable default order
207213
# self.default_column_options = { order: false }
208214
# @example Makes entire report HTML
209215
# self.default_column_options = { html: true }
216+
# @example Set the default header for all columns
217+
# self.default_column_options = ->(column) { { header: I18n.t(column.name, scope: 'my_scope.columns') } }
210218

211219
# @!method default_column_options
212-
# @return [Hash] default options passed to {#column} method call
220+
# @return [Hash,Proc] default options passed to {#column} method call, or a proc that returns them.
213221
# @see #default_column_options=
214222

215223
# @!method batch_size=(value)
@@ -368,9 +376,10 @@ def define_column(columns, name, query = nil, **options, &block)
368376
block ||= lambda do |model|
369377
model.public_send(name)
370378
end
379+
371380
position = Datagrid::Utils.extract_position_from_options(columns, options)
372381
column = Datagrid::Columns::Column.new(
373-
self, name, query, default_column_options.merge(options), &block
382+
self, name, query, options, &block
374383
)
375384
columns.insert(position, column)
376385
column

‎lib/datagrid/columns/column.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def initialize(grid_class, name, query, options = {}, &block)
5252
@grid_class = grid_class
5353
@name = name.to_sym
5454
@query = query
55-
@options = options
55+
@options = Datagrid::Utils.callable(grid_class.default_column_options, self).merge(options)
5656

5757
if options[:class]
5858
Datagrid::Utils.warn_once(

‎lib/datagrid/core.rb

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ def self.included(base)
5252
class_attribute :datagrid_attributes, instance_writer: false, default: []
5353
class_attribute :dynamic_block, instance_writer: false
5454
class_attribute :forbidden_attributes_protection, instance_writer: false, default: false
55+
class_attribute :default_filter_options, default: {}
5556
end
5657
end
5758

‎lib/datagrid/filters.rb

+23
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,35 @@ module Datagrid
123123
# filter(:id, :integer, header: "Identifier")
124124
# filter(:created_at, :date, range: true, default: proc { 1.month.ago.to_date..Date.today })
125125
#
126+
# ## Default Filter Options
127+
#
128+
# Default options for all filters in a grid can be set using `default_filter_options`.
129+
#
130+
# self.default_filter_options = { header: "" }
131+
#
132+
# It can also accept a proc with the filter instance as an argument:
133+
#
134+
# self.default_filter_options = ->(filter) { { header: I18n.t(filter.name, scope: 'filters') } }
135+
#
126136
# # Localization
127137
#
128138
# Filter labels can be localized or specified via the `:header` option:
129139
#
130140
# filter(:created_at, :date, header: "Creation date")
131141
# filter(:created_at, :date, header: proc { I18n.t("creation_date") })
132142
module Filters
143+
# @!method default_filter_options=(value)
144+
# @param [Hash,Proc] value default options passed to {#filter} method call.
145+
# When a proc is passed, it will be called with the filter instance as an argument,
146+
# and expected to produce the options hash.
147+
# @return [Hash,Proc] default options passed to {#filter} method call, or a proc that returns them.
148+
# @example Set the default header for all filters
149+
# self.default_filter_options = ->(filter) { { header: I18n.t(filter.name, scope: 'my_scope.filters') } }
150+
151+
# @!method default_filter_options
152+
# @return [Hash,Proc] default options passed to {#filter} method call, or a proc that returns them.
153+
# @see #default_filter_options=
154+
133155
require "datagrid/filters/base_filter"
134156
require "datagrid/filters/enum_filter"
135157
require "datagrid/filters/extended_boolean_filter"
@@ -163,6 +185,7 @@ module Filters
163185

164186
included do
165187
include Datagrid::Core
188+
class_attribute :default_filter_options, instance_writer: false, default: {}
166189
class_attribute :filters_array, default: []
167190
end
168191

‎lib/datagrid/filters/base_filter.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class BaseFilter
1515
def initialize(grid_class, name, **options, &block)
1616
self.grid_class = grid_class
1717
self.name = name.to_sym
18-
self.options = options
18+
self.options = Datagrid::Utils.callable(grid_class.default_filter_options, self).merge(options)
1919
self.block = block
2020
end
2121

‎lib/datagrid/utils.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,8 @@ def process_availability(grid, if_option, unless_option)
133133
!property_availability(grid, unless_option, false)
134134
end
135135

136-
def callable(value)
137-
value.respond_to?(:call) ? value.call : value
136+
def callable(value, *arguments)
137+
value.respond_to?(:call) ? value.call(*arguments) : value
138138
end
139139

140140
protected

‎spec/datagrid/columns_spec.rb

+41
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,30 @@ class Report27 < Datagrid::Base
9898
expect(Report27.new.header.first).to eq("Nombre")
9999
end
100100
end
101+
102+
it "uses configured default header" do
103+
grid = test_grid do
104+
self.default_column_options = ->(column) { { header: -> { I18n.t(column.name, scope: "other.location") } } }
105+
106+
scope { Entry }
107+
column(:name)
108+
end
109+
110+
store_translations(:en, other: { location: { name: "Nosaukums" } }) do
111+
expect(grid.header.first).to eq("Nosaukums")
112+
end
113+
end
114+
115+
it "prefers column-specific header over default" do
116+
grid = test_grid do
117+
self.default_column_options = { header: -> { "Global Header" } }
118+
119+
scope { Entry }
120+
column(:name, header: "Column Specific Header")
121+
end
122+
123+
expect(grid.header.first).to eq("Column Specific Header")
124+
end
101125
end
102126

103127
it "returns html_columns" do
@@ -311,6 +335,23 @@ def show?
311335
report.attributes = { order: :name, descending: true }
312336
expect(report.assets).to eq([second, first])
313337
end
338+
339+
it "accepts proc as default column options" do
340+
report = test_grid do
341+
scope { Entry }
342+
self.default_column_options = ->(column) { { order: column.name == :name ? "name" : false } }
343+
column(:id)
344+
column(:name)
345+
end
346+
first = Entry.create(name: "1st")
347+
second = Entry.create(name: "2nd")
348+
expect do
349+
report.attributes = { order: :id }
350+
report.assets
351+
end.to raise_error(Datagrid::OrderUnsupported)
352+
report.attributes = { order: :name, descending: true }
353+
expect(report.assets).to eq([second, first])
354+
end
314355
end
315356

316357
describe "fetching data in batches" do

‎spec/datagrid/filters_spec.rb

+50
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,30 @@ class InheritedReport < TranslatedReport
202202
expect(grid.filters.map(&:header)).to eq(["Navn"])
203203
end
204204
end
205+
206+
it "translates filter using configured default header" do
207+
grid = test_grid do
208+
self.default_filter_options = ->(filter) { { header: -> { I18n.t(filter.name, scope: "other.location") } } }
209+
210+
scope { Entry }
211+
filter(:name)
212+
end
213+
214+
store_translations(:en, other: { location: { name: "Nosaukums" } }) do
215+
expect(grid.filters.map(&:header)).to eq(["Nosaukums"])
216+
end
217+
end
218+
219+
it "prefers filter-specific header over default" do
220+
grid = test_grid do
221+
self.default_filter_options = { header: -> { "Global Header" } }
222+
223+
scope { Entry }
224+
filter(:name, header: "Filter Specific Header")
225+
end
226+
227+
expect(grid.filters.map(&:header)).to eq(["Filter Specific Header"])
228+
end
205229
end
206230

207231
describe "#select_options" do
@@ -304,4 +328,30 @@ class TestGrid8728 < Datagrid::Base
304328
end
305329
end
306330
end
331+
332+
describe ".default_filter_options" do
333+
it "passes default options to each filter definition" do
334+
grid = test_grid do
335+
scope { Entry }
336+
self.default_filter_options = { header: "Guess!" }
337+
filter(:id, :integer)
338+
filter(:name, :string)
339+
end
340+
341+
expect(grid.filters.map(&:header)).to eq(["Guess!", "Guess!"])
342+
end
343+
344+
it "accepts proc as default filter options" do
345+
grid = test_grid do
346+
scope { Entry }
347+
self.default_filter_options = lambda { |filter|
348+
{ header: filter.name == :id ? "Identification!" : filter.name.to_s }
349+
}
350+
filter(:id, :integer)
351+
filter(:name, :string)
352+
end
353+
354+
expect(grid.filters.map(&:header)).to eq(["Identification!", "name"])
355+
end
356+
end
307357
end

0 commit comments

Comments
 (0)
Please sign in to comment.