class SparkComponents::Element
Attributes
attr[R]
parents[R]
yield[RW]
Public Class Methods
add_class(*args)
click to toggle source
# File lib/spark_components/element.rb, line 48 def self.add_class(*args) tag_attrs.add_class(*args) end
aria_attr(*args)
click to toggle source
# File lib/spark_components/element.rb, line 56 def self.aria_attr(*args) arg = attribute(*args) tag_attrs.aria(arg) end
attribute(*args)
click to toggle source
# File lib/spark_components/element.rb, line 22 def self.attribute(*args) args.each_with_object({}) do |arg, obj| if arg.is_a?(Hash) arg.each do |attr, default| obj[attr.to_sym] = default set_attribute(attr.to_sym, default: default) end else obj[arg.to_sym] = nil set_attribute(arg.to_sym) end end end
attributes()
click to toggle source
# File lib/spark_components/element.rb, line 14 def self.attributes @attributes ||= {} end
base_class(name = nil)
click to toggle source
# File lib/spark_components/element.rb, line 44 def self.base_class(name = nil) tag_attrs.base_class(name) end
data_attr(*args)
click to toggle source
# File lib/spark_components/element.rb, line 52 def self.data_attr(*args) tag_attrs.data(attribute(*args)) end
element(name, multiple: false, component: nil, &config)
click to toggle source
rubocop:disable Metrics/AbcSize rubocop:disable Metrics/CyclomaticComplexity rubocop:disable Metrics/MethodLength rubocop:disable Metrics/PerceivedComplexity
# File lib/spark_components/element.rb, line 84 def self.element(name, multiple: false, component: nil, &config) plural_name = name.to_s.pluralize.to_sym if multiple # Extend components by string or class; e.g., "core/header" or Core::HeaderComponent component = "#{component}_component".classify.constantize if component.is_a?(String) elements[name] = { multiple: plural_name || false, class: Class.new((component || Element), &config) } define_method_or_raise(name) do |attributes = nil, &block| return get_instance_variable(multiple ? plural_name : name) unless attributes || block element = self.class.elements[name][:class].new(@view, attributes, &block) element.parent = self if multiple get_instance_variable(plural_name) << element else set_instance_variable(name, element) end if element.respond_to?(:render) element.before_render element.yield = element.render end end return if !multiple || name == plural_name define_method_or_raise(plural_name) do get_instance_variable(plural_name) end end
elements()
click to toggle source
# File lib/spark_components/element.rb, line 18 def self.elements @elements ||= {} end
inherited(subclass)
click to toggle source
# File lib/spark_components/element.rb, line 132 def self.inherited(subclass) attributes.each { |name, options| subclass.set_attribute(name, options.dup) } elements.each { |name, options| subclass.elements[name] = options.dup } subclass.tag_attrs.merge!(tag_attrs.dup) end
model_name()
click to toggle source
# File lib/spark_components/element.rb, line 10 def self.model_name ActiveModel::Name.new(SparkComponents::Element) end
new(view, attributes = nil, &block)
click to toggle source
# File lib/spark_components/element.rb, line 139 def initialize(view, attributes = nil, &block) @view = view attributes ||= {} initialize_tag_attrs assign_tag_attrs(attributes) initialize_attributes(attributes) initialize_elements extend_view_methods after_init @yield = render_block(&block) validate! end
root_attr(*args)
click to toggle source
# File lib/spark_components/element.rb, line 61 def self.root_attr(*args) tag_attrs.root(attribute(*args)) end
set_attribute(name, default: nil)
click to toggle source
# File lib/spark_components/element.rb, line 36 def self.set_attribute(name, default: nil) attributes[name] = { default: default } define_method_or_raise(name) do get_instance_variable(name) end end
tag_attrs()
click to toggle source
# File lib/spark_components/element.rb, line 65 def self.tag_attrs @tag_attrs ||= SparkComponents::Attributes::Tag.new end
validates_choice(name, choices, required: true)
click to toggle source
# File lib/spark_components/element.rb, line 69 def self.validates_choice(name, choices, required: true) choices = choices.dup choices = [choices] unless choices.is_a?(Array) supported_choices = choices.map { |c| c.is_a?(String) ? c.to_sym : c.to_s }.concat(choices) choices = choices.to_sentence(last_word_connector: ", or ") message = "\"%<value>s\" is not valid. Options for #{name} include: #{choices}" validates(name, inclusion: { in: supported_choices, message: message }, allow_blank: !required) end
Private Class Methods
define_method_or_raise(method_name, &block)
click to toggle source
rubocop:enable Metrics/AbcSize rubocop:enable Metrics/CyclomaticComplexity rubocop:enable Metrics/MethodLength rubocop:enable Metrics/PerceivedComplexity
# File lib/spark_components/element.rb, line 123 def self.define_method_or_raise(method_name, &block) # Select instance methods but not those which are intance methods received by extending a class methods = (instance_methods - superclass.instance_methods(false)) raise(SparkComponents::Error, "Method '#{method_name}' already exists.") if methods.include?(method_name.to_sym) define_method(method_name, &block) end
Public Instance Methods
add_class(*args)
click to toggle source
# File lib/spark_components/element.rb, line 173 def add_class(*args) classnames(*args) end
after_init()
click to toggle source
# File lib/spark_components/element.rb, line 152 def after_init; end
aria_attr(*args)
click to toggle source
# File lib/spark_components/element.rb, line 185 def aria_attr(*args) @tag_attrs.aria(*args) end
base_class(name = nil)
click to toggle source
# File lib/spark_components/element.rb, line 168 def base_class(name = nil) classnames.base = name unless name.nil? classnames.base end
before_render()
click to toggle source
# File lib/spark_components/element.rb, line 154 def before_render; end
blank?()
click to toggle source
blank? is aliased to an element's content to easily determine if content is blank. This is because template conditionals may render an element's content empty.
# File lib/spark_components/element.rb, line 204 def blank? @yield.blank? end
classnames(*args)
click to toggle source
# File lib/spark_components/element.rb, line 164 def classnames(*args) @tag_attrs.classnames(*args) end
data_attr(*args)
click to toggle source
# File lib/spark_components/element.rb, line 181 def data_attr(*args) @tag_attrs.data(*args) end
join_class(*args)
click to toggle source
# File lib/spark_components/element.rb, line 177 def join_class(*args) classnames.join_class(*args) end
parent()
click to toggle source
# File lib/spark_components/element.rb, line 160 def parent @parents.last end
parent=(obj)
click to toggle source
# File lib/spark_components/element.rb, line 156 def parent=(obj) @parents = [obj.parents, obj].flatten.compact end
root_attr(*args)
click to toggle source
# File lib/spark_components/element.rb, line 189 def root_attr(*args) @tag_attrs.root(*args) end
tag_attrs()
click to toggle source
# File lib/spark_components/element.rb, line 193 def tag_attrs @tag_attrs.attrs end
to_s()
click to toggle source
# File lib/spark_components/element.rb, line 197 def to_s @yield end
Protected Instance Methods
assign_tag_attrs(attributes)
click to toggle source
Assign tag attributes from arguments
# File lib/spark_components/element.rb, line 232 def assign_tag_attrs(attributes) # support default data, class, and aria attribute names data_attr(attributes.delete(:data)) if attributes[:data] aria_attr(attributes.delete(:aria)) if attributes[:aria] add_class(*attributes.delete(:class)) if attributes[:class] root_attr(attributes.delete(:splat)) if attributes[:splat] end
extend_view_methods()
click to toggle source
# File lib/spark_components/element.rb, line 262 def extend_view_methods view_methods.each do |name| next if respond_to?(name) || !@view.respond_to?(name) self.class.define_method(name) do |*args, &block| @view.send(name, *args, &block) end end end
get_instance_variable(name)
click to toggle source
# File lib/spark_components/element.rb, line 272 def get_instance_variable(name) instance_variable_get(:"@#{name}") end
initialize_attributes(attributes)
click to toggle source
# File lib/spark_components/element.rb, line 240 def initialize_attributes(attributes) self.class.attributes.each do |name, options| set_instance_variable(name, attributes[name] || (options[:default] && options[:default].dup)) update_tag_attr(name) end end
initialize_elements()
click to toggle source
# File lib/spark_components/element.rb, line 247 def initialize_elements self.class.elements.each do |name, options| if (plural_name = options[:multiple]) set_instance_variable(plural_name, []) else set_instance_variable(name, nil) end end end
initialize_tag_attrs()
click to toggle source
# File lib/spark_components/element.rb, line 227 def initialize_tag_attrs @tag_attrs = self.class.tag_attrs.dup end
render_partial(file)
click to toggle source
# File lib/spark_components/element.rb, line 223 def render_partial(file) @view.render(partial: file, object: self) end
set_instance_variable(name, value)
click to toggle source
# File lib/spark_components/element.rb, line 276 def set_instance_variable(name, value) instance_variable_set(:"@#{name}", value) end
update_tag_attr(name)
click to toggle source
Set tag attribute values from from parameters
# File lib/spark_components/element.rb, line 217 def update_tag_attr(name) %i[aria data root].each do |el| @tag_attrs.send(el)[name] = get_instance_variable(name) if @tag_attrs.send(el).key?(name) end end
view_methods()
click to toggle source
Define common view methods to “alias”
# File lib/spark_components/element.rb, line 258 def view_methods %i[tag content_tag image_tag concat content_for link_to component capture] end
Private Instance Methods
render_block(&block)
click to toggle source
# File lib/spark_components/element.rb, line 210 def render_block(&block) block_given? ? @view.capture(self, &block) : nil end