Skip to content

Instantly share code, notes, and snippets.

@georgekettle
Created November 10, 2023 20:39
Show Gist options
  • Save georgekettle/6150707c6b40ab747a9be530df825e46 to your computer and use it in GitHub Desktop.
Save georgekettle/6150707c6b40ab747a9be530df825e46 to your computer and use it in GitHub Desktop.
AttributeMerger for Phlex Components
class AttributeMerger
attr_reader :default_attrs, :user_attrs
OVERRIDE_KEY = '!'.freeze
def initialize(default_attrs, user_attrs)
@default_attrs = flatten_hash(default_attrs)
@user_attrs = flatten_hash(user_attrs)
end
def call
merged_attrs = merge_hashes(default_attrs, non_override_attrs)
mix(merged_attrs, override_attrs)
end
private
# @return [Hash]
def mix(*args)
args.each_with_object({}) do |object, result|
result.merge!(object) do |_key, old, new|
case new
when Hash
old.is_a?(Hash) ? mix(old, new) : new
when Array
old.is_a?(Array) ? (old + new) : new
when String
old.is_a?(String) ? "#{old} #{new}" : new
else
new
end
end
result.transform_keys! do |key|
key.end_with?("!") ? key.name.chop.to_sym : key
end
end
end
def override_attrs
user_attrs.select do |key, value|
key.to_s.include?(OVERRIDE_KEY)
end
end
def non_override_attrs
user_attrs.reject do |key, value|
key.to_s.include?(OVERRIDE_KEY)
end
end
def flatten_hash(hash, parent_key = '', result_hash = {})
hash.each do |key, value|
new_key = parent_key.empty? ? key : "#{parent_key}_#{key}".to_sym
if value.is_a? Hash
flatten_hash(value, new_key, result_hash)
else
result_hash[new_key] = value
end
end
result_hash
end
def merge_hashes(hash1, hash2)
flat_hash1 = flatten_hash(hash1)
flat_hash2 = flatten_hash(hash2)
merged = flat_hash1.merge(flat_hash2) do |key, oldval, newval|
"#{oldval} #{newval}"
end
merged
end
end
require 'attribute_merger'
AttributeMerger.new({class: 'bg-blue border py-2', data_action: 'click->accordion#open'}, {}).call
# => {class: 'bg-blue border py-2', data_action: 'click->accordion#open'}
AttributeMerger.new({class: 'bg-blue border py-2', data_action: 'click->accordion#open'}, {class: 'bg-black',
data_action: 'mouseenter->accordion#open'}).call
# => {:class=>"bg-blue border py-2 bg-black", :data_action=>"click->accordion#open mouseenter->accordion#open"}
# Override attributes with '!' key values (eg. class!:)
AttributeMerger.new({
class: 'bg-blue border py-2',
data_action: 'click->accordion#open'
},
{
class!: 'bg-black',
data: {
action!: 'mouseenter->accordion#open'
}
}
).call
# => {:class=>"bg-black", :data_action=>"mouseenter->accordion#open"}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment