Module: CmAdmin::Models::DslMethod
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/cm_admin/models/dsl_method.rb
Instance Method Summary collapse
- 
  
    
      #action_group(name, icon_name: 'fa fa-list', icon_style: nil)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Create a new group for actions. 
- 
  
    
      #alert_box(header: nil, body: nil, type: nil, icon_name: nil, partial: nil, display_if: ->(_arg) { true }, html_attrs: {})  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Adds a new alert to the current section. 
- 
  
    
      #all_db_columns(options = {})  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Get all columns for a model for index layout. 
- 
  
    
      #bulk_action(name: nil, display_name: nil, display_if: ->(_) { true }, redirection_url: nil, icon_name: nil, verb: nil, display_type: nil, modal_configuration: {}, route_type: nil, partial: nil, icon_style: nil, execution_mode: :individual, success_message: ->(_arg) { nil }, error_message: ->(_arg) { nil }, &block)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Create a new bulk action for model. 
- 
  
    
      #cm_edit(page_title: nil, page_description: nil, partial: nil, redirect_to: nil)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Create a form for edit action. 
- 
  
    
      #cm_index(page_title: nil, page_description: nil, partial: nil, view_type: :table)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Create a table for index page with pagination. 
- 
  
    
      #cm_new(page_title: nil, page_description: nil, partial: nil, redirect_to: nil)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Create a form for new action. 
- #cm_section(section_name, display_if: nil, col_size: nil, html_attrs: nil, partial: nil, &block) ⇒ Object
- 
  
    
      #cm_show(page_title: nil, page_description: nil, partial: nil)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Create a view for show page. 
- 
  
    
      #cm_show_section(section_name, display_if: nil, html_attrs: nil, partial: nil, &block)  ⇒ Object 
    
    
  
  
  
  
  
  
  deprecated
  
  
    Deprecated. Use #cm_section instead of this method 
- 
  
    
      #column(field_name, options = {})  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Create a new column on index layout. 
- 
  
    
      #custom_action(name: nil, page_title: nil, page_description: nil, display_name: nil, verb: nil, layout: nil, layout_type: nil, partial: nil, path: nil, display_type: nil, redirect_to: nil, modal_configuration: {}, url_params: {}, display_if: ->(_) { true }, route_type: nil, icon_name: 'fa fa-th-large', icon_style: nil, group_name: nil, success_message: ->(_) { nil }, error_message: ->(_, _) { nil }, &block)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Create a new custom action for model custom_action name: ‘change_password’, route_type: ‘member’, verb: ‘get’, icon_name: ‘fa-solid fa-key’, page_title: ‘Change Password’, path: ‘:id/change_password’, display_type: :form_modal do form do cm_section ‘Password Details’ do form_field :username form_field :age_group_id, input_type: :single_select, helper_method: :age_group_type_collection form_field :cultural_background_ids, input_type: :multi_select, helper_method: :cultural_background_type_collection form_field :language, input_type: :single_select, helper_method: :language_collection end end on_submit do @customer = ::Customer.find(params) @customer.update!(gender_id: params[:age_group_id]) @customer end end Note: The form block is mandatory for form modal and form page. 
- 
  
    
      #eager_load_associations(associations = [])  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Configure Eager load associations for action This will help us avoid N+1 queries. 
- 
  
    
      #filter(db_column_name, filter_type = nil, options = {})  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Create a new filter for model. 
- 
  
    
      #kanban_view(column_name, exclude: [], only: [])  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Set kanban view for current action. 
- 
  
    
      #page_description(description)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Set page description for current action. 
- 
  
    
      #page_title(title)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Set page title for current action. 
- 
  
    
      #row(display_if: nil, html_attrs: nil, &block)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Create a new row on page or form. 
- 
  
    
      #scope_list(scopes = [])  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Set scopes for current action. 
- 
  
    
      #sort_column(column = :created_at)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    @deprecated: use #sortable_columns instead of this method Set sort column for filters. 
- 
  
    
      #sort_direction(direction = :desc)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    @deprecated: use #sortable_columns instead of this method Set sort direction for filters. 
- 
  
    
      #sortable_columns(columns)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Configure sortable columns for model verified_at is a JSONB column, so we need to specify the sort_datatype sortable_columns([‘id’, display_name: ‘ID’, default: true, default_direction: ‘desc’, ‘updated_at’, display_name: ‘Last Updated At’, ‘verified_at’, display_name: ‘Verified At’, sort_datatype: ‘TIMESTAMP’]). 
- 
  
    
      #tab(tab_name, action_name, associated_model: nil, layout_type: nil, layout: nil, partial: nil, display_if: nil, show_count: true, view_type: nil, associated_model_name: nil, allow_create_action: -> { true }, &block)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Create a new tab on show page. 
Instance Method Details
#action_group(name, icon_name: 'fa fa-list', icon_style: nil) ⇒ Object
Create a new group for actions
| 289 290 291 292 293 | # File 'lib/cm_admin/models/dsl_method.rb', line 289 def action_group(name, icon_name: 'fa fa-list', icon_style: nil) @current_group = { name:, icon_name:, icon_style: } yield @current_group = nil end | 
#alert_box(header: nil, body: nil, type: nil, icon_name: nil, partial: nil, display_if: ->(_arg) { true }, html_attrs: {}) ⇒ Object
Alerts cannot be placed inside nested sections. If added within a nested section, the alert will appear on the wrapped cm_show_section.
Only the specified types (info, success, danger, warning) are supported. Any other type will default to a standard div.
Adds a new alert to the current section.
| 517 518 519 | # File 'lib/cm_admin/models/dsl_method.rb', line 517 def alert_box(header: nil, body: nil, type: nil, icon_name: nil, partial: nil, display_if: ->(_arg) { true }, html_attrs: {}) @current_action.alerts << CmAdmin::Models::Alert.new(header:, body:, type:, icon_name:, partial:, display_if:, html_attrs:) end | 
#all_db_columns(options = {}) ⇒ Object
Get all columns for a model for index layout.
| 268 269 270 271 272 273 274 275 276 277 | # File 'lib/cm_admin/models/dsl_method.rb', line 268 def all_db_columns( = {}) field_names = instance_variable_get(:@ar_model)&.columns&.map { |x| x.name.to_sym } if .include?(:exclude) && field_names excluded_fields = ([] << [:exclude]).flatten.map(&:to_sym) field_names -= excluded_fields end field_names.each do |field_name| column field_name end end | 
#bulk_action(name: nil, display_name: nil, display_if: ->(_) { true }, redirection_url: nil, icon_name: nil, verb: nil, display_type: nil, modal_configuration: {}, route_type: nil, partial: nil, icon_style: nil, execution_mode: :individual, success_message: ->(_arg) { nil }, error_message: ->(_arg) { nil }, &block) ⇒ Object
Create a new bulk action for model
| 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 | # File 'lib/cm_admin/models/dsl_method.rb', line 418 def bulk_action(name: nil, display_name: nil, display_if: ->(_) { true }, redirection_url: nil, icon_name: nil, verb: nil, display_type: nil, modal_configuration: {}, route_type: nil, partial: nil, icon_style: nil, execution_mode: :individual, success_message: ->(_arg) { nil }, error_message: ->(_arg) { nil }, &block) bulk_action = CmAdmin::Models::BulkAction.new( name:, display_name:, display_if:, modal_configuration:, redirection_url:, icon_name:, action_type: :bulk_action, execution_mode:, verb:, display_type:, route_type:, partial:, icon_style:, success_message:, error_message:, &block ) if display_type == :form_modal @action = bulk_action @current_action = @action @current_action.verb = :post @available_actions << @action define_singleton_method(:on_submit) do |&code_block| @action.code_block = code_block end yield else @available_actions << bulk_action end end | 
#cm_edit(page_title: nil, page_description: nil, partial: nil, redirect_to: nil) ⇒ Object
Create a form for edit action
Create a form field for form
@param form_field [String] the name of field
@param input_type [Symbol] the type of field, +:integer+, +:decimal+, +:string+, +:single_select+, +:multi_select+, +:date+, +:date_time+, +:text+, +:switch+, +:custom_single_select+, +:checkbox_group+, +:radio_button+, +:custom_string+, +:custom_date+, +:radio_button_group+
@param is_required [Boolean] the field is required or not, or can be set automatically based on model validation
@param collection [Array] the collection of field, use with single_select or multi_select
For understanding difference between switch and check_box, refer to https://blog.uxtweak.com/checkbox-vs-toggle-switch/
| 71 72 73 74 75 76 | # File 'lib/cm_admin/models/dsl_method.rb', line 71 def cm_edit(page_title: nil, page_description: nil, partial: nil, redirect_to: nil) @current_action = CmAdmin::Models::Action.find_by(self, name: 'edit') page_title ||= "Edit #{ar_model.model_name.plural.titleize}" @current_action.set_values(page_title, page_description, partial, redirect_to) yield end | 
#cm_index(page_title: nil, page_description: nil, partial: nil, view_type: :table) ⇒ Object
Create a table for index page with pagination.

| 20 21 22 23 24 25 | # File 'lib/cm_admin/models/dsl_method.rb', line 20 def cm_index(page_title: nil, page_description: nil, partial: nil, view_type: :table) @current_action = CmAdmin::Models::Action.find_by(self, name: 'index') page_title ||= ar_model.model_name.plural.titleize @current_action.set_values(page_title, page_description, partial, view_type) yield end | 
#cm_new(page_title: nil, page_description: nil, partial: nil, redirect_to: nil) ⇒ Object
Create a form for new action
Create a form field for form
@param form_field [String] the name of field
@param input_type [Symbol] the type of field, +:integer+, +:decimal+, +:string+, +:single_select+, +:multi_select+, +:date+, +:date_time+, +:text+, +:switch+, +:custom_single_select+, +:checkbox_group+, +:radio_button+, +:custom_string+, +:custom_date+, +:radio_button_group+
@param is_required [Boolean] the field is required or not, or can be set automatically based on model validation
@param collection [Array] the collection of field, use with single_select or multi_select
For understanding difference between switch and check_box, refer to https://blog.uxtweak.com/checkbox-vs-toggle-switch/
| 98 99 100 101 102 103 | # File 'lib/cm_admin/models/dsl_method.rb', line 98 def cm_new(page_title: nil, page_description: nil, partial: nil, redirect_to: nil) @current_action = CmAdmin::Models::Action.find_by(self, name: 'new') page_title ||= "Add #{ar_model.model_name.plural.titleize}" @current_action.set_values(page_title, page_description, partial, redirect_to) yield end | 
#cm_section(section_name, display_if: nil, col_size: nil, html_attrs: nil, partial: nil, &block) ⇒ Object
| 201 202 203 204 205 | # File 'lib/cm_admin/models/dsl_method.rb', line 201 def cm_section(section_name, display_if: nil, col_size: nil, html_attrs: nil, partial: nil, &block) @available_fields[@current_action.name.to_sym] ||= [] @available_fields[@current_action.name.to_sym] << CmAdmin::Models::Section.new(section_name, @current_action, @model, display_if, html_attrs, col_size, partial, &block) end | 
#cm_show(page_title: nil, page_description: nil, partial: nil) ⇒ Object
Create a view for show page
| 44 45 46 47 48 49 | # File 'lib/cm_admin/models/dsl_method.rb', line 44 def cm_show(page_title: nil, page_description: nil, partial: nil) @current_action = CmAdmin::Models::Action.find_by(self, name: 'show') page_title ||= ar_model.model_name.plural.titleize @current_action.set_values(page_title, page_description, partial) yield end | 
#cm_show_section(section_name, display_if: nil, html_attrs: nil, partial: nil, &block) ⇒ Object
Use #cm_section instead of this method
| 208 209 210 | # File 'lib/cm_admin/models/dsl_method.rb', line 208 def cm_show_section(section_name, display_if: nil, html_attrs: nil, partial: nil, &block) cm_section(section_name, display_if:, html_attrs:, partial:, &block) end | 
#column(field_name, options = {}) ⇒ Object
Create a new column on index layout.
| 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 | # File 'lib/cm_admin/models/dsl_method.rb', line 227 def column(field_name, = {}) return unless @current_action.instance_of?(CmAdmin::Models::Action) @available_fields[@current_action.name.to_sym] ||= [] if @available_fields[@current_action.name.to_sym].select(&:lockable).size.positive? && [:lockable] raise 'Only one column can be locked in a table.' end if @available_fields[@current_action.name.to_sym].select(&:kanban_image).size.positive? && [:kanban_image] raise 'Only one column can be kanban image in a card view.' end if @available_fields[@current_action.name.to_sym].select(&:kanban_footer).size >= 2 && [:kanban_footer] raise 'Only two columns can be kanban footer in a card view.' end duplicate_columns = @available_fields[@current_action.name.to_sym].filter { |x| x.field_name.to_sym == field_name } terminate = false if duplicate_columns.size.positive? duplicate_columns.each do |column| if [:field_type].to_s != 'association' terminate = true elsif [:field_type].to_s == 'association' && column.association_name.to_s == [:association_name].to_s terminate = true end end end return if terminate add_to_filter = [:add_to_filter].nil? || [:add_to_filter] generate_filter_for_columns(field_name, add_to_filter: add_to_filter) @available_fields[@current_action.name.to_sym] << CmAdmin::Models::Column.new(field_name, ) end | 
#custom_action(name: nil, page_title: nil, page_description: nil, display_name: nil, verb: nil, layout: nil, layout_type: nil, partial: nil, path: nil, display_type: nil, redirect_to: nil, modal_configuration: {}, url_params: {}, display_if: ->(_) { true }, route_type: nil, icon_name: 'fa fa-th-large', icon_style: nil, group_name: nil, success_message: ->(_) { nil }, error_message: ->(_, _) { nil }, &block) ⇒ Object
Create a new custom action for model custom_action name: ‘change_password’, route_type: ‘member’, verb: ‘get’, icon_name: ‘fa-solid fa-key’, page_title: ‘Change Password’, path: ‘:id/change_password’, display_type: :form_modal do
form do
  cm_section 'Password Details' do
    form_field :username
    form_field :age_group_id, input_type: :single_select, helper_method: :age_group_type_collection
    form_field :cultural_background_ids, input_type: :multi_select, helper_method: :cultural_background_type_collection
    form_field :language, input_type: :single_select, helper_method: :language_collection
  end
end
on_submit do
  @customer = ::Customer.find(params[:id])
  @customer.update!(gender_id: params[:customer][:age_group_id])
  @customer
end
end Note: The form block is mandatory for form modal and form page. Params fields will always be under the parent class, for example: params[:age_group_id]
| 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 | # File 'lib/cm_admin/models/dsl_method.rb', line 346 def custom_action(name: nil, page_title: nil, page_description: nil, display_name: nil, verb: nil, layout: nil, layout_type: nil, partial: nil, path: nil, display_type: nil, redirect_to: nil, modal_configuration: {}, url_params: {}, display_if: ->(_) { true }, route_type: nil, icon_name: 'fa fa-th-large', icon_style: nil, group_name: nil, success_message: ->(_) { nil }, error_message: ->(_, _) { nil }, &block) @action = CmAdmin::Models::CustomAction.new( page_title:, page_description:, name:, display_name:, verb:, layout:, layout_type:, partial:, path:, parent: current_action.name, display_type:, display_if:, redirect_to:, action_type: :custom, route_type:, icon_name:, icon_style:, modal_configuration:, model_name: self.name, url_params:, group_name:, success_message:, error_message:, &block ) if @current_group @action.group_name = @current_group[:name] @action.group_icon_name = @current_group[:icon_name] @action.group_icon_style = @current_group[:icon_style] end if %i[form_page form_modal].include?(display_type) @current_action = @action @available_actions << @action define_singleton_method(:on_submit) do |&code_block| if display_type == :form_modal @action.code_block = code_block else @action.verb = :get generate_update_action(name, path, verb, redirect_to, route_type, , , &code_block) end end yield else @available_actions << @action end end | 
#eager_load_associations(associations = []) ⇒ Object
Configure Eager load associations for action This will help us avoid N+1 queries
| 580 581 582 | # File 'lib/cm_admin/models/dsl_method.rb', line 580 def eager_load_associations(associations = []) @current_action.eager_load_associations = associations if @current_action end | 
#filter(db_column_name, filter_type = nil, options = {}) ⇒ Object
Create a new filter for model
| 455 456 457 458 | # File 'lib/cm_admin/models/dsl_method.rb', line 455 def filter(db_column_name, filter_type = nil, = {}) filter_type = default_filter_type(db_column_name, filter_type) @filters << CmAdmin::Models::Filter.new(db_column_name:, filter_type:, options:) end | 
#kanban_view(column_name, exclude: [], only: []) ⇒ Object
Set kanban view for current action
| 125 126 127 128 129 130 131 | # File 'lib/cm_admin/models/dsl_method.rb', line 125 def kanban_view(column_name, exclude: [], only: []) return unless @current_action @current_action.kanban_attr[:column_name] = column_name @current_action.kanban_attr[:exclude] = exclude @current_action.kanban_attr[:only] = only end | 
#page_description(description) ⇒ Object
Set page description for current action
| 115 116 117 118 119 | # File 'lib/cm_admin/models/dsl_method.rb', line 115 def page_description(description) return unless @current_action @current_action.page_description = description end | 
#page_title(title) ⇒ Object
Set page title for current action
| 107 108 109 110 111 | # File 'lib/cm_admin/models/dsl_method.rb', line 107 def page_title(title) return unless @current_action @current_action.page_title = title end | 
#row(display_if: nil, html_attrs: nil, &block) ⇒ Object
Create a new row on page or form.
| 186 187 188 189 | # File 'lib/cm_admin/models/dsl_method.rb', line 186 def row(display_if: nil, html_attrs: nil, &block) @available_fields[@current_action.name.to_sym] ||= [] @available_fields[@current_action.name.to_sym] << CmAdmin::Models::Row.new(@current_action, @model, display_if, html_attrs, &block) end | 
#scope_list(scopes = []) ⇒ Object
Set scopes for current action
| 135 136 137 138 139 | # File 'lib/cm_admin/models/dsl_method.rb', line 135 def scope_list(scopes = []) return unless @current_action @current_action.scopes = scopes end | 
#sort_column(column = :created_at) ⇒ Object
@deprecated: use #sortable_columns instead of this method Set sort column for filters
| 479 480 481 | # File 'lib/cm_admin/models/dsl_method.rb', line 479 def sort_column(column = :created_at) @current_action.sort_column = column.to_sym if @current_action end | 
#sort_direction(direction = :desc) ⇒ Object
@deprecated: use #sortable_columns instead of this method Set sort direction for filters
| 465 466 467 468 469 470 471 472 | # File 'lib/cm_admin/models/dsl_method.rb', line 465 def sort_direction(direction = :desc) unless CmAdmin::Models::Action::VALID_SORT_DIRECTION.include?(direction.to_sym.downcase) raise ArgumentError, "Select a valid sort direction like #{CmAdmin::Models::Action::VALID_SORT_DIRECTION.join(' or ')} instead of #{direction}" end @current_action.sort_direction = direction.to_sym if @current_action end | 
#sortable_columns(columns) ⇒ Object
default sort direction will be ascending
Configure sortable columns for model verified_at is a JSONB column, so we need to specify the sort_datatype
sortable_columns([{column: 'id', display_name: 'ID', default: true, default_direction: 'desc'},
                  {column: 'updated_at', display_name: 'Last Updated At'},
                  {column: 'verified_at', display_name: 'Verified At', sort_datatype: 'TIMESTAMP'}])
| 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 | # File 'lib/cm_admin/models/dsl_method.rb', line 553 def sortable_columns(columns) @sort_columns = columns.map do |column| column[:display_if] ||= ->(_arg) { true } column end default_column = @sort_columns.filter do |column| column.key?(:default) || column.key?(:default_direction) end raise ArgumentError, 'only one column can be default' if default_column.size > 1 if default_column.blank? @default_sort_column = nil @default_sort_direction = 'asc' return end default_column = default_column.first @default_sort_column = default_column[:column] @default_sort_direction = default_column[:default_direction] if default_column[:default_direction].present? end | 
#tab(tab_name, action_name, associated_model: nil, layout_type: nil, layout: nil, partial: nil, display_if: nil, show_count: true, view_type: nil, associated_model_name: nil, allow_create_action: -> { true }, &block) ⇒ Object
Create a new tab on show page.
| 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | # File 'lib/cm_admin/models/dsl_method.rb', line 158 def tab(tab_name, action_name, associated_model: nil, layout_type: nil, layout: nil, partial: nil, display_if: nil, show_count: true, view_type: nil, associated_model_name: nil, allow_create_action: -> { true }, &block) action_name = action_name.to_s.gsub(' ', '').underscore if action_name.to_s == '' @current_action = CmAdmin::Models::Action.find_by(self, name: 'show') @available_tabs << CmAdmin::Models::Tab.new(tab_name, '', display_if, show_count, &block) else action = CmAdmin::Models::Action.new(name: action_name.to_s, verb: :get, path: ":id/#{action_name}", layout_type:, layout:, partial:, child_records: associated_model, action_type: :tab, display_type: :page, model_name: name, view_type:, associated_model_name:, allow_create_action:) @available_actions << action @current_action = action @available_tabs << CmAdmin::Models::Tab.new(tab_name, action_name, display_if, show_count, &block) end yield if block end |