Skip to content

Commit

Permalink
Support element initialization via components attributes Hash
Browse files Browse the repository at this point in the history
Renames the components attributes Hash to attributes_or_elements.
Enhances the initialize_elements method to lookup available element
values from the attributes_or_elements Hash and assigns them.
  • Loading branch information
msalzburg committed Aug 9, 2023
1 parent 7750158 commit a71fe1b
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 11 deletions.
7 changes: 6 additions & 1 deletion .rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2023-08-09 18:43:11 UTC using RuboCop version 1.56.0.
# on 2023-08-09 19:56:28 UTC using RuboCop version 1.56.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
Expand All @@ -12,3 +12,8 @@
Gemspec/RequiredRubyVersion:
Exclude:
- 'elemental_components.gemspec'

# Offense count: 1
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
Metrics/MethodLength:
Max: 13
34 changes: 24 additions & 10 deletions lib/elemental_components/element.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ def self.define_method_or_raise(method_name, &block)
end
private_class_method :define_method_or_raise

def initialize(view, attributes = nil, &block)
def initialize(view, attributes_or_elements = nil, &block)
@view = view
initialize_attributes(attributes || {})
initialize_elements
initialize_attributes(attributes_or_elements || {})
initialize_elements(attributes_or_elements || {})
@yield = block_given? ? @view.capture(self, &block) : nil
validate!
end
Expand All @@ -85,28 +85,42 @@ def content

protected

def initialize_attributes(attributes)
def initialize_attributes(attributes_or_elements)
self.class.attributes.each do |name, options|
set_instance_variable(name, attribute_value(attributes, name, options[:default]))
set_instance_variable(name, attribute_value(attributes_or_elements, name, options[:default]))
end
end

def attribute_value(attributes, name, default)
return attributes[name] if attributes.key?(name)

default.dup
def attribute_value(attributes_or_elements, name, default)
attributes_or_elements.key?(name) ? attributes_or_elements[name] : default.dup
end

def initialize_elements
def initialize_elements(attributes_or_elements)
self.class.elements.each do |name, options|
if (plural_name = options[:multiple])
set_instance_variable(plural_name, [])

if (plural_values = element_value(attributes_or_elements, plural_name))
plural_values.each { |plural_value| initialize_element(name, plural_value) }
end
else
set_instance_variable(name, nil)

if (single_value = element_value(attributes_or_elements, name))
initialize_element(name, single_value)
end
end
end
end

def initialize_element(name, value)
value.is_a?(Hash) ? send(name.to_sym, value) : send(name.to_sym, {}) { value }
end

def element_value(attributes_or_elements, name)
attributes_or_elements.key?(name) ? attributes_or_elements[name] : nil
end

private

def get_instance_variable(name)
Expand Down
55 changes: 55 additions & 0 deletions test/elemental_components/component_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,61 @@ class ElementalComponents::ComponentTest < ActiveSupport::TestCase
assert_equal "bar", component.foos[1].content
end

test "initialize element with multiple true via plural_name in attributes hash" do
component_class = Class.new(ElementalComponents::Component) do
element :item, multiple: true
end
component = component_class.new(view_class.new, items: %w[foo bar])
assert_equal 2, component.items.length
assert_equal "foo", component.items[0].content
assert_equal "bar", component.items[1].content
end

test "initialize element with multiple true via plural_name in attributes hash and via block" do
component_class = Class.new(ElementalComponents::Component) do
element :item, multiple: true
end
component = component_class.new(view_class.new, items: %w[foo bar])
component.item { "baz" }
assert_equal 3, component.items.length
assert_equal "foo", component.items[0].content
assert_equal "bar", component.items[1].content
assert_equal "baz", component.items[2].content
end

test "initialize element with multiple true and attributes via plural_name in attributes hash" do
component_class = Class.new(ElementalComponents::Component) do
element :item, multiple: true do
attribute :title
attribute :count
end
end
component = component_class.new(view_class.new, items: [{ title: "foo", count: 1 }, { title: "bar", count: 2 }])
assert_equal 2, component.items.length
assert_equal "foo", component.items[0].title
assert_equal 1, component.items[0].count
assert_equal "bar", component.items[1].title
assert_equal 2, component.items[1].count
end

test "initialize element with multiple true and attributes via plural_name in attributes hash and via block" do
component_class = Class.new(ElementalComponents::Component) do
element :item, multiple: true do
attribute :title
attribute :count
end
end
component = component_class.new(view_class.new, items: [{ title: "foo", count: 1 }, { title: "bar", count: 2 }])
component.item({ title: "baz", count: 3 })
assert_equal 3, component.items.length
assert_equal "foo", component.items[0].title
assert_equal 1, component.items[0].count
assert_equal "bar", component.items[1].title
assert_equal 2, component.items[1].count
assert_equal "baz", component.items[2].title
assert_equal 3, component.items[2].count
end

test "initialize element with multiple true when singular and plural name are the same" do
component_class = Class.new(ElementalComponents::Component) do
element :foos, multiple: true
Expand Down

0 comments on commit a71fe1b

Please sign in to comment.