compony 0.5.3 → 0.5.5

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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/CHANGELOG.md +11 -0
  4. data/Gemfile.lock +6 -6
  5. data/README.md +36 -0
  6. data/VERSION +1 -1
  7. data/app/controllers/compony_controller.rb +4 -0
  8. data/compony.gemspec +4 -4
  9. data/doc/ComponentGenerator.html +1 -1
  10. data/doc/Components.html +1 -1
  11. data/doc/ComponentsGenerator.html +1 -1
  12. data/doc/Compony/Component.html +1 -1
  13. data/doc/Compony/ComponentMixins/Default/Labelling.html +1 -1
  14. data/doc/Compony/ComponentMixins/Default/Standalone/ResourcefulVerbDsl.html +1 -1
  15. data/doc/Compony/ComponentMixins/Default/Standalone/StandaloneDsl.html +96 -27
  16. data/doc/Compony/ComponentMixins/Default/Standalone/VerbDsl.html +1 -1
  17. data/doc/Compony/ComponentMixins/Default/Standalone.html +1 -1
  18. data/doc/Compony/ComponentMixins/Default.html +1 -1
  19. data/doc/Compony/ComponentMixins/Resourceful.html +1 -1
  20. data/doc/Compony/ComponentMixins.html +1 -1
  21. data/doc/Compony/Components/Button.html +1 -1
  22. data/doc/Compony/Components/Destroy.html +1 -1
  23. data/doc/Compony/Components/Edit.html +1 -1
  24. data/doc/Compony/Components/Form.html +210 -127
  25. data/doc/Compony/Components/New.html +1 -1
  26. data/doc/Compony/Components/WithForm.html +1 -1
  27. data/doc/Compony/Components.html +1 -1
  28. data/doc/Compony/ControllerMixin.html +1 -1
  29. data/doc/Compony/Engine.html +1 -1
  30. data/doc/Compony/MethodAccessibleHash.html +1 -1
  31. data/doc/Compony/ModelFields/Anchormodel.html +1 -1
  32. data/doc/Compony/ModelFields/Association.html +1 -1
  33. data/doc/Compony/ModelFields/Attachment.html +1 -1
  34. data/doc/Compony/ModelFields/Base.html +1 -1
  35. data/doc/Compony/ModelFields/Boolean.html +1 -1
  36. data/doc/Compony/ModelFields/Color.html +1 -1
  37. data/doc/Compony/ModelFields/Currency.html +1 -1
  38. data/doc/Compony/ModelFields/Date.html +1 -1
  39. data/doc/Compony/ModelFields/Datetime.html +1 -1
  40. data/doc/Compony/ModelFields/Decimal.html +1 -1
  41. data/doc/Compony/ModelFields/Email.html +1 -1
  42. data/doc/Compony/ModelFields/Float.html +1 -1
  43. data/doc/Compony/ModelFields/Integer.html +1 -1
  44. data/doc/Compony/ModelFields/Percentage.html +1 -1
  45. data/doc/Compony/ModelFields/Phone.html +1 -1
  46. data/doc/Compony/ModelFields/RichText.html +1 -1
  47. data/doc/Compony/ModelFields/String.html +1 -1
  48. data/doc/Compony/ModelFields/Text.html +1 -1
  49. data/doc/Compony/ModelFields/Time.html +1 -1
  50. data/doc/Compony/ModelFields/Url.html +1 -1
  51. data/doc/Compony/ModelFields.html +1 -1
  52. data/doc/Compony/ModelMixin.html +29 -29
  53. data/doc/Compony/NaturalOrdering.html +1 -1
  54. data/doc/Compony/RequestContext.html +1 -1
  55. data/doc/Compony/Version.html +1 -1
  56. data/doc/Compony/ViewHelpers.html +1 -1
  57. data/doc/Compony.html +3 -3
  58. data/doc/ComponyController.html +1 -1
  59. data/doc/_index.html +1 -1
  60. data/doc/file.README.html +42 -7
  61. data/doc/index.html +42 -7
  62. data/doc/method_list.html +112 -96
  63. data/doc/top-level-namespace.html +1 -1
  64. data/lib/compony/component_mixins/default/standalone/standalone_dsl.rb +18 -10
  65. data/lib/compony/components/form.rb +49 -32
  66. data/lib/compony/model_mixin.rb +24 -14
  67. data/lib/compony.rb +2 -2
  68. metadata +3 -9
@@ -102,7 +102,7 @@
102
102
  </div>
103
103
 
104
104
  <div id="footer">
105
- Generated on Fri Dec 20 13:46:32 2024 by
105
+ Generated on Mon Apr 7 13:00:52 2025 by
106
106
  <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
107
107
  0.9.37 (ruby-3.3.5).
108
108
  </div>
@@ -17,6 +17,7 @@ module Compony
17
17
  @scope_args = scope_args
18
18
  @verbs = {}
19
19
  @skip_authentication = false
20
+ @skip_forgery_protection = false
20
21
  @layout = true # can be overriden by false or a string
21
22
  end
22
23
 
@@ -25,16 +26,17 @@ module Compony
25
26
  evaluate(&block)
26
27
  @component = block.binding.eval('self') # Fetches the component holding this DSL call (via the block)
27
28
  return {
28
- name: @name,
29
- path: @path,
30
- constraints: @constraints,
31
- scope: @scope,
32
- scope_args: @scope_args,
33
- verbs: @verbs,
34
- rails_action_name: Compony.rails_action_name(comp_name, family_name, @name),
35
- path_helper_name: Compony.path_helper_name(comp_name, family_name, @name),
36
- skip_authentication: @skip_authentication,
37
- layout: @layout
29
+ name: @name,
30
+ path: @path,
31
+ constraints: @constraints,
32
+ scope: @scope,
33
+ scope_args: @scope_args,
34
+ verbs: @verbs,
35
+ rails_action_name: Compony.rails_action_name(comp_name, family_name, @name),
36
+ path_helper_name: Compony.path_helper_name(comp_name, family_name, @name),
37
+ skip_authentication: @skip_authentication,
38
+ skip_forgery_protection: @skip_forgery_protection,
39
+ layout: @layout
38
40
  }.compact
39
41
  end
40
42
 
@@ -65,6 +67,12 @@ module Compony
65
67
  @skip_authentication = true
66
68
  end
67
69
 
70
+ # DSL
71
+ # Defines that for this component, no forgery protection (CSRF) should be performed.
72
+ def skip_forgery_protection!
73
+ @skip_forgery_protection = true
74
+ end
75
+
68
76
  # DSL
69
77
  # Speficies the Rails layout (under `app/views/layouts`) that should be used to render this component.
70
78
  # Defaults to Rails' default (`layouts/application`) if the method is never called.
@@ -36,7 +36,8 @@ module Compony
36
36
  end
37
37
 
38
38
  content do
39
- form_html = simple_form_for(data, method: @comp_opts[:submit_verb], url: @submit_path) do |f|
39
+ form_params = { method: @comp_opts[:submit_verb], url: @submit_path }.merge(@form_params || {})
40
+ form_html = simple_form_for(data, **form_params) do |f|
40
41
  component.with_simpleform(f, controller) do
41
42
  instance_exec(&form_fields)
42
43
  div class: 'compony-form-buttons' do
@@ -95,32 +96,38 @@ module Compony
95
96
 
96
97
  # Called inside the form_fields block. This makes the method `field` available in the block.
97
98
  # See also notes for `with_simpleform`.
98
- def field(name, **input_opts)
99
+ # If multilang is true, a suffixed field is generated for every available locale (useful with gem "mobility"). Render the array as you wish.
100
+ def field(name, multilang: false, **input_opts)
99
101
  fail("The `field` method may only be called inside `form_fields` for #{inspect}.") unless @simpleform
100
- name = name.to_sym
101
102
 
102
- input_opts.merge!(disabled: true) if @form_disabled
103
+ if multilang
104
+ I18n.available_locales.map { |locale| field("#{name}_#{locale}", **input_opts) }
105
+ else
106
+ name = name.to_sym
103
107
 
104
- # Check per-field authorization
105
- if @cancancan_action.present? && @controller.current_ability.permitted_attributes(@cancancan_action, @simpleform.object).exclude?(name)
106
- Rails.logger.debug do
107
- "Skipping form field #{name.inspect} because the current user is not allowed to perform #{@cancancan_action.inspect} on #{@simpleform.object}."
108
+ input_opts.merge!(disabled: true) if @form_disabled
109
+
110
+ # Check per-field authorization
111
+ if @cancancan_action.present? && @controller.current_ability.permitted_attributes(@cancancan_action, @simpleform.object).exclude?(name)
112
+ Rails.logger.debug do
113
+ "Skipping form field #{name.inspect} because the current user is not allowed to perform #{@cancancan_action.inspect} on #{@simpleform.object}."
114
+ end
115
+ return
108
116
  end
109
- return
110
- end
111
117
 
112
- hidden = input_opts.delete(:hidden)
113
- model_field = @simpleform.object.fields[name]
114
- fail("Field #{name.inspect} is not defined on #{@simpleform.object.inspect} but was requested in #{inspect}.") unless model_field
118
+ hidden = input_opts.delete(:hidden)
119
+ model_field = @simpleform.object.fields[name]
120
+ fail("Field #{name.inspect} is not defined on #{@simpleform.object.inspect} but was requested in #{inspect}.") unless model_field
115
121
 
116
- if hidden
117
- return model_field.simpleform_input_hidden(@simpleform, self, **input_opts)
118
- else
119
- unless @focus_given || @skip_autofocus
120
- input_opts[:autofocus] = true unless input_opts.key? :autofocus
121
- @focus_given = true
122
+ if hidden
123
+ return model_field.simpleform_input_hidden(@simpleform, self, **input_opts)
124
+ else
125
+ unless @focus_given || @skip_autofocus
126
+ input_opts[:autofocus] = true unless input_opts.key? :autofocus
127
+ @focus_given = true
128
+ end
129
+ return model_field.simpleform_input(@simpleform, self, **input_opts)
122
130
  end
123
- return model_field.simpleform_input(@simpleform, self, **input_opts)
124
131
  end
125
132
  end
126
133
 
@@ -163,6 +170,11 @@ module Compony
163
170
  @form_disabled = true
164
171
  end
165
172
 
173
+ # DSL method, allows to customize parameters given to simple_form_for
174
+ def form_params(**new_form_params)
175
+ @form_params = new_form_params
176
+ end
177
+
166
178
  protected
167
179
 
168
180
  # DSL method, adds a new line to the schema whitelisting a single param inside the schema's wrapper
@@ -173,19 +185,24 @@ module Compony
173
185
 
174
186
  # DSL method, adds a new field to the schema whitelisting a single field of data_class
175
187
  # This auto-generates the correct schema line for the field.
176
- def schema_field(field_name)
177
- # This runs upon component setup.
178
- @schema_lines_for_data << proc do |data, controller|
179
- # This runs within a request context.
180
- field = data.class.fields[field_name.to_sym] || fail("No field #{field_name.to_sym.inspect} found for #{data.inspect} in #{inspect}.")
181
- # Check per-field authorization
182
- if @cancancan_action.present? && controller.current_ability.permitted_attributes(@cancancan_action.to_sym, data).exclude?(field.name.to_sym)
183
- Rails.logger.debug do
184
- "Skipping form schema_field #{field_name.inspect} because the current user is not allowed to perform #{@cancancan_action.inspect} on #{data}."
188
+ # If multilang is true, a suffixed field is generated for every available locale (useful with gem "mobility")
189
+ def schema_field(field_name, multilang: false)
190
+ if multilang
191
+ I18n.available_locales.each { |locale| schema_field("#{field_name}_#{locale}") }
192
+ else
193
+ # This runs upon component setup.
194
+ @schema_lines_for_data << proc do |data, controller|
195
+ # This runs within a request context.
196
+ field = data.class.fields[field_name.to_sym] || fail("No field #{field_name.to_sym.inspect} found for #{data.inspect} in #{inspect}.")
197
+ # Check per-field authorization
198
+ if @cancancan_action.present? && controller.current_ability.permitted_attributes(@cancancan_action.to_sym, data).exclude?(field.name.to_sym)
199
+ Rails.logger.debug do
200
+ "Skipping form schema_field #{field_name.inspect} because the current user is not allowed to perform #{@cancancan_action.inspect} on #{data}."
201
+ end
202
+ next nil
185
203
  end
186
- next nil
204
+ next field.schema_line
187
205
  end
188
- next field.schema_line
189
206
  end
190
207
  end
191
208
 
@@ -198,7 +215,7 @@ module Compony
198
215
  # Check per-field authorization
199
216
  unless @cancancan_action.nil? || controller.current_ability.can?(:set_password, data)
200
217
  Rails.logger.debug do
201
- "Skipping form schema_pw_field #{name.inspect} because the current user is not allowed to perform :set_password on #{data}."
218
+ "Skipping form schema_pw_field #{field_name.inspect} because the current user is not allowed to perform :set_password on #{data}."
202
219
  end
203
220
  next nil
204
221
  end
@@ -19,21 +19,27 @@ module Compony
19
19
  end
20
20
 
21
21
  # DSL method, defines a new field which will be translated and can be added to field groups
22
- def field(name, type, **extra_attrs)
23
- name = name.to_sym
24
- self.fields = fields.dup
25
- field = Compony.model_field_class_for(type.to_s.camelize).new(name, self, **extra_attrs)
26
- # Handle the case where ActiveType would interfere with attribute registration
27
- if defined?(ActiveType) && self <= ActiveType::Object && !include?(ActiveModel::Attributes)
28
- fail "Please add `include ActiveModel::Attributes` at the top of the class #{self}, as attributes cannot be registered otherwise with ActiveType."
29
- end
30
- # Register the field as an attribute
31
- if defined?(ActiveType) && self <= ActiveType::Object
32
- ar_attribute(name)
22
+ # If multilang is true, a suffixed field is generated for every available locale, along with a non-suffixed virtual field (useful with gem "mobility")
23
+ def field(name, type, multilang: false, **extra_attrs)
24
+ if multilang
25
+ field(name, type, virtual: true, **extra_attrs)
26
+ I18n.available_locales.each { |locale| field("#{name}_#{locale}", type, **extra_attrs) }
33
27
  else
34
- attribute(name)
28
+ name = name.to_sym
29
+ self.fields = fields.dup
30
+ field = Compony.model_field_class_for(type.to_s.camelize).new(name, self, **extra_attrs)
31
+ # Handle the case where ActiveType would interfere with attribute registration
32
+ if defined?(ActiveType) && self <= ActiveType::Object && !include?(ActiveModel::Attributes)
33
+ fail "Please add `include ActiveModel::Attributes` at the top of the class #{self}, as attributes cannot be registered otherwise with ActiveType."
34
+ end
35
+ # Register the field as an attribute
36
+ if defined?(ActiveType) && self <= ActiveType::Object
37
+ ar_attribute(name)
38
+ else
39
+ attribute(name)
40
+ end
41
+ fields[name] = field
35
42
  end
36
- fields[name] = field
37
43
  end
38
44
 
39
45
  # DSL method, sets the containing model.
@@ -66,7 +72,11 @@ module Compony
66
72
  # Add a prevention that reflects the `has_many` `dependent' properties. Avoids that users can press buttons that will result in a failed destroy.
67
73
  reflect_on_all_associations.select { |assoc| %i[restrict_with_exception restrict_with_error].include? assoc.options[:dependent] }.each do |assoc|
68
74
  prevent(:destroy, I18n.t('compony.feasibility.has_dependent_models', dependent_class: I18n.t(assoc.klass.model_name.plural.humanize))) do
69
- public_send(assoc.name).any?
75
+ if assoc.is_a? ActiveRecord::Reflection::HasOneReflection
76
+ !public_send(assoc.name).nil?
77
+ else
78
+ public_send(assoc.name).any?
79
+ end
70
80
  end
71
81
  end
72
82
  self.autodetect_feasibilities_completed = true
data/lib/compony.rb CHANGED
@@ -79,13 +79,13 @@ module Compony
79
79
  end
80
80
 
81
81
  # Getter for content_before_root_comp_block
82
- # @see Compony#content_before_root_comp
82
+ # @see Compony#content_before_root_comp=
83
83
  def self.content_before_root_comp_block
84
84
  @content_before_root_comp_block
85
85
  end
86
86
 
87
87
  # Getter for content_after_root_comp_block
88
- # @see Compony#content_after_root_comp
88
+ # @see Compony#content_after_root_comp=
89
89
  def self.content_after_root_comp_block
90
90
  @content_after_root_comp_block
91
91
  end
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: compony
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 0.5.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sandro Kalbermatter
8
8
  - contributors
9
- autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2024-12-20 00:00:00.000000000 Z
11
+ date: 2025-04-07 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: yard
@@ -165,8 +164,6 @@ dependencies:
165
164
  - - "~>"
166
165
  - !ruby/object:Gem::Version
167
166
  version: 3.6.1
168
- description:
169
- email:
170
167
  executables: []
171
168
  extensions: []
172
169
  extra_rdoc_files: []
@@ -312,10 +309,8 @@ files:
312
309
  - lib/generators/components/USAGE
313
310
  - lib/generators/components/components_generator.rb
314
311
  - logo.svg
315
- homepage:
316
312
  licenses: []
317
313
  metadata: {}
318
- post_install_message:
319
314
  rdoc_options: []
320
315
  require_paths:
321
316
  - lib
@@ -330,8 +325,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
330
325
  - !ruby/object:Gem::Version
331
326
  version: '0'
332
327
  requirements: []
333
- rubygems_version: 3.5.22
334
- signing_key:
328
+ rubygems_version: 3.6.3
335
329
  specification_version: 4
336
330
  summary: Compony is a Gem that allows you to write your Rails application in component-style
337
331
  fashion. It combines a controller action and route along \ with its view into a