stimulus_helpers 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dd7023b93ba3d485fbea28c5eee63938fab133d3a142d40494e0bf37b7216ab1
4
- data.tar.gz: 61bd7b0845434ceffeece2f56560207c80f220646622abf207dde1fb79434cf8
3
+ metadata.gz: 14c71e9cd468dd53e36d2ff91e05d42a05f3adc2b77a206cb54a92d3ada5b2aa
4
+ data.tar.gz: 8c74bf98bef6ea4be290669a45a27f0dd4ffdc22fa35bd77fb010aa7b0cb1c86
5
5
  SHA512:
6
- metadata.gz: 2d5a7e5abb4d4263004243f8967f9d1f04cc1b360acd68ca13359286a79928f6ce8407dc08962325d96e2bf146dece12193187bd7dcc9aa83f6bc42916723ab0
7
- data.tar.gz: 22852bd7e2403fe4acc820cd7626a22caf3ca834f310a17a9751f9c003f7d91b497ad8065b988781cdcdc77f06c127b882904c021831dfb556f5762bc665cf23
6
+ metadata.gz: 9a8089db24fa96a1791ac596b2287d0a934091c6b153fcc5714ef93f04539b615bf7aa1c3f6b362577a8cc36f93e217ffd63d2d0c4df2ff03a141ab303f1d959
7
+ data.tar.gz: e54556d56355788621c6ed9144beaa00dd20bdaa42947b27627b9495c4e294dbb2f022e7590dcb28addab75f689effb8464d38599559607e95cde44b71010293
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.1.2
1
+ 3.3.5
data/CHANGELOG.md CHANGED
@@ -0,0 +1,31 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.2.0] - 2025-01-06
11
+
12
+ ### Performance
13
+ - Optimize string operations and concatenations for large attribute sets
14
+ - Add caching for dasherized keys to avoid repeated string transformations
15
+ - Implement batch JSON serialization to reduce overhead
16
+ - Improve action building performance by replacing array operations with direct string building
17
+
18
+ ## [0.1.0] - 2024-XX-XX
19
+
20
+ ### Added
21
+ - Initial release of stimulus_helpers gem
22
+ - Helper methods for Stimulus controller attributes:
23
+ - `stimulus_controller(name)` - Controller binding
24
+ - `stimulus_action(controller, action, listener)` and `stimulus_actions(controller, actions)` - Action bindings
25
+ - `stimulus_class(controller, name, value)` and `stimulus_classes(controller, classes)` - CSS class bindings
26
+ - `stimulus_value(controller, name, value)` and `stimulus_values(controller, values)` - Value bindings
27
+ - `stimulus_target(controller, target)` - Target bindings
28
+ - `stimulus_param(controller, name, value)` and `stimulus_params(controller, params)` - Parameter bindings
29
+ - `stimulus_outlet(controller, name, value)` and `stimulus_outlets(controller, outlets)` - Outlet bindings
30
+ - Automatic JSON serialization for complex values (Arrays and Hashes)
31
+ - Automatic dasherization of attribute names following Stimulus conventions
data/CLAUDE.md ADDED
@@ -0,0 +1,137 @@
1
+ # Instructions for Claude Code
2
+
3
+ ## Project Overview
4
+
5
+ This is the `stimulus_helpers` Ruby gem - a utility library that provides helper methods for building Stimulus controller attributes in Ruby views. The gem makes it easier to work with Stimulus.js by providing a clean Ruby API for generating the necessary HTML attributes.
6
+
7
+ ## Key Information
8
+
9
+ - **Gem Name**: stimulus_helpers
10
+ - **Current Version**: 0.1.0
11
+ - **Ruby Version**: 3.1.2
12
+ - **License**: MIT
13
+ - **Author**: Tomáš Celizna
14
+
15
+ ## Project Structure
16
+
17
+ ```
18
+ stimulus_helpers/
19
+ ├── lib/
20
+ │ ├── stimulus_helpers.rb # Main module with all helper methods
21
+ │ └── stimulus_helpers/
22
+ │ └── version.rb # Version constant
23
+ ├── test/
24
+ │ ├── stimulus_helpers_test.rb # Test suite
25
+ │ └── test_helper.rb # Test configuration
26
+ ├── stimulus_helpers.gemspec # Gem specification
27
+ ├── Gemfile # Dependencies
28
+ ├── Rakefile # Build tasks
29
+ └── README.md # Documentation
30
+ ```
31
+
32
+ ## Development Workflow
33
+
34
+ ### Running Tests
35
+ ```bash
36
+ bundle exec rake test
37
+ # or simply
38
+ bundle exec rake
39
+ ```
40
+
41
+ ### Running Linter
42
+ ```bash
43
+ bundle exec rubocop
44
+ ```
45
+
46
+ ### Installing Dependencies
47
+ ```bash
48
+ bundle install
49
+ ```
50
+
51
+ ### Building the Gem
52
+ ```bash
53
+ bundle exec rake build
54
+ ```
55
+
56
+ ### Releasing a New Version
57
+ 1. Update the version number in `lib/stimulus_helpers/version.rb`
58
+ 2. Update CHANGELOG.md with the changes
59
+ 3. Commit the changes
60
+ 4. Run `bundle exec rake release`
61
+
62
+ ## Code Style Guidelines
63
+
64
+ - Follow the RuboCop configuration in `.rubocop.yml`
65
+ - Use Ruby 3.1+ syntax features (like value omission in hash literals)
66
+ - Keep methods focused and well-documented
67
+ - Maintain test coverage for all public methods
68
+
69
+ ## Helper Methods Overview
70
+
71
+ The gem provides the following helper methods:
72
+
73
+ 1. **Controller**: `stimulus_controller(name)`
74
+ 2. **Actions**: `stimulus_action(controller, action, listener)` and `stimulus_actions(controller, actions)`
75
+ 3. **Classes**: `stimulus_class(controller, name, value)` and `stimulus_classes(controller, classes)`
76
+ 4. **Values**: `stimulus_value(controller, name, value)` and `stimulus_values(controller, values)`
77
+ 5. **Target**: `stimulus_target(controller, target)`
78
+ 6. **Params**: `stimulus_param(controller, name, value)` and `stimulus_params(controller, params)`
79
+ 7. **Outlets**: `stimulus_outlet(controller, name, value)` and `stimulus_outlets(controller, outlets)`
80
+
81
+ ## Implementation Notes
82
+
83
+ - The main module uses `build_stimulus_action` and `build_stimulus_attribute` private methods to construct the attribute hashes
84
+ - Complex values (Arrays and Hashes) are automatically converted to JSON
85
+ - Attribute names are dasherized to follow Stimulus conventions
86
+ - The gem depends on ActiveSupport for string inflections
87
+
88
+ ## Testing Approach
89
+
90
+ - Tests are in `test/stimulus_helpers_test.rb`
91
+ - Each helper method has corresponding test coverage
92
+ - Tests verify the exact structure of returned hashes
93
+ - Run tests with `bundle exec rake test`
94
+
95
+ ## Common Tasks
96
+
97
+ ### Adding a New Helper Method
98
+
99
+ 1. Add the public method to `lib/stimulus_helpers.rb`
100
+ 2. Use the existing private methods (`build_stimulus_action` or `build_stimulus_attribute`) if applicable
101
+ 3. Add corresponding tests to `test/stimulus_helpers_test.rb`
102
+ 4. Update the README.md with usage examples
103
+ 5. Run tests and linter to ensure everything passes
104
+
105
+ ### Debugging
106
+
107
+ - Use `bin/console` to start an IRB session with the gem loaded
108
+ - The test suite uses Minitest - add debugging with `puts` or use a debugger gem
109
+ - Check the GitHub Actions workflow results for CI failures
110
+
111
+ ## Important Considerations
112
+
113
+ 1. **Backwards Compatibility**: This gem is used by other projects, so maintain backwards compatibility when making changes
114
+ 2. **Dependencies**: Keep dependencies minimal - currently only requires ActiveSupport
115
+ 3. **Documentation**: Update README.md when adding new features
116
+ 4. **Versioning**: Follow semantic versioning (MAJOR.MINOR.PATCH)
117
+
118
+ ## Git Workflow
119
+
120
+ - The main branch is protected
121
+ - Create feature branches for new work
122
+ - Ensure all tests pass before merging
123
+ - The GitHub Actions workflow runs on every push
124
+
125
+ ## Troubleshooting
126
+
127
+ - If tests fail locally but pass in CI, check Ruby version (should be 3.1.2)
128
+ - RuboCop violations can often be auto-fixed with `bundle exec rubocop -A`
129
+ - Bundle install issues: try `bundle update` or delete `Gemfile.lock` and reinstall
130
+
131
+ ## Future Improvements
132
+
133
+ Based on the current codebase, potential areas for enhancement:
134
+ - Add more comprehensive documentation/examples
135
+ - Consider adding type signatures (RBS file is currently minimal)
136
+ - Add more edge case testing
137
+ - Consider performance optimizations for large attribute sets
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![StimulusHelpers](https://github.com/tomasc/stimulus_helpers/actions/workflows/ruby.yml/badge.svg)](https://github.com/tomasc/stimulus_helpers/actions/workflows/ruby.yml)
4
4
 
5
- Helpers to build stimulus controller attributes for use in views and components.
5
+ Helpers to build stimulus controller attributes for use in views and controller-names.
6
6
 
7
7
  ## Installation
8
8
 
@@ -32,42 +32,68 @@ ActionView::Base.send :include, StimulusHelpers
32
32
 
33
33
  This will add the following helpers:
34
34
 
35
+ Controller:
36
+
35
37
  ```ruby
36
- stimulus_controller("component")
37
- # => { "controller" => "component" }
38
+ stimulus_controller("controller-name")
39
+ # => { "controller" => "controller-name" }
40
+ ```
38
41
 
39
- stimulus_action("component", "click", "open")
40
- # => { "action" => "click->component#open" }
42
+ Action:
41
43
 
42
- stimulus_actions("component", click: "open", blur: "close")
43
- # => { "action" => "click->component#open blur->component#close" }
44
+ ```ruby
45
+ stimulus_action("controller-name", "click", "open")
46
+ # => { "action" => "click->controller-name#open" }
47
+
48
+ stimulus_actions("controller-name", click: "open", blur: "close")
49
+ # => { "action" => "click->controller-name#open blur->controller-name#close" }
50
+ ```
44
51
 
45
- stimulus_class("component", "open", "component--open")
46
- # => { "component-open-class" => "component--open" }
52
+ Class:
47
53
 
48
- stimulus_classes("component", open: "component--open", closed: "component--closed")
49
- # => { "component-open-class" => "component--open", "component-closed-class" => "component--closed" }
54
+ ```ruby
55
+ stimulus_class("controller-name", "open", "controller-name--open")
56
+ # => { "controller-name-open-class" => "controller-name--open" }
50
57
 
51
- stimulus_value("component", "open", true)
52
- # => { "component-open-value" => "true" }
58
+ stimulus_classes("controller-name", open: "controller-name--open", closed: "controller-name--closed")
59
+ # => { "controller-name-open-class" => "controller-name--open", "controller-name-closed-class" => "controller-name--closed" }
60
+ ```
53
61
 
54
- stimulus_values("component", user: { name: "Jens" }, names: ["foo", "bar"])
55
- # => { "component-user-value" => "{\"name\":\"Jens\"}", "component-names-value" => "[\"foo\",\"bar\"]" }
62
+ Value:
56
63
 
57
- stimulus_target("component", :input)
58
- # => { "component-target" => "input" }
64
+ ```ruby
65
+ stimulus_value("controller-name", "open", true)
66
+ # => { "controller-name-open-value" => "true" }
59
67
 
60
- stimulus_param("component", "id", 123)
61
- # => { "component-id-param" => "123" }
68
+ stimulus_values("controller-name", user: { name: "Jens" }, names: ["foo", "bar"])
69
+ # => { "controller-name-user-value" => "{\"name\":\"Jens\"}", "controller-name-names-value" => "[\"foo\",\"bar\"]" }
70
+ ```
62
71
 
63
- stimulus_params("component", id: 123, name: "Jens")
64
- # => { "component-id-param" => "123", "component-name-param" => "Jens" }
72
+ Target:
65
73
 
66
- stimulus_outlet("component", "result", ".result")
67
- # => { "component-result-outlet" => ".result" }
74
+ ```ruby
75
+ stimulus_target("controller-name", :input)
76
+ # => { "controller-name-target" => "input" }
77
+ ```
78
+
79
+ Param:
80
+
81
+ ```ruby
82
+ stimulus_param("controller-name", "id", 123)
83
+ # => { "controller-name-id-param" => "123" }
84
+
85
+ stimulus_params("controller-name", id: 123, name: "Jens")
86
+ # => { "controller-name-id-param" => "123", "controller-name-name-param" => "Jens" }
87
+ ```
88
+
89
+ Outlet:
90
+
91
+ ```ruby
92
+ stimulus_outlet("controller-name", "result", ".result")
93
+ # => { "controller-name-result-outlet" => ".result" }
68
94
 
69
- stimulus_outlets("component", result: ".result", output: ".output")
70
- # => { "component-result-outlet" => ".result", "component-output-outlet" => ".output" }
95
+ stimulus_outlets("controller-name", result: ".result", output: ".output")
96
+ # => { "controller-name-result-outlet" => ".result", "controller-name-output-outlet" => ".output" }
71
97
  ```
72
98
 
73
99
  ## Development
@@ -78,4 +104,4 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
78
104
 
79
105
  ## Contributing
80
106
 
81
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/stimulus_helpers.
107
+ Bug reports and pull requests are welcome on GitHub at https://github.com/tomasc/stimulus_helpers.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module StimulusHelpers
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -5,6 +5,14 @@ require "active_support/core_ext/string/inflections"
5
5
  require "json"
6
6
 
7
7
  module StimulusHelpers
8
+ # Cache for dasherized keys to avoid repeated string operations
9
+ @dasherized_cache = {}
10
+ @cache_mutex = Mutex.new
11
+
12
+ class << self
13
+ attr_reader :dasherized_cache, :cache_mutex
14
+ end
15
+
8
16
  # @see https://blog.saeloun.com/2021/09/28/ruby-allow-value-omission-in-hash-literals
9
17
  def stimulus_controller(controller)
10
18
  { controller: }
@@ -91,19 +99,48 @@ module StimulusHelpers
91
99
 
92
100
  private
93
101
  def build_stimulus_action(controller:, actions: {})
94
- action = actions.map do |action, listeners|
95
- Array(listeners).map do |listener|
96
- "#{action}->#{controller}##{listener}"
102
+ # Use string concatenation instead of array operations for better performance
103
+ action_parts = []
104
+ actions.each do |action_name, listeners|
105
+ Array(listeners).each do |listener|
106
+ action_parts << "#{action_name}->#{controller}##{listener}"
97
107
  end
98
- end.join(" ")
99
- { action: }
108
+ end
109
+ { action: action_parts.join(" ") }
100
110
  end
101
111
 
102
112
  def build_stimulus_attribute(controller:, type: nil, attributes: {})
103
- attributes.transform_keys! { |key| "#{key}-#{type}" } if type
104
- attributes.each_with_object({}) do |(key, value), res|
105
- value = value.to_json if value.is_a?(Array) || value.is_a?(Hash)
106
- res["#{controller}-#{key.to_s.dasherize}"] = value.to_s
113
+ # Pre-process keys and batch JSON serialization for better performance
114
+ result = {}
115
+ json_values = {}
116
+
117
+ attributes.each do |key, value|
118
+ # Build the final key once
119
+ final_key = if type
120
+ "#{controller}-#{cached_dasherize("#{key}-#{type}")}"
121
+ else
122
+ "#{controller}-#{cached_dasherize(key.to_s)}"
123
+ end
124
+
125
+ # Batch JSON serialization
126
+ if value.is_a?(Array) || value.is_a?(Hash)
127
+ json_values[final_key] = value
128
+ else
129
+ result[final_key] = value.to_s
130
+ end
131
+ end
132
+
133
+ # Serialize all JSON values at once to reduce overhead
134
+ json_values.each do |key, value|
135
+ result[key] = value.to_json
136
+ end
137
+
138
+ result
139
+ end
140
+
141
+ def cached_dasherize(string)
142
+ StimulusHelpers.cache_mutex.synchronize do
143
+ StimulusHelpers.dasherized_cache[string] ||= string.dasherize
107
144
  end
108
145
  end
109
146
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stimulus_helpers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomas Celizna
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2023-03-11 00:00:00.000000000 Z
12
+ date: 2025-06-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -106,6 +106,7 @@ files:
106
106
  - ".rubocop.yml"
107
107
  - ".ruby-version"
108
108
  - CHANGELOG.md
109
+ - CLAUDE.md
109
110
  - Gemfile
110
111
  - LICENSE
111
112
  - README.md
@@ -136,7 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
136
137
  - !ruby/object:Gem::Version
137
138
  version: '0'
138
139
  requirements: []
139
- rubygems_version: 3.3.7
140
+ rubygems_version: 3.5.16
140
141
  signing_key:
141
142
  specification_version: 4
142
143
  summary: Helper methods for stimulus controllers.