From d47f24ff43b9bb26cd744f7d0d36f8507300dd49 Mon Sep 17 00:00:00 2001 From: Joel Drapper Date: Sat, 15 Feb 2025 21:09:17 +0000 Subject: [PATCH 1/6] Fix the benchmark script --- bench.rb | 52 +++++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 25 deletions(-) mode change 100644 => 100755 bench.rb diff --git a/bench.rb b/bench.rb old mode 100644 new mode 100755 index d7db4a2..6ee8b50 --- a/bench.rb +++ b/bench.rb @@ -1,35 +1,37 @@ +#!/usr/bin/env ruby # frozen_string_literal: true require "benchmark/ips" +require "class_variants" -module ClassVariants -end +RubyVM::YJIT.enable -require_relative "lib/class_variants/instance" +button_classes = ClassVariants.build( + base: "rounded border-2 focus:ring-blue-500", + variants: { + size: { + sm: "text-xs px-1.5 py-1", + base: "text-sm px-2 py-1.5", + lg: "text-base px-3 py-2" + }, + color: { + white: "text-white bg-transparent border-white", + blue: "text-white bg-blue-500 border-blue-700 hover:bg-blue-600", + red: "text-white bg-red-500 border-red-700 hover:bg-red-600" + }, + block: "justify-center w-full", + "!block": "justify-between" + }, + defaults: { + size: :base, + color: :white, + block: false + } +) Benchmark.ips do |x| - button_classes = ClassVariants::Instance.new( - "rounded border-2 focus:ring-blue-500", - variants: { - size: { - sm: "text-xs px-1.5 py-1", - base: "text-sm px-2 py-1.5", - lg: "text-base px-3 py-2" - }, - color: { - white: "text-white bg-transparent border-white", - blue: "text-white bg-blue-500 border-blue-700 hover:bg-blue-600", - red: "text-white bg-red-500 border-red-700 hover:bg-red-600" - }, - block: "justify-center w-full", - "!block": "justify-between" - }, - defaults: { - size: :base, - color: :white, - block: false - } - ) + x.warmup = 5 + x.time = 20 x.report("rendering only defaults") do button_classes.render From 4e4c1cfe3ee0830b3e5923d5ac596ec937ed44eb Mon Sep 17 00:00:00 2001 From: Joel Drapper Date: Sat, 15 Feb 2025 21:09:43 +0000 Subject: [PATCH 2/6] Frozen string literals --- lib/class_variants.rb | 2 ++ lib/class_variants/action_view/helpers.rb | 2 ++ lib/class_variants/configuration.rb | 2 ++ lib/class_variants/helper.rb | 2 ++ lib/class_variants/instance.rb | 2 ++ lib/class_variants/railtie.rb | 2 ++ lib/class_variants/version.rb | 4 +++- lib/generators/class_variants/install/install_generator.rb | 2 ++ 8 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/class_variants.rb b/lib/class_variants.rb index 1b25b74..f3d1f65 100644 --- a/lib/class_variants.rb +++ b/lib/class_variants.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "class_variants/version" require "class_variants/action_view/helpers" require "class_variants/configuration" diff --git a/lib/class_variants/action_view/helpers.rb b/lib/class_variants/action_view/helpers.rb index 91f6dd4..51cae5c 100644 --- a/lib/class_variants/action_view/helpers.rb +++ b/lib/class_variants/action_view/helpers.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ClassVariants module ActionView module Helpers diff --git a/lib/class_variants/configuration.rb b/lib/class_variants/configuration.rb index 6716879..d238b6f 100644 --- a/lib/class_variants/configuration.rb +++ b/lib/class_variants/configuration.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ClassVariants class Configuration def process_classes_with(&block) diff --git a/lib/class_variants/helper.rb b/lib/class_variants/helper.rb index edd3ad7..f9da355 100644 --- a/lib/class_variants/helper.rb +++ b/lib/class_variants/helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ClassVariants module Helper module ClassMethods diff --git a/lib/class_variants/instance.rb b/lib/class_variants/instance.rb index 0d7c721..7faf975 100644 --- a/lib/class_variants/instance.rb +++ b/lib/class_variants/instance.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ClassVariants class Instance def initialize(...) diff --git a/lib/class_variants/railtie.rb b/lib/class_variants/railtie.rb index 3ff3ba3..10c6131 100644 --- a/lib/class_variants/railtie.rb +++ b/lib/class_variants/railtie.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "rails/railtie" module ClassVariants diff --git a/lib/class_variants/version.rb b/lib/class_variants/version.rb index 35d122b..4fd6eca 100644 --- a/lib/class_variants/version.rb +++ b/lib/class_variants/version.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ClassVariants - VERSION = "1.1.0".freeze + VERSION = "1.1.0" end diff --git a/lib/generators/class_variants/install/install_generator.rb b/lib/generators/class_variants/install/install_generator.rb index e5b6c5e..2a6c948 100644 --- a/lib/generators/class_variants/install/install_generator.rb +++ b/lib/generators/class_variants/install/install_generator.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ClassVariants module Generators class InstallGenerator < Rails::Generators::Base From cfce2b3ddbb80c7196ddb06ddfa452fdd433811a Mon Sep 17 00:00:00 2001 From: Joel Drapper Date: Sat, 15 Feb 2025 21:10:42 +0000 Subject: [PATCH 3/6] Use existing block variable instead of block_given? --- lib/class_variants/instance.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/class_variants/instance.rb b/lib/class_variants/instance.rb index 7faf975..7625fe8 100644 --- a/lib/class_variants/instance.rb +++ b/lib/class_variants/instance.rb @@ -19,7 +19,7 @@ def dup end def merge(**options, &block) - raise ArgumentError, "Use of hash config and code block is not supported" if !options.empty? && block_given? + raise ArgumentError, "Use of hash config and code block is not supported" if !options.empty? && block (base = options.fetch(:base, nil)) && @bases << {class: base, slot: :default} @variants += [ @@ -28,7 +28,7 @@ def merge(**options, &block) ].inject(:+) @defaults.merge!(options.fetch(:defaults, {})) - instance_eval(&block) if block_given? + instance_eval(&block) if block self end @@ -66,9 +66,9 @@ def render(slot = :default, **overrides) private def base(klass = nil, &block) - raise ArgumentError, "Use of positional argument and code block is not supported" if klass && block_given? + raise ArgumentError, "Use of positional argument and code block is not supported" if klass && block - if block_given? + if block with_slots(&block).each do |slot| @bases << slot end @@ -78,9 +78,9 @@ def base(klass = nil, &block) end def variant(**options, &block) - raise ArgumentError, "Use of class option and code block is not supported" if options.key?(:class) && block_given? + raise ArgumentError, "Use of class option and code block is not supported" if options.key?(:class) && block - if block_given? + if block with_slots(&block).each do |slot| @variants << options.merge(slot) end From 1e194ba69df9624fa7de2d9af51510720c328c4c Mon Sep 17 00:00:00 2001 From: Joel Drapper Date: Sat, 15 Feb 2025 21:11:58 +0000 Subject: [PATCH 4/6] Use `candidate.each_key` This avoids the array allocation. --- lib/class_variants/instance.rb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/class_variants/instance.rb b/lib/class_variants/instance.rb index 7625fe8..7a79687 100644 --- a/lib/class_variants/instance.rb +++ b/lib/class_variants/instance.rb @@ -48,9 +48,15 @@ def render(slot = :default, **overrides) @variants.each do |candidate| next unless candidate[:slot] == slot - if (candidate.keys - [:class, :slot]).all? { |key| criteria[key] == candidate[key] } - result << candidate[:class] + match = false + + candidate.each_key do |key| + next if key == :class || key == :slot + match = criteria[key] == candidate[key] + break unless match end + + result << candidate[:class] if match end # add the passed in classes to the result From ff198b30b19683912c6a476bbb887ed5eb78683d Mon Sep 17 00:00:00 2001 From: Joel Drapper Date: Sat, 15 Feb 2025 21:19:09 +0000 Subject: [PATCH 5/6] Create `@slots` ivar in initializer This maintains a consistent object shape. --- lib/class_variants/instance.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/class_variants/instance.rb b/lib/class_variants/instance.rb index 7a79687..c32eba3 100644 --- a/lib/class_variants/instance.rb +++ b/lib/class_variants/instance.rb @@ -6,6 +6,7 @@ def initialize(...) @bases = [] @variants = [] @defaults = {} + @slots = nil merge(...) end From 40fb446b4cc6ddbc87a7915b84609b837f1d180e Mon Sep 17 00:00:00 2001 From: Joel Drapper Date: Sat, 15 Feb 2025 21:19:27 +0000 Subject: [PATCH 6/6] =?UTF-8?q?Don=E2=80=99t=20read=20the=20`@slots`=20iva?= =?UTF-8?q?r=20twice?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/class_variants/instance.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/class_variants/instance.rb b/lib/class_variants/instance.rb index c32eba3..940c887 100644 --- a/lib/class_variants/instance.rb +++ b/lib/class_variants/instance.rb @@ -107,9 +107,10 @@ def slot(name = :default, **options) end def with_slots - @slots = [] + new_slots = [] + @slots = new_slots yield - @slots + new_slots end def expand_variants(variants)