plutonium 0.18.5 → 0.18.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/plutonium.js +1 -1
  3. data/app/assets/plutonium.js.map +2 -2
  4. data/app/assets/plutonium.min.js +1 -1
  5. data/app/assets/plutonium.min.js.map +2 -2
  6. data/app/views/resource/interactive_bulk_action.html.erb +1 -1
  7. data/app/views/resource/interactive_resource_action.html.erb +1 -1
  8. data/lib/generators/pu/eject/layout/layout_generator.rb +1 -2
  9. data/lib/generators/pu/eject/shell/shell_generator.rb +1 -3
  10. data/lib/generators/pu/lib/plutonium_generators/concerns/logger.rb +4 -0
  11. data/lib/generators/pu/lib/plutonium_generators/concerns/package_selector.rb +80 -0
  12. data/lib/generators/pu/lib/plutonium_generators/concerns/resource_selector.rb +48 -0
  13. data/lib/generators/pu/lib/plutonium_generators/generator.rb +2 -42
  14. data/lib/generators/pu/lib/plutonium_generators/model_generator_base.rb +1 -4
  15. data/lib/generators/pu/res/conn/conn_generator.rb +9 -21
  16. data/lib/generators/pu/res/scaffold/scaffold_generator.rb +10 -5
  17. data/lib/plutonium/resource/controller.rb +3 -3
  18. data/lib/plutonium/resource/controllers/authorizable.rb +1 -1
  19. data/lib/plutonium/resource/controllers/crud_actions.rb +17 -17
  20. data/lib/plutonium/resource/controllers/interactive_actions.rb +3 -3
  21. data/lib/plutonium/resource/controllers/presentable.rb +2 -2
  22. data/lib/plutonium/resource/record/associated_with.rb +83 -0
  23. data/lib/plutonium/resource/record/associations.rb +92 -0
  24. data/lib/plutonium/resource/record/field_names.rb +83 -0
  25. data/lib/plutonium/resource/record/labeling.rb +19 -0
  26. data/lib/plutonium/resource/record/routes.rb +66 -0
  27. data/lib/plutonium/resource/record.rb +6 -258
  28. data/lib/plutonium/ui/breadcrumbs.rb +4 -4
  29. data/lib/plutonium/ui/component/methods.rb +4 -12
  30. data/lib/plutonium/ui/form/base.rb +22 -10
  31. data/lib/plutonium/ui/form/components/secure_association.rb +112 -0
  32. data/lib/plutonium/ui/form/components/secure_polymorphic_association.rb +54 -0
  33. data/lib/plutonium/ui/form/concerns/renders_nested_resource_fields.rb +0 -1
  34. data/lib/plutonium/ui/form/theme.rb +12 -1
  35. data/lib/plutonium/ui/page/show.rb +1 -1
  36. data/lib/plutonium/ui/page_header.rb +1 -1
  37. data/lib/plutonium/version.rb +1 -1
  38. data/package-lock.json +2 -2
  39. data/package.json +1 -1
  40. data/src/js/controllers/slim_select_controller.js +3 -1
  41. metadata +11 -4
  42. data/lib/plutonium/ui/form/components/belongs_to.rb +0 -66
  43. data/lib/plutonium/ui/form/components/has_many.rb +0 -66
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ # lib/plutonium/resource/associations.rb
4
+ module Plutonium
5
+ module Resource
6
+ module Record
7
+ module Associations
8
+ extend ActiveSupport::Concern
9
+
10
+ class_methods do
11
+ def belongs_to(name, scope = nil, **options)
12
+ super
13
+ include_secure_association_methods(:belongs_to, name)
14
+ end
15
+
16
+ def has_one(name, scope = nil, **options)
17
+ super
18
+ include_secure_association_methods(:has_one, name)
19
+ end
20
+
21
+ def has_many(name, scope = nil, **options)
22
+ super
23
+ include_secure_association_methods(:has_many, name)
24
+ end
25
+
26
+ def has_and_belongs_to_many(name, scope = nil, **options)
27
+ super
28
+ include_secure_association_methods(:has_and_belongs_to_many, name)
29
+ end
30
+
31
+ private
32
+
33
+ def include_secure_association_methods(association_type, name)
34
+ mod = Module.new
35
+ mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1
36
+ extend ActiveSupport::Concern
37
+
38
+ #{generate_sgid_methods(association_type, name)}
39
+
40
+ define_singleton_method(:to_s) { "Plutonium::Resource::Record::Associations::#{association_type.to_s.camelize}(:#{name})" }
41
+ define_singleton_method(:inspect) { "Plutonium::Resource::Record::Associations::#{association_type.to_s.camelize}(:#{name})" }
42
+ RUBY
43
+ include mod
44
+ end
45
+
46
+ def generate_sgid_methods(association_type, name)
47
+ case association_type
48
+ when :belongs_to, :has_one
49
+ generate_singular_sgid_methods(name)
50
+ when :has_many, :has_and_belongs_to_many
51
+ generate_collection_sgid_methods(name)
52
+ end
53
+ end
54
+
55
+ def generate_singular_sgid_methods(name)
56
+ <<-RUBY
57
+ def #{name}_sgid
58
+ #{name}&.to_signed_global_id
59
+ end
60
+
61
+ def #{name}_sgid=(sgid)
62
+ self.#{name} = GlobalID::Locator.locate_signed(sgid)
63
+ end
64
+ RUBY
65
+ end
66
+
67
+ def generate_collection_sgid_methods(name)
68
+ <<-RUBY
69
+ def #{name.to_s.singularize}_sgids
70
+ #{name}.map(&:to_signed_global_id)
71
+ end
72
+
73
+ def #{name.to_s.singularize}_sgids=(sgids)
74
+ self.#{name} = GlobalID::Locator.locate_many_signed(sgids)
75
+ end
76
+
77
+ def add_#{name.to_s.singularize}_sgid(sgid)
78
+ record = GlobalID::Locator.locate_signed(sgid)
79
+ #{name} << record if record
80
+ end
81
+
82
+ def remove_#{name.to_s.singularize}_sgid(sgid)
83
+ record = GlobalID::Locator.locate_signed(sgid)
84
+ #{name}.delete(record) if record
85
+ end
86
+ RUBY
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ # lib/plutonium/resource/associations.rb
4
+ module Plutonium
5
+ module Resource
6
+ module Record
7
+ module FieldNames
8
+ extend ActiveSupport::Concern
9
+
10
+ class_methods do
11
+ def resource_field_names
12
+ return @resource_field_names if defined?(@resource_field_names) && !Rails.env.local?
13
+
14
+ @resource_field_names = gather_resource_field_names
15
+ end
16
+
17
+ def belongs_to_association_field_names
18
+ return @belongs_to_association_field_names if defined?(@belongs_to_association_field_names) && !Rails.env.local?
19
+
20
+ @belongs_to_association_field_names = reflect_on_all_associations(:belongs_to).map(&:name)
21
+ end
22
+
23
+ def has_one_association_field_names
24
+ return @has_one_association_field_names if defined?(@has_one_association_field_names) && !Rails.env.local?
25
+
26
+ @has_one_association_field_names = reflect_on_all_associations(:has_one)
27
+ .map { |assoc| (!/_attachment$|_blob$/.match?(assoc.name)) ? assoc.name : nil }
28
+ .compact
29
+ end
30
+
31
+ def has_many_association_field_names
32
+ return @has_many_association_field_names if defined?(@has_many_association_field_names) && !Rails.env.local?
33
+
34
+ @has_many_association_field_names = reflect_on_all_associations(:has_many)
35
+ .map { |assoc| (!/_attachments$|_blobs$/.match?(assoc.name)) ? assoc.name : nil }
36
+ .compact
37
+ end
38
+
39
+ def has_one_attached_field_names
40
+ return @has_one_attached_field_names if defined?(@has_one_attached_field_names) && !Rails.env.local?
41
+
42
+ @has_one_attached_field_names = if respond_to?(:reflect_on_all_attachments)
43
+ reflect_on_all_attachments
44
+ .select { |a| a.macro == :has_one_attached }
45
+ .map(&:name)
46
+ else
47
+ []
48
+ end
49
+ end
50
+
51
+ def has_many_attached_field_names
52
+ return @has_many_attached_field_names if defined?(@has_many_attached_field_names) && !Rails.env.local?
53
+
54
+ @has_many_attached_field_names = if respond_to?(:reflect_on_all_attachments)
55
+ reflect_on_all_attachments
56
+ .select { |a| a.macro == :has_many_attached }
57
+ .map(&:name)
58
+ else
59
+ []
60
+ end
61
+ end
62
+
63
+ def content_column_field_names
64
+ return @content_column_field_names if defined?(@content_column_field_names) && !Rails.env.local?
65
+
66
+ @content_column_field_names = content_columns.map { |col| col.name.to_sym }
67
+ end
68
+
69
+ private
70
+
71
+ def gather_resource_field_names
72
+ belongs_to_association_field_names +
73
+ has_one_attached_field_names +
74
+ has_one_association_field_names +
75
+ has_many_attached_field_names +
76
+ has_many_association_field_names +
77
+ content_column_field_names
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # lib/plutonium/resource/associations.rb
4
+ module Plutonium
5
+ module Resource
6
+ module Record
7
+ module Labeling
8
+ def to_label
9
+ %i[name title].each do |method|
10
+ name = send(method) if respond_to?(method)
11
+ return name if name.present?
12
+ end
13
+
14
+ "#{model_name.human} ##{to_param}"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ # lib/plutonium/resource/associations.rb
4
+ module Plutonium
5
+ module Resource
6
+ module Record
7
+ module Routes
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ scope :from_path_param, ->(param) { where(id: param) }
12
+ end
13
+
14
+ class_methods do
15
+ def has_many_association_routes
16
+ return @has_many_association_routes if defined?(@has_many_association_routes) && !Rails.env.local?
17
+
18
+ @has_many_association_routes = reflect_on_all_associations(:has_many).map { |assoc| assoc.klass.model_name.plural }
19
+ end
20
+
21
+ def all_nested_attributes_options
22
+ unless Rails.env.local?
23
+ return @all_nested_attributes_options if defined?(@all_nested_attributes_options)
24
+ end
25
+
26
+ @all_nested_attributes_options = reflect_on_all_associations.map do |association|
27
+ setter_method = "#{association.name}_attributes="
28
+ if method_defined?(setter_method)
29
+ [association.name, nested_attributes_options[association.name].merge(
30
+ macro: association.macro,
31
+ class: association.polymorphic? ? nil : association.klass
32
+ )]
33
+ end
34
+ end.compact.to_h
35
+ end
36
+
37
+ private
38
+
39
+ def path_parameter(param_name)
40
+ param_name = param_name.to_sym
41
+
42
+ scope :from_path_param, ->(param) { where(param_name => param) }
43
+
44
+ define_method :to_param do
45
+ return nil unless persisted?
46
+
47
+ send(param_name)
48
+ end
49
+ end
50
+
51
+ def dynamic_path_parameter(param_name)
52
+ param_name = param_name.to_sym
53
+
54
+ scope :from_path_param, ->(param) { where(id: param.split("-").first) }
55
+
56
+ define_method :to_param do
57
+ return nil unless persisted?
58
+
59
+ "#{id}-#{send(param_name)}".parameterize
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -2,265 +2,13 @@ module Plutonium
2
2
  module Resource
3
3
  module Record
4
4
  extend ActiveSupport::Concern
5
- include Plutonium::Models::HasCents
6
-
7
- included do
8
- scope :from_path_param, ->(param) { where(id: param) }
9
-
10
- scope :associated_with, ->(record) do
11
- named_scope = :"associated_with_#{record.model_name.singular}"
12
- return send(named_scope, record) if respond_to?(named_scope)
13
-
14
- # TODO: add support for polymorphic associations
15
- # TODO: add logging
16
- # TODO: memoize this
17
-
18
- own_association = klass.find_association_from_self_to_record(record)
19
- if own_association
20
- return klass.query_based_on_association(own_association, record)
21
- end
22
-
23
- record_association = klass.find_association_to_self_from_record(record)
24
- if record_association
25
- # TODO: add a warning here about a potentially poor performing query
26
- return where(id: record.public_send(record_association.name))
27
- end
28
-
29
- klass.raise_association_error(record, named_scope)
30
- end
31
- end
32
-
33
- class_methods do
34
- # Returns the resource field names
35
- # @return [Array<Symbol>]
36
- def resource_field_names
37
- return @resource_field_names if defined?(@resource_field_names) && !Rails.env.local?
38
-
39
- @resource_field_names = gather_resource_field_names
40
- end
41
-
42
- # Overrides belongs_to to add support for polymorphic associations
43
- # @param [Symbol] name The name of the association
44
- # @param [Proc] scope The scope for the association
45
- # @param [Hash] options The options for the association
46
- def belongs_to(name, scope = nil, **options)
47
- super
48
-
49
- return unless options[:polymorphic]
50
-
51
- mod = Module.new
52
- mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1
53
- extend ActiveSupport::Concern
54
-
55
- def #{name}_sgid
56
- #{name}&.to_signed_global_id
57
- end
58
-
59
- def #{name}_sgid=(sgid)
60
- self.#{name} = GlobalID::Locator.locate_signed(sgid)
61
- end
62
-
63
- define_singleton_method(:to_s) { "Plutonium::Polymorphic::BelongsTo(:#{name})" }
64
- define_singleton_method(:inspect) { "Plutonium::Polymorphic::BelongsTo(:#{name})" }
65
- RUBY
66
- include mod
67
- end
68
-
69
- # Returns the names of belongs_to associations
70
- # @return [Array<Symbol>]
71
- def belongs_to_association_field_names
72
- return @belongs_to_association_field_names if defined?(@belongs_to_association_field_names) && !Rails.env.local?
73
-
74
- @belongs_to_association_field_names = reflect_on_all_associations(:belongs_to).map(&:name)
75
- end
76
-
77
- # Returns the names of has_one associations
78
- # @return [Array<Symbol>]
79
- def has_one_association_field_names
80
- return @has_one_association_field_names if defined?(@has_one_association_field_names) && !Rails.env.local?
81
-
82
- @has_one_association_field_names = reflect_on_all_associations(:has_one)
83
- .map { |assoc| (!/_attachment$|_blob$/.match?(assoc.name)) ? assoc.name : nil }
84
- .compact
85
- end
86
-
87
- # Returns the names of has_many associations
88
- # @return [Array<Symbol>]
89
- def has_many_association_field_names
90
- return @has_many_association_field_names if defined?(@has_many_association_field_names) && !Rails.env.local?
91
-
92
- @has_many_association_field_names = reflect_on_all_associations(:has_many)
93
- .map { |assoc| (!/_attachments$|_blobs$/.match?(assoc.name)) ? assoc.name : nil }
94
- .compact
95
- end
96
-
97
- # Returns the names of has_one attached associations
98
- # @return [Array<Symbol>]
99
- def has_one_attached_field_names
100
- return @has_one_attached_field_names if defined?(@has_one_attached_field_names) && !Rails.env.local?
101
-
102
- @has_one_attached_field_names = if respond_to?(:reflect_on_all_attachments)
103
- reflect_on_all_attachments
104
- .select { |a| a.macro == :has_one_attached }
105
- .map(&:name)
106
- else
107
- []
108
- end
109
- end
110
-
111
- # Returns the names of has_many attached associations
112
- # @return [Array<Symbol>]
113
- def has_many_attached_field_names
114
- return @has_many_attached_field_names if defined?(@has_many_attached_field_names) && !Rails.env.local?
115
5
 
116
- @has_many_attached_field_names = if respond_to?(:reflect_on_all_attachments)
117
- reflect_on_all_attachments
118
- .select { |a| a.macro == :has_many_attached }
119
- .map(&:name)
120
- else
121
- []
122
- end
123
- end
124
-
125
- # Returns the names of content columns
126
- # @return [Array<Symbol>]
127
- def content_column_field_names
128
- return @content_column_field_names if defined?(@content_column_field_names) && !Rails.env.local?
129
-
130
- @content_column_field_names = content_columns.map { |col| col.name.to_sym }
131
- end
132
-
133
- # Returns the routes for has_many associations
134
- # @return [Array<Symbol>]
135
- def has_many_association_routes
136
- return @has_many_association_routes if defined?(@has_many_association_routes) && !Rails.env.local?
137
-
138
- @has_many_association_routes = reflect_on_all_associations(:has_many).map { |assoc| assoc.klass.model_name.plural }
139
- end
140
-
141
- # Returns all nested attributes options
142
- # @return [Hash]
143
- def all_nested_attributes_options
144
- unless Rails.env.local?
145
- return @all_nested_attributes_options if defined?(@all_nested_attributes_options)
146
- end
147
-
148
- @all_nested_attributes_options = reflect_on_all_associations.map do |association|
149
- setter_method = "#{association.name}_attributes="
150
- if method_defined?(setter_method)
151
- [association.name, nested_attributes_options[association.name].merge(
152
- macro: association.macro,
153
- class: association.polymorphic? ? nil : association.klass
154
- )]
155
- end
156
- end.compact.to_h
157
- end
158
-
159
- # Finds the association to the given record
160
- # @param [ActiveRecord::Base] record The record to find the association with
161
- # @return [ActiveRecord::Reflection::AssociationReflection, nil]
162
- def find_association_from_self_to_record(record)
163
- reflect_on_all_associations.find do |assoc|
164
- assoc.klass.name == record.class.name unless assoc.polymorphic?
165
- rescue
166
- assoc.check_validity!
167
- raise
168
- end
169
- end
170
-
171
- # Finds the association to self in the given record
172
- # @param [ActiveRecord::Base] record The record to find the association with
173
- # @return [ActiveRecord::Reflection::AssociationReflection, nil]
174
- def find_association_to_self_from_record(record)
175
- record.class.reflect_on_all_associations.find do |assoc|
176
- assoc.klass.name == name
177
- rescue
178
- assoc.check_validity!
179
- raise
180
- end
181
- end
182
-
183
- # Queries based on the association type
184
- # @param [ActiveRecord::Reflection::AssociationReflection] assoc The association
185
- # @param [ActiveRecord::Base] record The record to query with
186
- # @return [ActiveRecord::Relation]
187
- def query_based_on_association(assoc, record)
188
- case assoc.macro
189
- when :has_one
190
- joins(assoc.name).where(assoc.name => {record.class.primary_key => record.id})
191
- when :belongs_to
192
- where(assoc.name => record)
193
- when :has_many
194
- joins(assoc.name).where(assoc.klass.table_name => record)
195
- else
196
- raise NotImplementedError, "associated_with->##{assoc.macro}"
197
- end
198
- end
199
-
200
- # Raises an error for unresolved associations
201
- # @param [ActiveRecord::Base] record The record with unresolved association
202
- # @param [Symbol] named_scope The named scope
203
- # @raise [RuntimeError]
204
- def raise_association_error(record, named_scope)
205
- raise "Could not resolve the association between '#{name}' and '#{record.class.name}'\n\n" \
206
- "Define\n" \
207
- " 1. the associations between the models\n" \
208
- " 2. a named scope on #{name} e.g.\n\n" \
209
- "scope :#{named_scope}, ->(#{record.model_name.singular}) { do_something_here }"
210
- end
211
-
212
- private
213
-
214
- # Defines a scope and method for path parameters
215
- # @param [Symbol] param_name The name of the parameter
216
- def path_parameter(param_name)
217
- param_name = param_name.to_sym
218
-
219
- scope :from_path_param, ->(param) { where(param_name => param) }
220
-
221
- define_method :to_param do
222
- return nil unless persisted?
223
-
224
- send(param_name)
225
- end
226
- end
227
-
228
- # Defines a scope and method for dynamic path parameters
229
- # @param [Symbol] param_name The name of the parameter
230
- def dynamic_path_parameter(param_name)
231
- param_name = param_name.to_sym
232
-
233
- scope :from_path_param, ->(param) { where(id: param.split("-").first) }
234
-
235
- define_method :to_param do
236
- return nil unless persisted?
237
-
238
- "#{id}-#{send(param_name)}".parameterize
239
- end
240
- end
241
-
242
- # Gathers all resource field names
243
- # @return [Array<Symbol>]
244
- def gather_resource_field_names
245
- belongs_to_association_field_names +
246
- has_one_attached_field_names +
247
- has_one_association_field_names +
248
- has_many_attached_field_names +
249
- has_many_association_field_names +
250
- content_column_field_names
251
- end
252
- end
253
-
254
- # Returns a label for the record
255
- # @return [String]
256
- def to_label
257
- %i[name title].each do |method|
258
- name = send(method) if respond_to?(method)
259
- return name if name.present?
260
- end
261
-
262
- "#{model_name.human} ##{to_param}"
263
- end
6
+ include Plutonium::Models::HasCents
7
+ include Plutonium::Resource::Record::Routes
8
+ include Plutonium::Resource::Record::Labeling
9
+ include Plutonium::Resource::Record::FieldNames
10
+ include Plutonium::Resource::Record::Associations
11
+ include Plutonium::Resource::Record::AssociatedWith
264
12
  end
265
13
  end
266
14
  end
@@ -87,7 +87,7 @@ module Plutonium
87
87
  end
88
88
 
89
89
  # Record
90
- if resource_record.present?
90
+ if resource_record?
91
91
  # Record Resource
92
92
  li(class: "flex items-center") do
93
93
  svg(
@@ -112,7 +112,7 @@ module Plutonium
112
112
  end
113
113
 
114
114
  # Record Itself
115
- if resource_record.persisted? && action_name != "show"
115
+ if resource_record!.persisted? && action_name != "show"
116
116
  li(class: "flex items-center") do
117
117
  svg(
118
118
  class: "rtl:rotate-180 block w-3 h-3 mx-1 text-gray-400",
@@ -129,8 +129,8 @@ module Plutonium
129
129
  d: "m1 9 4-4-4-4"
130
130
  )
131
131
  end
132
- link_to display_name_of(resource_record),
133
- resource_url_for(resource_record),
132
+ link_to display_name_of(resource_record!),
133
+ resource_url_for(resource_record!),
134
134
  class:
135
135
  "ms-1 text-sm font-medium text-gray-700 hover:text-primary-600 md:ms-2 dark:text-gray-200 dark:hover:text-white"
136
136
  end
@@ -10,18 +10,6 @@ module Plutonium
10
10
 
11
11
  private
12
12
 
13
- def resource_class
14
- helpers.controller.send(:resource_class)
15
- end
16
-
17
- def resource_record
18
- helpers.controller.send(:resource_record)
19
- end
20
-
21
- def current_parent
22
- helpers.controller.send(:current_parent)
23
- end
24
-
25
13
  def params
26
14
  helpers.controller.params
27
15
  end
@@ -35,11 +23,15 @@ module Plutonium
35
23
  end
36
24
 
37
25
  delegate \
26
+ :resource_class,
27
+ :resource_record!,
28
+ :resource_record?,
38
29
  :resource_name,
39
30
  :resource_name_plural,
40
31
  :display_name_of,
41
32
  :resource_url_for,
42
33
  :current_user,
34
+ :current_parent,
43
35
  :current_definition,
44
36
  :current_query_object,
45
37
  :raw_resource_query_params,
@@ -19,16 +19,6 @@ module Plutonium
19
19
  select_tag(**attributes, class!: "", &)
20
20
  end
21
21
 
22
- def belongs_to_tag(**attributes, &)
23
- attributes[:data_controller] = tokens(attributes[:data_controller], "slim-select") # TODO: put this behind a config
24
- create_component(Components::BelongsTo, :belongs_to, **attributes, &)
25
- end
26
-
27
- def has_many_tag(**attributes, &)
28
- attributes[:data_controller] = tokens(attributes[:data_controller], "slim-select") # TODO: put this behind a config
29
- create_component(Components::HasMany, :has_many, **attributes, &)
30
- end
31
-
32
22
  def flatpickr_tag(**, &)
33
23
  create_component(Components::Flatpickr, :flatpickr, **, &)
34
24
  end
@@ -42,6 +32,28 @@ module Plutonium
42
32
  create_component(Components::Uppy, :uppy, **, &)
43
33
  end
44
34
  alias_method :file_tag, :uppy_tag
35
+
36
+ def secure_association_tag(**attributes, &)
37
+ attributes[:data_controller] = tokens(attributes[:data_controller], "slim-select") # TODO: put this behind a config
38
+ create_component(Components::SecureAssociation, :association, **attributes, &)
39
+ end
40
+ # preserve original methods with prefix
41
+ alias_method :basic_belongs_to_tag, :belongs_to_tag
42
+ alias_method :basic_has_many_tag, :has_many_tag
43
+ alias_method :basic_has_one_tag, :has_one_tag
44
+ # use new methods as defaults
45
+ alias_method :belongs_to_tag, :secure_association_tag
46
+ alias_method :has_many_tag, :secure_association_tag
47
+ alias_method :has_one_tag, :secure_association_tag
48
+
49
+ def secure_polymorphic_association_tag(**attributes, &)
50
+ attributes[:data_controller] = tokens(attributes[:data_controller], "slim-select") # TODO: put this behind a config
51
+ create_component(Components::SecurePolymorphicAssociation, :polymorphic_association, **attributes, &)
52
+ end
53
+ # preserve original methods with prefix
54
+ alias_method :basic_polymorphic_belongs_to_tag, :polymorphic_belongs_to_tag
55
+ # use new methods as defaults
56
+ alias_method :polymorphic_belongs_to_tag, :secure_polymorphic_association_tag
45
57
  end
46
58
 
47
59
  private