Module: CrudComponents
- Defined in:
- lib/crud_components.rb,
lib/crud_components.rb,
lib/crud_components/model.rb,
lib/crud_components/query.rb,
lib/crud_components/action.rb,
lib/crud_components/config.rb,
lib/crud_components/engine.rb,
lib/crud_components/errors.rb,
lib/crud_components/markup.rb,
lib/crud_components/builder.rb,
lib/crud_components/helpers.rb,
lib/crud_components/version.rb,
lib/crud_components/fieldset.rb,
lib/crud_components/like_spec.rb,
lib/crud_components/structure.rb,
lib/crud_components/where_like.rb,
lib/crud_components/fields/base.rb,
lib/crud_components/dynamic_column.rb,
lib/crud_components/route_resolver.rb,
lib/crud_components/presenters/base.rb,
lib/crud_components/presenters/form.rb,
lib/crud_components/presenters/cells.rb,
lib/crud_components/fields/date_field.rb,
lib/crud_components/fields/enum_field.rb,
lib/crud_components/fields/json_field.rb,
lib/crud_components/fields/path_field.rb,
lib/crud_components/fields/text_field.rb,
lib/crud_components/presenters/filter.rb,
lib/crud_components/presenters/record.rb,
lib/crud_components/permission_context.rb,
lib/crud_components/presenters/actions.rb,
lib/crud_components/fields/string_field.rb,
lib/crud_components/fields/boolean_field.rb,
lib/crud_components/fields/dynamic_field.rb,
lib/crud_components/fields/numeric_field.rb,
lib/crud_components/fields/computed_field.rb,
lib/crud_components/fields/has_many_field.rb,
lib/crud_components/presenters/collection.rb,
lib/crud_components/fields/attachment_field.rb,
lib/crud_components/fields/belongs_to_field.rb,
lib/crud_components/presenters/cell_context.rb,
lib/crud_components/presenters/column_selection.rb,
lib/generators/crud_components/views/views_generator.rb,
lib/generators/crud_components/install/install_generator.rb
Defined Under Namespace
Modules: Fields, Generators, Helpers, LikeSpec, Markup, Model, Permission, Presenters, RouteResolver, WhereLike Classes: Action, Builder, Config, DefinitionError, DynamicColumn, Engine, Error, Fieldset, PermissionContext, Query, Structure, UnknownFieldsetError
Constant Summary collapse
- RESERVED_PARAMS =
The query params the gem owns (filters are top-level params named after the field, so a field can’t share these names). Declaring such an attribute raises in the Builder rather than silently colliding with sort/pagination.
%w[q sort dir page per cols].freeze
- NULL_FILTER_VALUE =
Sentinel filter value meaning “the column is NULL” (boolean/enum filters on nullable columns offer it as a “not set” choice). Improbable as a real value, so it never collides with a genuine enum key or boolean string.
'__null__'.freeze
- VERSION =
'0.1.0'.freeze
Class Method Summary collapse
-
.bundled_css ⇒ Object
The gem’s stylesheet (the column-picker float styles), read once from the packaged file.
- .config ⇒ Object
- .configure {|config| ... } ⇒ Object
-
.permitted_attributes(model, action: :update, ability: nil) ⇒ Object
The strong-params permit list for a model’s derived form — the same field metadata the form renders from, so the two can’t drift.
-
.previews_available? ⇒ Boolean
private
Whether non-image attachment previews (e.g. a PDF’s first page) can actually be generated here.
-
.selected(scope, params, param: :selected) ⇒ Object
Resolve a bulk-action selection from request params into a relation.
-
.selected_columns(params, param_prefix: nil) {|names| ... } ⇒ Object
The column-picker selection from a request’s params: the ordered list of column names the user ticked, or nil when the picker wasn’t submitted.
- .structure_for(model) ⇒ Object
-
.where_like(relation, spec, value) ⇒ Object
Safe case-insensitive contains-match on any relation, using the same escaped-ILIKE machinery as ‘filter like:` / `search_in` — so you never hand-write `where(“col LIKE ?”, “%#value%”)` (which forgets to escape the user’s ‘%`/`_`).
Class Method Details
.bundled_css ⇒ Object
The gem’s stylesheet (the column-picker float styles), read once from the packaged file. Backs the ‘crud_components_styles` helper, which inlines it; the same file is also linkable via `stylesheet_link_tag “crud_components”` on hosts whose asset pipeline serves engine assets.
154 155 156 |
# File 'lib/crud_components.rb', line 154 def bundled_css @bundled_css ||= File.read(File.('../app/assets/stylesheets/crud_components.css', __dir__)) end |
.config ⇒ Object
52 53 54 |
# File 'lib/crud_components.rb', line 52 def config @config ||= Config.new end |
.configure {|config| ... } ⇒ Object
56 57 58 |
# File 'lib/crud_components.rb', line 56 def configure yield config end |
.permitted_attributes(model, action: :update, ability: nil) ⇒ Object
The strong-params permit list for a model’s derived form — the same field metadata the form renders from, so the two can’t drift. Use in a controller:
params.require(:book)
.permit(*CrudComponents.permitted_attributes(Book, action: :update,
ability: current_ability))
131 132 133 |
# File 'lib/crud_components.rb', line 131 def permitted_attributes(model, action: :update, ability: nil) Structure.for(model).permitted_params(action, PermissionContext.new(ability)) end |
.previews_available? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Whether non-image attachment previews (e.g. a PDF’s first page) can actually be generated here. Beyond a previewer binary (poppler/ffmpeg, which ‘previewable?` already checks), processing needs `image_processing` plus the configured variant backend’s gem (ruby-vips or mini_magick). When any is missing, the renderer shows an icon + filename rather than a preview that would 500 at processing time.
112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/crud_components.rb', line 112 def previews_available? return @previews_available if defined?(@previews_available) @previews_available = begin require 'image_processing' processor = defined?(ActiveStorage) ? ActiveStorage.variant_processor : :vips require(processor.to_s == 'mini_magick' ? 'mini_magick' : 'vips') true rescue LoadError false end end |
.selected(scope, params, param: :selected) ⇒ Object
Resolve a bulk-action selection from request params into a relation. The row checkboxes submit ‘selected[]=<identify_by>` (a slug array; a comma string is also accepted).
Pass the same authorized scope you’d render — selection narrows within it, so a tampered slug can never reach a row outside it:
CrudComponents.selected(@books, params).destroy_all # @books already scoped
A model class also works when you don’t scope (acts on the whole table):
CrudComponents.selected(Book, params)
144 145 146 147 148 |
# File 'lib/crud_components.rb', line 144 def selected(scope, params, param: :selected) model = scope.respond_to?(:klass) ? scope.klass : scope values = Array(params[param]).flat_map { |v| v.to_s.split(',') }.map(&:strip).reject(&:blank?) scope.where(Structure.for(model).identify_by => values) end |
.selected_columns(params, param_prefix: nil) {|names| ... } ⇒ Object
The column-picker selection from a request’s params: the ordered list of column names the user ticked, or nil when the picker wasn’t submitted. Honors ‘param_prefix:` (match it to the picker’s). Persist it however you like, then feed it back via ‘picked_columns:`.
cols = CrudComponents.selected_columns(params)
current_user.update!(book_columns: cols) if cols
A block runs only when a selection was submitted, and receives the list:
CrudComponents.selected_columns(params) { |cols| current_user.update!(book_columns: cols) }
Accepts both the no-JS ‘cols[]=a&cols=b` array and the comma-joined `cols=a,b` the crud-columns controller submits.
95 96 97 98 99 100 101 102 103 |
# File 'lib/crud_components.rb', line 95 def selected_columns(params, param_prefix: nil) key = param_prefix ? "#{param_prefix}_cols" : 'cols' raw = params[key] || params[key.to_sym] list = raw.is_a?(Array) ? raw : raw.is_a?(String) ? raw.split(',') : nil names = list&.map { |n| n.to_s.strip }&.reject(&:blank?) names = nil if names.nil? || names.empty? yield names if block_given? && names names end |
.structure_for(model) ⇒ Object
60 61 62 |
# File 'lib/crud_components.rb', line 60 def structure_for(model) Structure.for(model) end |
.where_like(relation, spec, value) ⇒ Object
Safe case-insensitive contains-match on any relation, using the same escaped-ILIKE machinery as ‘filter like:` / `search_in` — so you never hand-write `where(“col LIKE ?”, “%#value%”)` (which forgets to escape the user’s ‘%`/`_`). The scope handed to a filter/search block already carries `#where_like`; this module function is for the relations you build yourself, e.g. a subquery on another model:
filter: ->(scope, value) {
ids = CrudComponents.where_like(PropertyValue.where(definition: prop), :value, value)
scope.where(id: ids.select(:subject_id))
}
‘spec` is a LikeSpec spec (`:value`, `%i[a b]`, `{ assoc: :col }`).
77 78 79 |
# File 'lib/crud_components.rb', line 77 def where_like(relation, spec, value) LikeSpec.apply(relation, spec, value) end |