class ActionPresenter::Base
Constants
- BOOTSTRAP_SIZES
- PRESENTER_ATTRIBUTES
- PRESENTER_CLASSES
inheritance tracking
Attributes
form_builder[R]
record[RW]
view[RW]
Public Class Methods
define_extension(base_method, new_method, *extension_params)
click to toggle source
# File lib/action_presenter/base.rb, line 117 def define_extension(base_method, new_method, *extension_params) define_method(new_method) do |*params, &content_block| send(base_method, *params, *extension_params.deep_dup, &content_block) end end
generate_bootstrap_presenter_methods!()
click to toggle source
# File lib/action_presenter/base/bootstrap.rb, line 4 def self.generate_bootstrap_presenter_methods! ["", "offset"].each do |namespace| define_method("col_#{namespace}_class".squeeze("_")) do |*hashes, &content_block| classes = [] BOOTSTRAP_SIZES.each do |col_size| col_width = extract("col_#{col_size}", *hashes).to_i.nonzero? if col_width col_width += 1 if extract("#{col_size}_expand", *hashes) == true && col_width < 11 col_width -= 1 if extract("#{col_size}_compact", *hashes) == true && col_width > 2 raise ArgumentError, "col_width must be between 1 and 12" if !col_width.between?(1,12) # col-sm-3 classes << "col-#{col_size}-#{namespace}-#{col_width}".squeeze("-") end end [extract_html(*hashes)[:class], *classes].join(" ") end end define_method(:col_div) do |*hashes, &content_block| classes = [] BOOTSTRAP_SIZES.each do |col_size| col_width = extract("col_#{col_size}", *hashes).to_i.nonzero? col_offset_width = extract("col_#{col_size}_offset", *hashes).to_i.nonzero? if col_width col_width += 1 if extract("#{col_size}_expand", *hashes) == true && col_width < 11 col_width -= 1 if extract("#{col_size}_compact", *hashes) == true && col_width > 2 classes << col_class("col_#{col_size}" => col_width) end if col_offset_width col_offset_width += 1 if extract("#{col_size}_offset_expand", *hashes) == true && col_offset_width < 11 col_offset_width -= 1 if extract("#{col_size}_offset_compact", *hashes) == true && col_offset_width > 2 raise ArgumentError, "col_width must be between 1 and 12" if !col_offset_width.between?(1,12) classes << col_offset_class("col_#{col_size}" => col_offset_width) end end div_tag(*hashes, add_class: classes.join(" "), &content_block) end define_method(:check_box_div_label) do |*hashes, &content_block| content = extract_content(*hashes, &content_block) check_box_div(*hashes) { label_tag(content: content) } end define_method(:label_span) do |label, *hashes, &content_block| span_tag(*hashes, add_class: "label label-#{label}", &content_block) end define_method(:alert_div) do |alert, *hashes, &content_block| div_tag(*hashes, class: "alert alert-#{alert} alert-dismissible", role: "alert", &content_block) end define_method(:dismiss_button) do |target, *hashes, &content_block| button_tag(*hashes, "aria-label" => "Dismiss", data: { dismiss: target.to_s }, &content_block) end define_method(:dropdown_toggle_btn) do |*hashes, &content_block| btn = extract(:btn, *hashes, btn: "default") button_tag(*hashes, class: "btn btn-#{btn} dropdown-toggle", data: { toggle: "dropdown" }, &content_block) end define_method(:glyphicon) do |glyphicon, *hashes, &content_block| span_tag(*hashes, add_class: "glyphicon glyphicon-#{glyphicon}", &content_block) end # override core classes { core_label_class: -> { "control-label" }, core_select_class: -> { "form-control" }, core_field_class: -> { "form-control" }, core_text_area_class: -> { "form-control" }, }.each do |method, block| define_method(method, &block) end # div define_extension(:div_tag, :row_div, class: "row") define_extension(:div_tag, :form_group_div, class: "form-group") define_extension(:div_tag, :dropdown_div, class: "dropdown") define_extension(:div_tag, :check_box_div, class: "checkbox") # span define_extension(:span_tag, :caret_span, class: "caret") # ul define_extension(:ul_tag, :dropdown_menu_ul, class: "dropdown-menu", role: "menu") # label define_extension(:label_tag, :radio_label, class: "radio") define_extension(:label_tag, :check_box_label, class: "checkbox") end
inherited(new_presenter_class)
click to toggle source
Calls superclass method
# File lib/action_presenter/base.rb, line 6 def self.inherited(new_presenter_class) PRESENTER_CLASSES << new_presenter_class super end
new()
click to toggle source
core methods
# File lib/action_presenter/base.rb, line 12 def initialize end
presenter_options()
click to toggle source
# File lib/action_presenter/base.rb, line 123 def presenter_options @presenter_options ||= ActiveSupport::OrderedOptions.new.merge( verify_content: true, presents: name.underscore.remove(/_presenter\z/).singularize.to_sym, ) end
Public Instance Methods
check_box(name, *hashes)
click to toggle source
# File lib/action_presenter/base/form.rb, line 76 def check_box(name, *hashes) default_html = { class: check_box_class } checked_value = extract(:checked_value, *hashes, checked_value: "true") unchecked_value = extract(:unchecked_value, *hashes, unchecked_value: "false") form_builder.check_box(name, extract_html(*hashes, default_html), checked_value, unchecked_value) end
check_box_tag(name, *hashes, &content_block)
click to toggle source
# File lib/action_presenter/base/html.rb, line 92 def check_box_tag(name, *hashes, &content_block) default_html = { id: name.to_s.slugify_html, name: name, class: check_box_class } checked_value = extract_content(*hashes, content: "true").presence unchecked_value = extract(:unchecked_value, *hashes).presence checked = extract(:checked, *hashes, checked: view.params.to_unsafe_h.dig_html(name).presence == checked_value).present? check_box_html = extract_html(*hashes, default_html) content = "".html_safe if unchecked_value.present? content += view.check_box_tag(nil, unchecked_value, true, default_html.merge(id: nil, class: nil, style: "display: none;")) end content + view.check_box_tag(nil, checked_value, checked, check_box_html) end
date_select(name, *hashes)
click to toggle source
# File lib/action_presenter/base/form.rb, line 54 def date_select(name, *hashes) default_html = { class: date_select_class } hashes << { order: %i[ month day year ] } select_options = {} %i[ include_blank prompt order default start_year end_year add_month_numbers use_short_month ].each { |key| select_options[key] = extract(key, *hashes) } form_builder.date_select(name, select_options.compact, extract_html(*hashes, default_html)) end
datetime_select(name, *hashes)
click to toggle source
# File lib/action_presenter/base/form.rb, line 65 def datetime_select(name, *hashes) default_html = { class: datetime_select_class } hashes << { order: %i[ month day year ], ampm: true } select_options = {} %i[ include_blank prompt ampm order default start_year end_year ].each { |key| select_options[key] = extract(key, *hashes) } form_builder.datetime_select(name, select_options, extract_html(*hashes, class: datetime_select_class)) end
extract(key, *hashes)
click to toggle source
# File lib/action_presenter/base.rb, line 28 def extract(key, *hashes) hashes.compact.map do |hash| begin hash.delete(key.to_sym) || hash.delete(key.to_s) rescue StandardError => error raise ArgumentError, "#{error.class} while trying to extract key #{key.inspect} from #{hash.inspect}: #{error.message}" end end.compact.first end
extract_content(*hashes, &content_block)
click to toggle source
# File lib/action_presenter/base.rb, line 85 def extract_content(*hashes, &content_block) content = extract(:content, *hashes) # block has highest precedence content = view.capture(&content_block) if content_block.is_a?(Proc) content = content.to_s if content.is_a?(Numeric) # check for escaped HTML if presenter_options.verify_content && !content.is_a?(ActiveSupport::SafeBuffer) if content =~ /<[a-zA-Z]+( |>)/ || content =~ / / warning_message = "Escaped HTML in #{self.class} content: #{content}" if Rails.env.production? Rails.logger.warn { warning_message } else raise ArgumentError, warning_message end end end content end
extract_content_block(*hashes, &content_block)
click to toggle source
# File lib/action_presenter/base.rb, line 104 def extract_content_block(*hashes, &content_block) content_block.is_a?(Proc) ? content_block : proc { extract_content(*hashes) } end
extract_html(*hashes)
click to toggle source
# File lib/action_presenter/base.rb, line 38 def extract_html(*hashes) html_attributes = {} add_classes = [] remove_classes = [] merge_data = {} reverse_merge_data = {} hashes.each do |hash| next if hash.blank? # custom class attributes add_class = extract(:add_class, hash) add_classes << add_class if add_class.present? remove_class = extract(:remove_class, hash) remove_classes << remove_class if remove_class.present? # custom data attributes merging_data = extract(:merge_data, hash) merge_data.merge!(merging_data.to_h.symbolize_keys) if merging_data.present? reverse_merging_data = extract(:reverse_merge_data, hash) reverse_merge_data.merge!(reverse_merging_data.to_h.symbolize_keys) if reverse_merging_data.present? # rest html_attributes.reverse_merge!(hash.symbolize_keys) end # custom class attributes if add_classes.present? || remove_classes.present? classes_to_a = -> (value) do case value when Symbol then classes_to_a.call(send(value)) when Array then value.map { |v| classes_to_a.call(v) } else value.to_s.split(/\s/) end.flatten end classes = classes_to_a.call(html_attributes[:class]) classes += classes_to_a.call(add_classes) classes -= classes_to_a.call(remove_classes) # reverse so classes appear to append in order html_attributes[:class] = classes.uniq.join(" ").presence end # custom data attributes if merge_data.present? || reverse_merge_data.present? html_attributes[:data] ||= {} html_attributes[:data].merge!(merge_data) if merge_data.present? html_attributes[:data].reverse_merge!(reverse_merge_data) if reverse_merge_data.present? end html_attributes.select do |html_attribute, value| !html_attribute.in?(PRESENTER_ATTRIBUTES) end end
extract_query_params(*hashes)
click to toggle source
# File lib/action_presenter/base.rb, line 112 def extract_query_params(*hashes) extract(:query_params, *hashes, query_params: {}) end
extract_record(*hashes)
click to toggle source
# File lib/action_presenter/base.rb, line 108 def extract_record(*hashes) extract(:record, *hashes, record: record) end
file_field_tag(name, *hashes, &content_block)
click to toggle source
# File lib/action_presenter/base/html.rb, line 70 def file_field_tag(name, *hashes, &content_block) default_html = { id: name.to_s.slugify_html, name: name, class: file_field_class } view.file_field_tag(name, extract_html(*hashes, default_html)) end
form_builder=(new_form_builder)
click to toggle source
# File lib/action_presenter/base/form.rb, line 20 def form_builder=(new_form_builder) @form_builder = new_form_builder self.record = form_builder.try(:object) @form_builder end
form_for(*hashes) { |form_builder| ... }
click to toggle source
# File lib/action_presenter/base/form.rb, line 12 def form_for(*hashes, &content_block) record = extract_record(*hashes) view.form_for(record, extract_html(*hashes)) do |form_builder| self.form_builder = form_builder yield(form_builder) end end
form_tag(path, *hashes) { |form_builder| ... }
click to toggle source
# File lib/action_presenter/base/form.rb, line 5 def form_tag(path, *hashes, &content_block) view.form_tag(path, extract_html(*hashes)) do |form_builder| self.form_builder = form_builder yield(form_builder) end end
html_tag(tag, *hashes, &content_block)
click to toggle source
# File lib/action_presenter/base/html.rb, line 4 def html_tag(tag, *hashes, &content_block) view.content_tag(tag, extract_html(*hashes), &extract_content_block(*hashes, &content_block)) end
image_tag(name, *hashes, &content_block)
click to toggle source
# File lib/action_presenter/base/html.rb, line 46 def image_tag(name, *hashes, &content_block) view.image_tag(name, extract_html(*hashes), &extract_content_block(*hashes, &content_block)) end
inline_html_tag(tag, *hashes, &content_block)
click to toggle source
# File lib/action_presenter/base/html.rb, line 8 def inline_html_tag(tag, *hashes, &content_block) view.tag(tag, extract_html(*hashes), &extract_content_block(*hashes, &content_block)) end
label(name, *hashes, &content_block)
click to toggle source
form elements
# File lib/action_presenter/base/form.rb, line 27 def label(name, *hashes, &content_block) default_html = { class: label_class } form_builder.label(name, extract_html(*hashes, default_html), &extract_content_block(*hashes, &content_block)) end
label_for(name, *hashes, &content_block)
click to toggle source
# File lib/action_presenter/base/html.rb, line 87 def label_for(name, *hashes, &content_block) default_html = { class: label_for_class } view.label_tag(name, extract_html(*hashes, default_html), &extract_content_block(*hashes, &content_block)) end
link_to(link, *hashes, &content_block)
click to toggle source
# File lib/action_presenter/base/html.rb, line 50 def link_to(link, *hashes, &content_block) view.link_to(link, extract_html(*hashes), &extract_content_block(*hashes, &content_block)) end
method_field(*hashes, &content_block)
click to toggle source
# File lib/action_presenter/base/html.rb, line 42 def method_field(*hashes, &content_block) hidden_field_tag("_method", *hashes, id: nil, value: "post", &content_block) end
presenter_options()
click to toggle source
# File lib/action_presenter/base.rb, line 24 def presenter_options self.class.presenter_options.dup end
select(name, *hashes, &content_block)
click to toggle source
# File lib/action_presenter/base/form.rb, line 47 def select(name, *hashes, &content_block) default_html = { class: select_class } content = extract_content(*hashes, &content_block) || {} select_options = %i[ include_blank prompt ].map { |key| [key, extract(key, *hashes)] }.to_h form_builder.select(name, content, select_options, extract_html(*hashes, default_html)) end
select_tag(name, *hashes, &content_block)
click to toggle source
form elements
# File lib/action_presenter/base/html.rb, line 55 def select_tag(name, *hashes, &content_block) default_html = { id: name.to_s.slugify_html, name: name, class: select_class } content = extract_content(*hashes, &content_block) if !content.is_a?(String) content = view.options_for_select(content, extract(:selected, *hashes, selected: view.params.to_unsafe_h.dig_html(name))) end view.select_tag(name, content, extract_html(*hashes, default_html)) end
set(options)
click to toggle source
# File lib/action_presenter/base.rb, line 19 def set(options) options.each { |method, value| send "#{method}=", value } self end
submit_tag(*hashes, &content_block)
click to toggle source
# File lib/action_presenter/base/html.rb, line 38 def submit_tag(*hashes, &content_block) view.submit_tag(extract_content(*hashes, content: "Submit", &content_block), extract_html(*hashes)) end
text_area(name, *hashes, &content_block)
click to toggle source
# File lib/action_presenter/base/form.rb, line 42 def text_area(name, *hashes, &content_block) default_html = { class: text_area_class, value: extract_content(*hashes, &content_block) }.compact form_builder.text_area(name, extract_html(*hashes, default_html)) end
text_area_tag(name, *hashes, &content_block)
click to toggle source
# File lib/action_presenter/base/html.rb, line 81 def text_area_tag(name, *hashes, &content_block) default_html = { id: name.to_s.slugify_html, name: name, class: text_area_class } content = extract_content(*hashes, content: view.params.to_unsafe_h.dig_html(name), &content_block) view.text_area_tag(name, content, extract_html(*hashes, default_html)) end
text_field(name, *hashes, &content_block)
click to toggle source
# File lib/action_presenter/base/form.rb, line 32 def text_field(name, *hashes, &content_block) default_html = { class: text_field_class, value: extract_content(*hashes, &content_block) }.compact form_builder.text_field(name, extract_html(*hashes, default_html)) end
text_field_tag(name, *hashes, &content_block)
click to toggle source
# File lib/action_presenter/base/html.rb, line 64 def text_field_tag(name, *hashes, &content_block) default_html = { id: name.to_s.slugify_html, name: name, class: text_field_class } content = extract_content(*hashes, content: view.params.to_unsafe_h.dig_html(name), &content_block) view.text_field_tag(name, content, extract_html(*hashes, default_html)) end