Module: StimulusTagHelper

Defined in:
lib/stimulus_tag_helper.rb,
lib/stimulus_tag_helper/version.rb,
lib/stimulus_tag_helper/stimulus_action.rb,
lib/stimulus_tag_helper/stimulus_controller_builder.rb

Defined Under Namespace

Classes: StimulusAction, StimulusControllerBuilder

Constant Summary collapse

TAG_BUILDER_OPTIMIZED_VERION =
Gem::Version.new("7.2.0")
VERSION =
"0.4.1"

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.aliasesObject



13
14
15
16
17
18
19
20
21
# File 'lib/stimulus_tag_helper.rb', line 13

def self.aliases
  @aliases ||= {}.tap do |aliases|
    properties.each do |property|
      property_alias = property.to_s.singularize.to_sym
      aliases[property] = property_alias
      aliases[property_alias] = property
    end
  end.freeze
end

.all_possible_properties_namesObject



23
24
25
# File 'lib/stimulus_tag_helper.rb', line 23

def self.all_possible_properties_names
  @all_possible_properties_names ||= aliases.keys
end

.attribute_method_name_for(property) ⇒ Object



32
33
34
35
# File 'lib/stimulus_tag_helper.rb', line 32

def self.attribute_method_name_for(property)
  property = aliases[property] if properties.exclude?(property)
  "#{property}_#{rendered_as(property) == :one ? "attribute" : "attributes"}"
end

.prevent_duplicates(properties_set, name) ⇒ Object

Raises:

  • (ArgumentError)


42
43
44
45
46
47
48
49
# File 'lib/stimulus_tag_helper.rb', line 42

def self.prevent_duplicates(properties_set, name)
  alias_name = StimulusTagHelper.aliases[name]
  return unless alias_name && (properties_set[alias_name])

  raise(ArgumentError, <<~STRING)
    "#{name} and #{alias_name} should not be passed at the same time"
  STRING
end

.propertiesObject



9
10
11
# File 'lib/stimulus_tag_helper.rb', line 9

def self.properties
  %i[controllers values classes targets actions outlets].freeze
end

.property_method_name_for(property) ⇒ Object



27
28
29
30
# File 'lib/stimulus_tag_helper.rb', line 27

def self.property_method_name_for(property)
  property = aliases[property] if properties.exclude?(property)
  "#{property}_#{rendered_as(property) == :one ? "property" : "properties"}"
end

.rendered_as(property) ⇒ Object



37
38
39
40
# File 'lib/stimulus_tag_helper.rb', line 37

def self.rendered_as(property)
  {controllers: :one, values: :many, classes: :many, targets: :many, actions: :one, outlets: :many} \
    [property] || raise(ArgumentError, "Unknown property: #{property.inspect}")
end

Instance Method Details

#stimulus_action_value(identifier, args_or_string) ⇒ Object

:nodoc:



167
168
169
170
171
172
173
# File 'lib/stimulus_tag_helper.rb', line 167

def stimulus_action_value(identifier, args_or_string) # :nodoc:
  return StimulusAction.parse(args_or_string, identifier: identifier) if args_or_string.is_a?(String)

  # WARNING: this is unsafe for public use by unexpired developers.
  # TODO: find a elegant way to escape -> splitter escaping &gt; back and forth.
  StimulusAction.new(identifier: identifier, **args_or_string).to_s.html_safe
end

#stimulus_actions_attributeObject Also known as: stimulus_action_attribute



161
162
163
# File 'lib/stimulus_tag_helper.rb', line 161

def stimulus_actions_attribute(...)
  {data: stimulus_actions_property(...)}
end

#stimulus_actions_property(identifier, *actions_params) ⇒ Object Also known as: stimulus_action_property



153
154
155
156
157
# File 'lib/stimulus_tag_helper.rb', line 153

def stimulus_actions_property(identifier, *actions_params)
  {
    action: actions_params.flatten.map { |action_params| stimulus_action_value(identifier, action_params) }.join(" ").html_safe
  }
end

#stimulus_attributesObject Also known as: stimulus_attribute



75
76
77
# File 'lib/stimulus_tag_helper.rb', line 75

def stimulus_attributes(...)
  {data: stimulus_properties(...)}
end

#stimulus_classes_attributesObject Also known as: stimulus_class_attribute



125
126
127
# File 'lib/stimulus_tag_helper.rb', line 125

def stimulus_classes_attributes(...)
  {data: stimulus_classes_properties(...)}
end

#stimulus_classes_properties(identifier, **classes) ⇒ Object Also known as: stimulus_class_property



131
132
133
134
135
136
137
# File 'lib/stimulus_tag_helper.rb', line 131

def stimulus_classes_properties(identifier, **classes)
  {}.tap do |properties|
    classes.each_pair do |name, value|
      properties["#{identifier}-#{name}-class"] = value
    end
  end
end

#stimulus_controller(identifier, tag: nil, **options, &block) ⇒ Object



51
52
53
54
55
# File 'lib/stimulus_tag_helper.rb', line 51

def stimulus_controller(identifier, tag: nil, **options, &block)
  builder = StimulusControllerBuilder.new(identifier: identifier, tag: tag, template: self, **options)
  return builder unless block
  builder.capture(&block)
end

#stimulus_controller_tag(identifier, tag:, data: {}, controller: nil, **args, &block) ⇒ Object

controller arg is used to add additional stimulus controllers to the element



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/stimulus_tag_helper.rb', line 58

def stimulus_controller_tag(identifier, tag:, data: {}, controller: nil, **args, &block)
  # class class interpreted as class attribute, not a stimulus class
  # what about value and action action? maybe here should be warning

  # maybe data should be merged in args?
  data.merge!(stimulus_properties(
    identifier,
    controller: data[:controller] || controller, # nil is allowed, because the args will be prepended by the identifier
    **args.extract!(*StimulusTagHelper.all_possible_properties_names - %i[class])
  ))
  if ActionView.version >= TAG_BUILDER_OPTIMIZED_VERION
    tag_builder.tag_string(tag, nil, args.merge(data: data), &block)
  else
    tag_builder.tag_string(tag, **args.merge(data: data), &block)
  end
end

#stimulus_controllers_attributeObject Also known as: stimulus_controller_attribute



97
98
99
# File 'lib/stimulus_tag_helper.rb', line 97

def stimulus_controllers_attribute(...)
  {data: stimulus_controllers_property(...)}
end

#stimulus_controllers_property(*identifiers) ⇒ Object Also known as: stimulus_controller_property



103
104
105
# File 'lib/stimulus_tag_helper.rb', line 103

def stimulus_controllers_property(*identifiers)
  {controller: identifiers.flatten.compact.uniq.join(" ")}
end

#stimulus_outlets_attributesObject Also known as: stimulus_outlet_attribute



175
176
177
# File 'lib/stimulus_tag_helper.rb', line 175

def stimulus_outlets_attributes(...)
  {data: stimulus_outlets_properties(...)}
end

#stimulus_outlets_properties(identifier, **outlets) ⇒ Object Also known as: stimulus_outlet_property



181
182
183
184
185
186
187
# File 'lib/stimulus_tag_helper.rb', line 181

def stimulus_outlets_properties(identifier, **outlets)
  {}.tap do |properties|
    outlets.each_pair do |name, selector|
      properties["#{identifier}-#{name}-outlet"] = selector
    end
  end
end

#stimulus_properties(identifier, **props) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/stimulus_tag_helper.rb', line 81

def stimulus_properties(identifier, **props)
  props = props.symbolize_keys
  {}.tap do |data|
    StimulusTagHelper.all_possible_properties_names.each do |name|
      next unless props.key?(name)

      args = Array.wrap(props[name]).unshift(identifier)
      kwargs = args.last.is_a?(Hash) ? args.pop : {}
      StimulusTagHelper.prevent_duplicates(props, name)
      data.merge!(
        public_send("stimulus_#{StimulusTagHelper.property_method_name_for(name)}", *args, **kwargs)
      )
    end
  end
end

#stimulus_targets_attributesObject Also known as: stimulus_target_attribute



141
142
143
# File 'lib/stimulus_tag_helper.rb', line 141

def stimulus_targets_attributes(...)
  {data: stimulus_targets_properties(...)}
end

#stimulus_targets_properties(identifier, *targets) ⇒ Object Also known as: stimulus_target_property



147
148
149
# File 'lib/stimulus_tag_helper.rb', line 147

def stimulus_targets_properties(identifier, *targets)
  {"#{identifier}-target" => targets.join(" ")}
end

#stimulus_values_attributesObject Also known as: stimulus_value_attribute



109
110
111
# File 'lib/stimulus_tag_helper.rb', line 109

def stimulus_values_attributes(...)
  {data: stimulus_values_properties(...)}
end

#stimulus_values_properties(identifier, **values) ⇒ Object Also known as: stimulus_value_property



115
116
117
118
119
120
121
# File 'lib/stimulus_tag_helper.rb', line 115

def stimulus_values_properties(identifier, **values)
  {}.tap do |properties|
    values.each_pair do |name, value|
      properties["#{identifier}-#{name}-value"] = value
    end
  end
end