Class: CrudComponents::Presenters::Collection
- Includes:
- ColumnSelection
- Defined in:
- lib/crud_components/presenters/collection.rb
Overview
The single collection local every layout partial receives.
query: :auto (default) → build a Query from the request params and apply it
query: :static → no filter row, no sort links, params ignored
query:
picker: false (default) → no column picker; true → render the gear picked_columns: :auto (default) → read ?cols=; an Array → that exact selection (no param read — the backend resolved it)
Defined Under Namespace
Classes: Group
Constant Summary
Constants inherited from Base
Instance Attribute Summary collapse
-
#fieldset ⇒ Object
readonly
Returns the value of attribute fieldset.
-
#layout ⇒ Object
readonly
Returns the value of attribute layout.
-
#model ⇒ Object
readonly
Returns the value of attribute model.
-
#owner ⇒ Object
readonly
Returns the value of attribute owner.
-
#param_prefix ⇒ Object
readonly
Returns the value of attribute param_prefix.
-
#query ⇒ Object
readonly
Returns the value of attribute query.
-
#structure ⇒ Object
readonly
Returns the value of attribute structure.
Attributes inherited from Base
Instance Method Summary collapse
-
#actions_column? ⇒ Boolean
── actions ──────────────────────────────────────────────────────────.
-
#available_fields ⇒ Object
Every column this user is allowed to see — declared fieldset fields plus the dynamic columns — regardless of the current visibility selection.
-
#cell(field, record) ⇒ Object
── cells ────────────────────────────────────────────────────────────.
-
#cell_context ⇒ Object
Click-to-filter context for value renderers — only when this collection actually has a live query.
- #collection_actions ⇒ Object
-
#column_header(field) ⇒ Object
The
<th>title forfield: a customheader:(a String — html_safe to carry markup — or a view-context block, e.g. a link) replaces the plainhuman_name; otherwise thehuman_nameitself. -
#column_header_actions(field) ⇒ Object
The header actions for
fieldas an Actions presenter (collection-kind: they act on the column's object × — for a :selection action — the ticked rows, not a single row), or nil. -
#column_param_name ⇒ Object
The checkbox param name the picker submits (respects param_prefix).
-
#column_picker? ⇒ Boolean
Whether to offer the column picker UI for this collection.
-
#column_selection_actions? ⇒ Boolean
A visible column may host an
on: :selectionaction in its header (acting on the ticked rows × that column's object). - #columns_count ⇒ Object
- #current_page ⇒ Object
- #custom_actions_partial ⇒ Object
-
#custom_header?(field) ⇒ Boolean
Whether
fieldbrings its own header markup or header actions. - #filter_fields ⇒ Object
- #filter_form_id ⇒ Object
-
#filterable? ⇒ Boolean
── filtering ────────────────────────────────────────────────────────.
-
#filterable_field?(field) ⇒ Boolean
Match by name, not object identity: a prebuilt Query carries its own DynamicField instances (from its extra_fields), while the collection built its own from extra_columns.
- #filtered? ⇒ Boolean
-
#group_open?(group) ⇒ Boolean
Default: every group open below the collapse threshold, only the first above it.
-
#group_toggle_url(group) ⇒ Object
Toggle this group in
?open=, materializing the current open set so the first click on a default view keeps the others as they are. - #grouped? ⇒ Boolean
-
#groups ⇒ Object
The records split into groups, in group order (the relation is ordered by the group key first, so consecutive records form each group).
-
#initialize(view:, records:, fieldset: nil, query: :auto, layout: :table, param_prefix: nil, actions: true, search_bar: true, group_by: nil, extra_columns: nil, picker: false, picked_columns: :auto) ⇒ Collection
constructor
A new instance of Collection.
- #label_link_field?(field) ⇒ Boolean
- #label_link_present?(record) ⇒ Boolean
-
#own_param_keys ⇒ Object
Every param key this collection owns (for reset).
-
#page_scope ⇒ Object
The underlying (possibly paginated) relation, for custom layouts that would rather drive their own pager — e.g.
-
#page_url(n) ⇒ Object
A URL for page n that keeps this collection's filters/search/sort and every other collection's params (only our own
pagechanges) — so the pager composes with everything and respectsparam_prefix:. -
#pager_pages(window: 2) ⇒ Object
Page numbers to show, with :gap markers for elided ranges: [1, :gap, 4, 5, 6, :gap, 10].
-
#paginated? ⇒ Boolean
── pagination ───────────────────────────────────────────────────────── We render a footer pager only when the relation handed to us is already paginated — i.e.
-
#picker_preserved_params ⇒ Object
Hidden inputs for the picker's GET form: keep every other param (filters, search, sort, other collections) but drop our own cols (the checkboxes resubmit it) and page (a column change resets paging).
-
#preserved_params ⇒ Object
Hidden inputs for the filter form: keep this collection's sort and every param that belongs to someone else (other prefixes, the page's own params).
- #record_link(record) ⇒ Object
- #records ⇒ Object
-
#reset_url ⇒ Object
Reset clears this collection's filter/search/sort/page params and keeps everyone else's (other prefixes, the page's own params).
- #row_actions(record) ⇒ Object
- #search_param_name ⇒ Object
- #search_value ⇒ Object
-
#searchable? ⇒ Boolean
── header search (?q=) and reset ──────────────────────────────────────.
- #select_form_id ⇒ Object
-
#select_param_name ⇒ Object
The checkbox param name (respects param_prefix) — value is each row's identify_by, resolved back with CrudComponents.selected.
- #select_value(record) ⇒ Object
- #selectable? ⇒ Boolean
-
#selection_actions ⇒ Object
── selection (bulk actions) ────────────────────────────────────────── Selection actions (
action :x, on: :selection) operate on the rows the user ticks. -
#show_pager? ⇒ Boolean
Whether to draw the footer at all — a single page needs no pager.
-
#show_toolbar? ⇒ Boolean
Whether the toolbar (search + collection actions) has anything to show — lets a layout skip an empty header row.
-
#sort_active?(field) ⇒ Boolean
Is this the column the result is currently sorted by?.
-
#sort_direction(field) ⇒ Object
The active sort direction for a column — :asc / :desc, or nil when the result isn't sorted by it.
-
#sort_numeric?(field) ⇒ Boolean
Whether this column sorts numerically (vs alphabetically) — numbers and dates do — so a layout can pick a sort-numeric vs sort-alpha glyph.
- #sort_url(field) ⇒ Object
-
#sortable_field?(field) ⇒ Boolean
── sorting ──────────────────────────────────────────────────────────.
- #static? ⇒ Boolean
- #surface ⇒ Object
- #total_count ⇒ Object
- #total_pages ⇒ Object
-
#trailing_column? ⇒ Boolean
The trailing column exists when something needs to live in it: row actions (in the body cells), the column picker (its gear in the header cell), or the inline filter row (its submit/reset button sits in this column).
Methods included from ColumnSelection
#column_visible?, #field_groups, #fields, #group_heading, #group_icon, #visible_columns
Methods inherited from Base
#ability, #config, #css, #permission_context, #render_cell, #render_filter_control
Constructor Details
#initialize(view:, records:, fieldset: nil, query: :auto, layout: :table, param_prefix: nil, actions: true, search_bar: true, group_by: nil, extra_columns: nil, picker: false, picked_columns: :auto) ⇒ Collection
Returns a new instance of Collection.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/crud_components/presenters/collection.rb', line 17 def initialize(view:, records:, fieldset: nil, query: :auto, layout: :table, param_prefix: nil, actions: true, search_bar: true, group_by: nil, extra_columns: nil, picker: false, picked_columns: :auto) super(view: view) unless records.respond_to?(:klass) raise ArgumentError, "crud_collection expects an ActiveRecord relation (e.g. Book.all, @books, or an " \ "authorized scope like Book.accessible_by(current_ability)), got #{records.class}. " \ 'Pass a scope so your authorization and filtering apply before the gem renders.' end relation = records @model = relation.klass @structure = Structure.for(@model) @owner = relation.respond_to?(:proxy_association) ? relation.proxy_association.owner : nil @layout = layout @param_prefix = param_prefix @actions_enabled = actions @search_bar_enabled = # Two orthogonal column-picker knobs (see ColumnSelection): the gear is on # iff `picker`; the selection comes from the param (`:auto`) or verbatim # from the resolved Array — they never both read the param. @picker = picker @picked_columns = normalize_picked_columns(picked_columns) # User-defined columns whose data lives outside the model's table. Built # fresh per request (never on the immutable Structure), so they may carry # the per-page value cache. @dynamic_fields = Array(extra_columns).map { |c| c.to_field(@model) } case query when :static @static = true @fieldset = @structure.fieldset(fieldset || :index) when :auto, nil @fieldset = @structure.fieldset(fieldset || :index) @query = Query.new(@model, view.request.query_parameters, fieldset: @fieldset, ability: ability, param_prefix: param_prefix, extra_fields: @dynamic_fields) relation = @query.apply(relation) when Query @query = query @fieldset = fieldset ? @structure.fieldset(fieldset) : query.fieldset @param_prefix = query.param_prefix else raise ArgumentError, "crud_collection query: expects :auto, :static or a CrudComponents::Query, got #{query.inspect}" end @relation = eager_load(relation) setup_grouping(group_by) if group_by end |
Instance Attribute Details
#fieldset ⇒ Object (readonly)
Returns the value of attribute fieldset.
15 16 17 |
# File 'lib/crud_components/presenters/collection.rb', line 15 def fieldset @fieldset end |
#layout ⇒ Object (readonly)
Returns the value of attribute layout.
15 16 17 |
# File 'lib/crud_components/presenters/collection.rb', line 15 def layout @layout end |
#model ⇒ Object (readonly)
Returns the value of attribute model.
15 16 17 |
# File 'lib/crud_components/presenters/collection.rb', line 15 def model @model end |
#owner ⇒ Object (readonly)
Returns the value of attribute owner.
15 16 17 |
# File 'lib/crud_components/presenters/collection.rb', line 15 def owner @owner end |
#param_prefix ⇒ Object (readonly)
Returns the value of attribute param_prefix.
15 16 17 |
# File 'lib/crud_components/presenters/collection.rb', line 15 def param_prefix @param_prefix end |
#query ⇒ Object (readonly)
Returns the value of attribute query.
15 16 17 |
# File 'lib/crud_components/presenters/collection.rb', line 15 def query @query end |
#structure ⇒ Object (readonly)
Returns the value of attribute structure.
15 16 17 |
# File 'lib/crud_components/presenters/collection.rb', line 15 def structure @structure end |
Instance Method Details
#actions_column? ⇒ Boolean
── actions ──────────────────────────────────────────────────────────
360 361 362 |
# File 'lib/crud_components/presenters/collection.rb', line 360 def actions_column? @actions_enabled && (custom_actions_partial.present? || row_action_definitions.any?) end |
#available_fields ⇒ Object
Every column this user is allowed to see — declared fieldset fields plus
the dynamic columns — regardless of the current visibility selection.
This is what a column picker offers as the universe to choose from.
(fields, column_visible? and the picker knobs come from ColumnSelection.)
84 85 86 87 |
# File 'lib/crud_components/presenters/collection.rb', line 84 def available_fields @available_fields ||= (structure.fieldset_fields(fieldset) + @dynamic_fields).select { |f| f.permitted?() } end |
#cell(field, record) ⇒ Object
── cells ────────────────────────────────────────────────────────────
104 105 106 107 108 109 110 111 |
# File 'lib/crud_components/presenters/collection.rb', line 104 def cell(field, record) html = render_cell(field, record, surface: :collection, cell_context: cell_context) if label_link_field?(field) && (path = record_link(record)) view.link_to(html, path, class: css.record_link, data: { turbo_action: 'advance' }) else html end end |
#cell_context ⇒ Object
Click-to-filter context for value renderers — only when this collection actually has a live query.
115 116 117 118 119 |
# File 'lib/crud_components/presenters/collection.rb', line 115 def cell_context return nil if static? || query.nil? @cell_context ||= CellContext.new(view: view, query: query) end |
#collection_actions ⇒ Object
384 385 386 387 388 389 390 |
# File 'lib/crud_components/presenters/collection.rb', line 384 def collection_actions return nil unless @actions_enabled @collection_actions ||= Actions.new(view: view, subject: model, structure: structure, actions: structure.fieldset_actions(fieldset, on: :collection), owner: owner) end |
#column_header(field) ⇒ Object
The <th> title for field: a custom header: (a String — html_safe to
carry markup — or a view-context block, e.g. a link) replaces the plain
human_name; otherwise the human_name itself. header: substitutes only
the name — the layout still wraps this in a sort link when the column is
sortable, and appends any header actions.
142 143 144 145 146 147 148 149 |
# File 'lib/crud_components/presenters/collection.rb', line 142 def column_header(field) header = field.header case header when nil then field.human_name when Proc then view.instance_exec(&header) else header end end |
#column_header_actions(field) ⇒ Object
The header actions for field as an Actions presenter (collection-kind:
they act on the column's object × — for a :selection action — the ticked
rows, not a single row), or nil. Each action's path block closes over that
object; the layout renders a :selection action as a select-form submitter
and any other as a link/button.
156 157 158 159 160 161 162 |
# File 'lib/crud_components/presenters/collection.rb', line 156 def column_header_actions(field) return nil unless field.header_actions.any? (@column_header_actions ||= {})[field] ||= Actions.new(view: view, subject: model, structure: structure, actions: field.header_actions, owner: owner) end |
#column_param_name ⇒ Object
The checkbox param name the picker submits (respects param_prefix).
93 |
# File 'lib/crud_components/presenters/collection.rb', line 93 def column_param_name = "#{pn('cols')}[]" |
#column_picker? ⇒ Boolean
Whether to offer the column picker UI for this collection.
90 |
# File 'lib/crud_components/presenters/collection.rb', line 90 def column_picker? = @picker && available_fields.any? |
#column_selection_actions? ⇒ Boolean
A visible column may host an on: :selection action in its header (acting
on the ticked rows × that column's object). Like a toolbar selection
action, it submits the shared select-form — so it needs the checkbox
column + select-form and thus makes the collection selectable.
415 416 417 418 419 |
# File 'lib/crud_components/presenters/collection.rb', line 415 def column_selection_actions? fields.any? do |field| column_header_actions(field)&.items&.any? { |item| item.action.selection? } end end |
#columns_count ⇒ Object
432 433 434 |
# File 'lib/crud_components/presenters/collection.rb', line 432 def columns_count fields.size + (selectable? ? 1 : 0) + (trailing_column? ? 1 : 0) end |
#current_page ⇒ Object
329 |
# File 'lib/crud_components/presenters/collection.rb', line 329 def current_page = @relation.current_page |
#custom_actions_partial ⇒ Object
374 375 376 |
# File 'lib/crud_components/presenters/collection.rb', line 374 def custom_actions_partial fieldset.custom_actions_partial end |
#custom_header?(field) ⇒ Boolean
Whether field brings its own header markup or header actions.
133 134 135 |
# File 'lib/crud_components/presenters/collection.rb', line 133 def custom_header?(field) field.custom_header? end |
#filter_fields ⇒ Object
181 182 183 |
# File 'lib/crud_components/presenters/collection.rb', line 181 def filter_fields @filter_fields ||= static? ? [] : query.filter_fields end |
#filter_form_id ⇒ Object
194 195 196 197 |
# File 'lib/crud_components/presenters/collection.rb', line 194 def filter_form_id suffix = param_prefix ? "_#{param_prefix}" : '' "crud_filter_#{model.model_name.plural}#{suffix}" end |
#filterable? ⇒ Boolean
── filtering ────────────────────────────────────────────────────────
177 178 179 |
# File 'lib/crud_components/presenters/collection.rb', line 177 def filterable? !static? && query && filter_fields.any? end |
#filterable_field?(field) ⇒ Boolean
Match by name, not object identity: a prebuilt Query carries its own
DynamicField instances (from its extra_fields), while the collection built
its own from extra_columns. Same column, different objects — include?
would miss them and silently drop the inline filter/sort (issue #21).
Declared fields are memoized on the Structure, so they share a name too.
190 191 192 |
# File 'lib/crud_components/presenters/collection.rb', line 190 def filterable_field?(field) filter_fields.any? { |f| f.name == field.name } end |
#filtered? ⇒ Boolean
212 213 214 |
# File 'lib/crud_components/presenters/collection.rb', line 212 def filtered? !static? && query&.active? end |
#group_open?(group) ⇒ Boolean
Default: every group open below the collapse threshold, only the first
above it. Once ?open= is set it is authoritative (and may open several).
298 299 300 301 302 303 304 |
# File 'lib/crud_components/presenters/collection.rb', line 298 def group_open?(group) if open_keys.nil? records.size < config.group_collapse_threshold || group == groups.first else open_keys.include?(group.key) end end |
#group_toggle_url(group) ⇒ Object
Toggle this group in ?open=, materializing the current open set so the
first click on a default view keeps the others as they are.
308 309 310 311 312 313 |
# File 'lib/crud_components/presenters/collection.rb', line 308 def group_toggle_url(group) current = groups.select { |g| group_open?(g) }.map(&:key) toggled = current.include?(group.key) ? current - [group.key] : current + [group.key] params = view.request.query_parameters.merge(pn('open') => toggled.join(',')) "#{view.request.path}?#{params.to_query}" end |
#grouped? ⇒ Boolean
286 |
# File 'lib/crud_components/presenters/collection.rb', line 286 def grouped? = !@group_by.nil? |
#groups ⇒ Object
The records split into groups, in group order (the relation is ordered by the group key first, so consecutive records form each group).
290 291 292 293 294 |
# File 'lib/crud_components/presenters/collection.rb', line 290 def groups @groups ||= records.group_by { |r| group_key_for(r) }.map do |key, recs| Group.new(key: key, label: group_label_for(recs.first), records: recs) end end |
#label_link_field?(field) ⇒ Boolean
121 122 123 |
# File 'lib/crud_components/presenters/collection.rb', line 121 def label_link_field?(field) field.name == structure.label_field_name end |
#label_link_present?(record) ⇒ Boolean
172 173 174 |
# File 'lib/crud_components/presenters/collection.rb', line 172 def label_link_present?(record) fields.any? { |f| label_link_field?(f) } && record_link(record).present? end |
#own_param_keys ⇒ Object
Every param key this collection owns (for reset).
240 241 242 243 |
# File 'lib/crud_components/presenters/collection.rb', line 240 def own_param_keys keys = filter_fields.flat_map { |f| [pn(f.name.to_s), pn("#{f.name}_geq"), pn("#{f.name}_leq")] } keys + %w[q sort dir page per].map { |k| pn(k) } end |
#page_scope ⇒ Object
The underlying (possibly paginated) relation, for custom layouts that
would rather drive their own pager — e.g. hand it to kaminari's
paginate helper instead of rendering the gem's _pager.
336 |
# File 'lib/crud_components/presenters/collection.rb', line 336 def page_scope = @relation |
#page_url(n) ⇒ Object
A URL for page n that keeps this collection's filters/search/sort and
every other collection's params (only our own page changes) — so the
pager composes with everything and respects param_prefix:.
341 342 343 344 |
# File 'lib/crud_components/presenters/collection.rb', line 341 def page_url(n) params = view.request.query_parameters.merge(pn('page') => n) "#{view.request.path}?#{params.to_query}" end |
#pager_pages(window: 2) ⇒ Object
Page numbers to show, with :gap markers for elided ranges: [1, :gap, 4, 5, 6, :gap, 10]. Always includes first/last and a window around the current page.
349 350 351 352 353 354 355 356 357 |
# File 'lib/crud_components/presenters/collection.rb', line 349 def pager_pages(window: 2) return [] if total_pages <= 1 shown = ([1, total_pages] + ((current_page - window)..(current_page + window)).to_a) .select { |p| p >= 1 && p <= total_pages }.uniq.sort shown.each_with_index.flat_map do |p, i| (i.positive? && p - shown[i - 1] > 1) ? [:gap, p] : [p] end end |
#paginated? ⇒ Boolean
── pagination ─────────────────────────────────────────────────────────
We render a footer pager only when the relation handed to us is already
paginated — i.e. the host called .page (kaminari / will_paginate, which
decorate the relation). The gem never paginates on its own: no records
arrive limited unless you asked for it. pagy keeps its state in a
separate object, not on the relation, so it can't be detected here —
render pagy_nav yourself.
322 323 324 |
# File 'lib/crud_components/presenters/collection.rb', line 322 def paginated? @relation.respond_to?(:current_page) && @relation.respond_to?(:total_pages) end |
#picker_preserved_params ⇒ Object
Hidden inputs for the picker's GET form: keep every other param (filters, search, sort, other collections) but drop our own cols (the checkboxes resubmit it) and page (a column change resets paging).
98 99 100 101 |
# File 'lib/crud_components/presenters/collection.rb', line 98 def picker_preserved_params drop = [pn('cols'), pn('page')] view.request.query_parameters.reject { |key, _| drop.include?(key) } end |
#preserved_params ⇒ Object
Hidden inputs for the filter form: keep this collection's sort and every param that belongs to someone else (other prefixes, the page's own params). Drop our own filter/search params — the controls themselves resubmit those.
233 234 235 236 237 |
# File 'lib/crud_components/presenters/collection.rb', line 233 def preserved_params own = filter_fields.flat_map { |f| [pn(f.name.to_s), pn("#{f.name}_geq"), pn("#{f.name}_leq")] } own += [pn('q'), pn('page'), pn('per')] view.request.query_parameters.reject { |key, _| own.include?(key) } end |
#record_link(record) ⇒ Object
164 165 166 167 168 169 170 |
# File 'lib/crud_components/presenters/collection.rb', line 164 def record_link(record) @record_links ||= {} return @record_links[record.id] if @record_links.key?(record.id) found = RouteResolver.record_path(view, record, owner: owner) @record_links[record.id] = found&.first end |
#records ⇒ Object
70 71 72 73 74 75 76 77 78 |
# File 'lib/crud_components/presenters/collection.rb', line 70 def records @records ||= begin rows = @relation.to_a # Prime each visible dynamic column's per-page cache once (no N+1); the # cell resolver then reads per row from what `preload:` returned. fields.each { |f| f.preload!(rows) if f.is_a?(Fields::DynamicField) } rows end end |
#reset_url ⇒ Object
Reset clears this collection's filter/search/sort/page params and keeps everyone else's (other prefixes, the page's own params).
224 225 226 227 |
# File 'lib/crud_components/presenters/collection.rb', line 224 def reset_url kept = view.request.query_parameters.reject { |key, _| own_param_keys.include?(key) } kept.any? ? "#{view.request.path}?#{kept.to_query}" : view.request.path end |
#row_actions(record) ⇒ Object
378 379 380 381 382 |
# File 'lib/crud_components/presenters/collection.rb', line 378 def row_actions(record) Actions.new(view: view, subject: record, structure: structure, actions: row_action_definitions, owner: owner, suppress_show: label_link_present?(record)) end |
#search_param_name ⇒ Object
204 205 206 |
# File 'lib/crud_components/presenters/collection.rb', line 204 def search_param_name query.param_name('q') end |
#search_value ⇒ Object
208 209 210 |
# File 'lib/crud_components/presenters/collection.rb', line 208 def search_value query&.value('q') end |
#searchable? ⇒ Boolean
── header search (?q=) and reset ──────────────────────────────────────
200 201 202 |
# File 'lib/crud_components/presenters/collection.rb', line 200 def searchable? @search_bar_enabled && !static? && query && query.searchable? end |
#select_form_id ⇒ Object
421 422 423 424 |
# File 'lib/crud_components/presenters/collection.rb', line 421 def select_form_id suffix = param_prefix ? "_#{param_prefix}" : '' "crud_select_#{model.model_name.plural}#{suffix}" end |
#select_param_name ⇒ Object
The checkbox param name (respects param_prefix) — value is each row's identify_by, resolved back with CrudComponents.selected.
428 |
# File 'lib/crud_components/presenters/collection.rb', line 428 def select_param_name = "#{pn('selected')}[]" |
#select_value(record) ⇒ Object
430 |
# File 'lib/crud_components/presenters/collection.rb', line 430 def select_value(record) = record.public_send(structure.identify_by).to_s |
#selectable? ⇒ Boolean
405 406 407 408 409 |
# File 'lib/crud_components/presenters/collection.rb', line 405 def selectable? return @selectable if defined?(@selectable) @selectable = @actions_enabled && (selection_actions.any? || column_selection_actions?) end |
#selection_actions ⇒ Object
── selection (bulk actions) ──────────────────────────────────────────
Selection actions (action :x, on: :selection) operate on the rows the
user ticks. Rendered as submit buttons that post the checked
selected[] slugs to the action path — no-JS works; the optional
crud-select controller adds select-all / select-group / a live count.
397 398 399 400 401 402 403 |
# File 'lib/crud_components/presenters/collection.rb', line 397 def selection_actions return nil unless @actions_enabled @selection_actions ||= Actions.new(view: view, subject: model, structure: structure, actions: structure.fieldset_actions(fieldset, on: :selection), owner: owner) end |
#show_pager? ⇒ Boolean
Whether to draw the footer at all — a single page needs no pager.
327 |
# File 'lib/crud_components/presenters/collection.rb', line 327 def show_pager? = paginated? && total_pages > 1 |
#show_toolbar? ⇒ Boolean
Whether the toolbar (search + collection actions) has anything to show — lets a layout skip an empty header row.
218 219 220 |
# File 'lib/crud_components/presenters/collection.rb', line 218 def searchable? || collection_actions&.any? || selection_actions&.any? end |
#sort_active?(field) ⇒ Boolean
Is this the column the result is currently sorted by?
258 259 260 |
# File 'lib/crud_components/presenters/collection.rb', line 258 def sort_active?(field) !sort_direction(field).nil? end |
#sort_direction(field) ⇒ Object
The active sort direction for a column — :asc / :desc, or nil when the
result isn't sorted by it. The presenter holds no icon names: a layout
turns this tri-state into whatever glyph it likes (see _table), pairing
it with sort_numeric? to choose a numeric vs alphabetic icon.
266 267 268 269 270 271 |
# File 'lib/crud_components/presenters/collection.rb', line 266 def sort_direction(field) current, dir = query&.sort_state return nil unless current == field.name.to_s dir.to_s == 'desc' ? :desc : :asc end |
#sort_numeric?(field) ⇒ Boolean
Whether this column sorts numerically (vs alphabetically) — numbers and dates do — so a layout can pick a sort-numeric vs sort-alpha glyph.
275 276 277 |
# File 'lib/crud_components/presenters/collection.rb', line 275 def sort_numeric?(field) field.is_a?(Fields::NumericField) || field.is_a?(Fields::DateField) end |
#sort_url(field) ⇒ Object
250 251 252 253 254 255 |
# File 'lib/crud_components/presenters/collection.rb', line 250 def sort_url(field) current, dir = query.sort_state next_dir = current == field.name.to_s && dir == 'asc' ? 'desc' : 'asc' params = view.request.query_parameters.merge(pn('sort') => field.name.to_s, pn('dir') => next_dir) "#{view.request.path}?#{params.to_query}" end |
#sortable_field?(field) ⇒ Boolean
── sorting ──────────────────────────────────────────────────────────
246 247 248 |
# File 'lib/crud_components/presenters/collection.rb', line 246 def sortable_field?(field) !static? && query && query.sortable_fields.any? { |f| f.name == field.name } end |
#static? ⇒ Boolean
67 |
# File 'lib/crud_components/presenters/collection.rb', line 67 def static? = !!@static |
#surface ⇒ Object
68 |
# File 'lib/crud_components/presenters/collection.rb', line 68 def surface = :collection |
#total_count ⇒ Object
331 |
# File 'lib/crud_components/presenters/collection.rb', line 331 def total_count = @relation.total_count |
#total_pages ⇒ Object
330 |
# File 'lib/crud_components/presenters/collection.rb', line 330 def total_pages = @relation.total_pages |
#trailing_column? ⇒ Boolean
The trailing column exists when something needs to live in it: row actions (in the body cells), the column picker (its gear in the header cell), or the inline filter row (its submit/reset button sits in this column). Without it a filterable table would render filter inputs with no button to apply them. Keeping it here also keeps the header, rows and width all in agreement.
370 371 372 |
# File 'lib/crud_components/presenters/collection.rb', line 370 def trailing_column? actions_column? || column_picker? || filterable? end |