compony 0.11.8 → 0.11.9
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 +4 -4
- data/.yardopts +36 -1
- data/CHANGELOG.md +31 -0
- data/CLAUDE.md +85 -0
- data/Gemfile.lock +1 -1
- data/README.md +13 -3
- data/VERSION +1 -1
- data/compony.gemspec +3 -3
- data/doc/ComponentGenerator.html +1 -1
- data/doc/Components.html +1 -1
- data/doc/ComponentsGenerator.html +1 -1
- data/doc/Compony/Component.html +54 -54
- data/doc/Compony/ComponentMixins/Default/Labelling.html +1 -1
- data/doc/Compony/ComponentMixins/Default/Standalone/ResourcefulVerbDsl.html +1 -1
- data/doc/Compony/ComponentMixins/Default/Standalone/StandaloneDsl.html +109 -70
- data/doc/Compony/ComponentMixins/Default/Standalone/VerbDsl.html +64 -28
- data/doc/Compony/ComponentMixins/Default/Standalone.html +1 -1
- data/doc/Compony/ComponentMixins/Default.html +1 -1
- data/doc/Compony/ComponentMixins/Resourceful.html +213 -74
- data/doc/Compony/ComponentMixins.html +1 -1
- data/doc/Compony/Components/Buttons/CssButton.html +1 -1
- data/doc/Compony/Components/Buttons/Link.html +1 -1
- data/doc/Compony/Components/Buttons.html +1 -1
- data/doc/Compony/Components/Destroy.html +83 -29
- data/doc/Compony/Components/Edit.html +110 -38
- data/doc/Compony/Components/Form.html +551 -208
- data/doc/Compony/Components/Index.html +1 -1
- data/doc/Compony/Components/List.html +3 -3
- data/doc/Compony/Components/New.html +110 -38
- data/doc/Compony/Components/Show.html +1 -1
- data/doc/Compony/Components/WithForm.html +194 -47
- data/doc/Compony/Components.html +1 -1
- data/doc/Compony/ControllerMixin.html +1 -1
- data/doc/Compony/Engine.html +1 -1
- data/doc/Compony/Intent.html +2 -2
- data/doc/Compony/ManageIntentsDsl.html +1 -1
- data/doc/Compony/MethodAccessibleHash.html +1 -1
- data/doc/Compony/ModelFields/Anchormodel.html +1 -1
- data/doc/Compony/ModelFields/Association.html +1 -1
- data/doc/Compony/ModelFields/Attachment.html +1 -1
- data/doc/Compony/ModelFields/Base.html +1 -1
- data/doc/Compony/ModelFields/Boolean.html +1 -1
- data/doc/Compony/ModelFields/Color.html +1 -1
- data/doc/Compony/ModelFields/Currency.html +1 -1
- data/doc/Compony/ModelFields/Date.html +1 -1
- data/doc/Compony/ModelFields/Datetime.html +1 -1
- data/doc/Compony/ModelFields/Decimal.html +1 -1
- data/doc/Compony/ModelFields/Email.html +1 -1
- data/doc/Compony/ModelFields/Float.html +1 -1
- data/doc/Compony/ModelFields/Integer.html +1 -1
- data/doc/Compony/ModelFields/Percentage.html +1 -1
- data/doc/Compony/ModelFields/Phone.html +1 -1
- data/doc/Compony/ModelFields/RichText.html +1 -1
- data/doc/Compony/ModelFields/String.html +1 -1
- data/doc/Compony/ModelFields/Text.html +1 -1
- data/doc/Compony/ModelFields/Time.html +1 -1
- data/doc/Compony/ModelFields/Url.html +1 -1
- data/doc/Compony/ModelFields.html +1 -1
- data/doc/Compony/ModelMixin.html +1 -1
- data/doc/Compony/NaturalOrdering.html +1 -1
- data/doc/Compony/RequestContext.html +1 -1
- data/doc/Compony/Version.html +1 -1
- data/doc/Compony/ViewHelpers.html +1 -1
- data/doc/Compony/VirtualModel.html +1 -1
- data/doc/Compony.html +1 -1
- data/doc/ComponyController.html +1 -1
- data/doc/_index.html +97 -1
- data/doc/file.CHANGELOG.html +758 -0
- data/doc/file.README.html +25 -4
- data/doc/file.basic_component.html +314 -0
- data/doc/file.cookbook.html +189 -0
- data/doc/file.destroy.html +105 -0
- data/doc/file.dsl_reference.html +672 -0
- data/doc/file.edit.html +109 -0
- data/doc/file.example.html +291 -0
- data/doc/file.example_advanced.html +257 -0
- data/doc/file.feasibility.html +115 -0
- data/doc/file.form.html +195 -0
- data/doc/file.generators.html +89 -0
- data/doc/file.glossary.html +217 -0
- data/doc/file.gotchas.html +222 -0
- data/doc/file.index.html +135 -0
- data/doc/file.inheritance.html +136 -0
- data/doc/file.installation.html +115 -0
- data/doc/file.integrations.html +218 -0
- data/doc/file.intents.html +265 -0
- data/doc/file.internal_datastructures.html +129 -0
- data/doc/file.list.html +253 -0
- data/doc/file.maintaining.html +127 -0
- data/doc/file.model_fields.html +137 -0
- data/doc/file.nesting.html +237 -0
- data/doc/file.new.html +109 -0
- data/doc/file.ownership.html +98 -0
- data/doc/file.patterns.html +669 -0
- data/doc/file.pre_built_components.html +99 -0
- data/doc/file.resourceful.html +181 -0
- data/doc/file.show.html +158 -0
- data/doc/file.standalone.html +233 -0
- data/doc/file.virtual_models.html +117 -0
- data/doc/file.with_form.html +157 -0
- data/doc/file_list.html +160 -0
- data/doc/guide/cookbook.md +41 -0
- data/doc/guide/dsl_reference.md +155 -0
- data/doc/guide/example_advanced.md +209 -0
- data/doc/guide/generators.md +1 -1
- data/doc/guide/glossary.md +42 -0
- data/doc/guide/gotchas.md +125 -0
- data/doc/guide/maintaining.md +64 -0
- data/doc/guide/patterns.md +681 -0
- data/doc/guide/pre_built_components/edit.md +1 -1
- data/doc/guide/pre_built_components/index.md +64 -1
- data/doc/guide/pre_built_components/list.md +111 -7
- data/doc/guide/pre_built_components/show.md +57 -2
- data/doc/guide/pre_built_components/with_form.md +56 -9
- data/doc/guide/pre_built_components.md +7 -2
- data/doc/guide/standalone.md +16 -1
- data/doc/index.html +25 -4
- data/doc/integrations.md +61 -0
- data/doc/llms.txt +62 -0
- data/doc/top-level-namespace.html +1 -1
- data/lib/compony/component.rb +8 -3
- data/lib/compony/component_mixins/default/standalone/standalone_dsl.rb +32 -15
- data/lib/compony/component_mixins/default/standalone/verb_dsl.rb +11 -3
- data/lib/compony/component_mixins/resourceful.rb +30 -16
- data/lib/compony/components/destroy.rb +21 -1
- data/lib/compony/components/edit.rb +25 -1
- data/lib/compony/components/form.rb +63 -21
- data/lib/compony/components/list.rb +1 -1
- data/lib/compony/components/new.rb +25 -1
- data/lib/compony/components/with_form.rb +20 -5
- data/lib/compony/intent.rb +1 -1
- metadata +43 -1
|
@@ -16,16 +16,27 @@ module Compony
|
|
|
16
16
|
@scope = scope
|
|
17
17
|
@scope_args = scope_args
|
|
18
18
|
@verbs = {}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
# These default to nil so that, on subsequent `standalone` calls (e.g. subclass overrides), they are stripped
|
|
20
|
+
# by `compact` and thus do NOT clobber values inherited via `deep_merge!`. The actual defaults are only injected
|
|
21
|
+
# when `provide_defaults` is true (i.e. the first `standalone` call). This mirrors VerbDsl#to_conf.
|
|
22
|
+
@skip_authentication = nil
|
|
23
|
+
@skip_forgery_protection = nil
|
|
24
|
+
@layout = nil # can be overriden by false or a string
|
|
22
25
|
end
|
|
23
26
|
|
|
27
|
+
# Defaults injected only on the first `standalone` call. Kept out of subsequent calls so inherited values survive.
|
|
28
|
+
DEFAULT_CONFIG = {
|
|
29
|
+
skip_authentication: false,
|
|
30
|
+
skip_forgery_protection: false,
|
|
31
|
+
layout: true
|
|
32
|
+
}.freeze
|
|
33
|
+
|
|
24
34
|
# For internal usage only, processes the block and returns a config hash.
|
|
25
35
|
def to_conf(&block)
|
|
26
36
|
evaluate(&block)
|
|
27
37
|
@component = block.binding.eval('self') # Fetches the component holding this DSL call (via the block)
|
|
28
|
-
|
|
38
|
+
base_config = @provide_defaults ? DEFAULT_CONFIG.dup : {}
|
|
39
|
+
return base_config.merge({
|
|
29
40
|
name: @name,
|
|
30
41
|
path: @path,
|
|
31
42
|
constraints: @constraints,
|
|
@@ -37,13 +48,16 @@ module Compony
|
|
|
37
48
|
skip_authentication: @skip_authentication,
|
|
38
49
|
skip_forgery_protection: @skip_forgery_protection,
|
|
39
50
|
layout: @layout
|
|
40
|
-
}.compact
|
|
51
|
+
}.compact)
|
|
41
52
|
end
|
|
42
53
|
|
|
43
54
|
protected
|
|
44
55
|
|
|
45
|
-
# DSL
|
|
46
|
-
#
|
|
56
|
+
# DSL method. Defines the config for one HTTP verb. The block runs within the verb DSL; positional and named
|
|
57
|
+
# arguments are forwarded to it. Call at most once per verb per standalone.
|
|
58
|
+
# @param verb [Symbol] The HTTP verb (one of `:get :head :post :put :delete :connect :options :trace :patch`).
|
|
59
|
+
# @return [void]
|
|
60
|
+
# @api public
|
|
47
61
|
# @see Compony::ComponentMixins::Default::Standalone::VerbDsl
|
|
48
62
|
def verb(verb, *, **nargs, &)
|
|
49
63
|
verb = verb.to_sym
|
|
@@ -61,22 +75,25 @@ module Compony
|
|
|
61
75
|
end
|
|
62
76
|
end
|
|
63
77
|
|
|
64
|
-
# DSL
|
|
65
|
-
#
|
|
78
|
+
# DSL method. Disables app authentication for this standalone (an `authorize` block is still mandatory).
|
|
79
|
+
# @return [void]
|
|
80
|
+
# @api public
|
|
66
81
|
def skip_authentication!
|
|
67
82
|
@skip_authentication = true
|
|
68
83
|
end
|
|
69
84
|
|
|
70
|
-
# DSL
|
|
71
|
-
#
|
|
85
|
+
# DSL method. Disables forgery protection (CSRF) for this standalone's controller action.
|
|
86
|
+
# @return [void]
|
|
87
|
+
# @api public
|
|
72
88
|
def skip_forgery_protection!
|
|
73
89
|
@skip_forgery_protection = true
|
|
74
90
|
end
|
|
75
91
|
|
|
76
|
-
# DSL
|
|
77
|
-
#
|
|
78
|
-
#
|
|
79
|
-
# @
|
|
92
|
+
# DSL method. Sets the Rails layout (under `app/views/layouts`) used to render this component.
|
|
93
|
+
# Defaults to Rails' default (`layouts/application`) if never called.
|
|
94
|
+
# @param layout [String,Symbol] Layout name, as passed to a Rails controller's `render`.
|
|
95
|
+
# @return [void]
|
|
96
|
+
# @api public
|
|
80
97
|
def layout(layout)
|
|
81
98
|
@layout = layout.to_s
|
|
82
99
|
end
|
|
@@ -35,14 +35,22 @@ module Compony
|
|
|
35
35
|
protected
|
|
36
36
|
|
|
37
37
|
# DSL
|
|
38
|
-
#
|
|
38
|
+
# Mandatory. The block must return truthy iff `current_ability` may access the component over this verb;
|
|
39
|
+
# a falsy result raises `CanCan::AccessDenied`.
|
|
40
|
+
# @yield Runs in the component's request context; returns truthy to grant access.
|
|
41
|
+
# @return [void]
|
|
42
|
+
# @api public
|
|
39
43
|
def authorize(&block)
|
|
40
44
|
@authorize_block = block
|
|
41
45
|
end
|
|
42
46
|
|
|
43
47
|
# DSL
|
|
44
|
-
#
|
|
45
|
-
#
|
|
48
|
+
# Last step in the lifecycle. May redirect or render. If omitted, the default is `render_standalone`.
|
|
49
|
+
# NOTE: overriding `respond` replaces the default, which is where `authorize` is evaluated - re-check authorization yourself.
|
|
50
|
+
# @param format [String,Symbol,nil] Format this block responds to; `nil` means "all other formats".
|
|
51
|
+
# @yield Runs in the component's request context; renders or redirects.
|
|
52
|
+
# @return [void]
|
|
53
|
+
# @api public
|
|
46
54
|
def respond(format = nil, &block)
|
|
47
55
|
@respond_blocks[format&.to_sym] = block
|
|
48
56
|
end
|
|
@@ -25,8 +25,13 @@ module Compony
|
|
|
25
25
|
super(*, **nargs, &)
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
+
# @!group DSL
|
|
29
|
+
|
|
28
30
|
# DSL method
|
|
29
|
-
# Sets or calculates the model class
|
|
31
|
+
# Sets or calculates the model class. Defaults to the component's family name, singularized and constantized.
|
|
32
|
+
# @param new_data_class [Class,nil] If given, the model class to use (e.g. a {Compony::VirtualModel} subclass).
|
|
33
|
+
# @return [Class] The resolved data class.
|
|
34
|
+
# @api public
|
|
30
35
|
def data_class(new_data_class = nil)
|
|
31
36
|
@data_class ||= new_data_class || family_name.singularize.camelize.constantize
|
|
32
37
|
end
|
|
@@ -38,27 +43,32 @@ module Compony
|
|
|
38
43
|
protected
|
|
39
44
|
|
|
40
45
|
# DSL method
|
|
41
|
-
# Sets
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
46
|
+
# Sets the default `load_data` block for all standalone paths and verbs (overridable per verb in the VerbDsl).
|
|
47
|
+
# Runs before authorization. The block is expected to assign `@data`.
|
|
48
|
+
# @yield Runs in the component's request context; must assign `@data`.
|
|
49
|
+
# @return [void]
|
|
50
|
+
# @api public
|
|
45
51
|
# @see Compony::ComponentMixins::Default::Standalone::VerbDsl#load_data
|
|
46
52
|
def load_data(&block)
|
|
47
53
|
@global_load_data_block = block
|
|
48
54
|
end
|
|
49
55
|
|
|
50
56
|
# DSL method
|
|
51
|
-
# Runs after
|
|
52
|
-
# Example
|
|
57
|
+
# Runs after `load_data` and before authorization for all standalone paths and verbs.
|
|
58
|
+
# Example: refine an AR collection produced by `load_data` before it is read.
|
|
59
|
+
# @yield Runs in the component's request context; may refine `@data`.
|
|
60
|
+
# @return [void]
|
|
61
|
+
# @api public
|
|
53
62
|
def after_load_data(&block)
|
|
54
63
|
@global_after_load_data_block = block
|
|
55
64
|
end
|
|
56
65
|
|
|
57
66
|
# DSL method
|
|
58
|
-
# Sets
|
|
59
|
-
#
|
|
60
|
-
#
|
|
61
|
-
#
|
|
67
|
+
# Sets the default `assign_attributes` block for all standalone paths and verbs (overridable per verb in the VerbDsl).
|
|
68
|
+
# The block is expected to assign validated `params` to attributes of `@data`.
|
|
69
|
+
# @yield Runs in the component's request context; assigns params onto `@data`.
|
|
70
|
+
# @return [void]
|
|
71
|
+
# @api public
|
|
62
72
|
# @see Compony::ComponentMixins::Default::Standalone::VerbDsl#assign_attributes
|
|
63
73
|
def assign_attributes(&block)
|
|
64
74
|
@global_assign_attributes_block = block
|
|
@@ -66,16 +76,20 @@ module Compony
|
|
|
66
76
|
|
|
67
77
|
# DSL method
|
|
68
78
|
# Runs after `assign_attributes` and before `store_data` for all standalone paths and verbs.
|
|
69
|
-
# Example
|
|
79
|
+
# Example: prefill or derive fields before validation.
|
|
80
|
+
# @yield Runs in the component's request context; may mutate `@data`.
|
|
81
|
+
# @return [void]
|
|
82
|
+
# @api public
|
|
70
83
|
def after_assign_attributes(&block)
|
|
71
84
|
@global_after_assign_attributes_block = block
|
|
72
85
|
end
|
|
73
86
|
|
|
74
87
|
# DSL method
|
|
75
|
-
# Sets
|
|
76
|
-
#
|
|
77
|
-
#
|
|
78
|
-
#
|
|
88
|
+
# Sets the default `store_data` block for all standalone paths and verbs (overridable per verb in the VerbDsl).
|
|
89
|
+
# The block is expected to persist `@data` (override e.g. for virtual models or custom persistence).
|
|
90
|
+
# @yield Runs in the component's request context; persists `@data`.
|
|
91
|
+
# @return [void]
|
|
92
|
+
# @api public
|
|
79
93
|
# @see Compony::ComponentMixins::Default::Standalone::VerbDsl#store_data
|
|
80
94
|
def store_data(&block)
|
|
81
95
|
@global_store_data_block = block
|
|
@@ -78,21 +78,41 @@ module Compony
|
|
|
78
78
|
end
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
+
# @!group DSL
|
|
82
|
+
|
|
81
83
|
# DSL method
|
|
82
|
-
# Sets
|
|
84
|
+
# Sets an optional hook evaluated (with backfire) after a successful destroy but before responding.
|
|
85
|
+
# Suitable for post-destroy side effects (like an `after_destroy` that only fires when this component destroyed the record).
|
|
86
|
+
# Do not redirect or render here - use {#on_destroyed_respond} / {#on_destroyed_redirect_path} for that.
|
|
87
|
+
# @yield Runs in the component's request context after `@data` was destroyed.
|
|
88
|
+
# @return [void]
|
|
89
|
+
# @api public
|
|
83
90
|
def on_destroyed(&block)
|
|
84
91
|
@on_destroyed_block = block
|
|
85
92
|
end
|
|
86
93
|
|
|
87
94
|
# DSL method
|
|
95
|
+
# Overrides the response issued after a successful destroy. The default shows a flash and redirects to
|
|
96
|
+
# {#on_destroyed_redirect_path} with HTTP 303 (forces a GET, required for Turbo). If you override this,
|
|
97
|
+
# {#on_destroyed_redirect_path} is no longer called.
|
|
98
|
+
# @yield Runs in the component's request context; expected to render or redirect.
|
|
99
|
+
# @return [void]
|
|
100
|
+
# @api public
|
|
88
101
|
def on_destroyed_respond(&block)
|
|
89
102
|
@on_destroyed_respond_block = block
|
|
90
103
|
end
|
|
91
104
|
|
|
92
105
|
# DSL method
|
|
106
|
+
# Overrides the redirect target used by the default {#on_destroyed_respond} (keeping the default flash).
|
|
107
|
+
# Defaults to the owner's Show (if owned) or the data's Index.
|
|
108
|
+
# @yield Runs in the component's request context; expected to return a Rails path (e.g. via `Compony.path`).
|
|
109
|
+
# @return [void]
|
|
110
|
+
# @api public
|
|
93
111
|
def on_destroyed_redirect_path(&block)
|
|
94
112
|
@on_destroyed_redirect_path_block = block
|
|
95
113
|
end
|
|
114
|
+
|
|
115
|
+
# @!endgroup
|
|
96
116
|
end
|
|
97
117
|
end
|
|
98
118
|
end
|
|
@@ -90,26 +90,50 @@ module Compony
|
|
|
90
90
|
end
|
|
91
91
|
end
|
|
92
92
|
|
|
93
|
+
# @!group DSL
|
|
94
|
+
|
|
93
95
|
# DSL method
|
|
94
|
-
# Sets
|
|
96
|
+
# Sets an optional hook evaluated (with backfire) after a successful update but before responding.
|
|
97
|
+
# Suitable for post-update side effects (like an `after_update` that only fires when this component updated the record).
|
|
98
|
+
# Do not redirect or render here - use {#on_updated_respond} / {#on_updated_redirect_path} for that.
|
|
99
|
+
# @yield Runs in the component's request context after `@data` was saved successfully.
|
|
100
|
+
# @return [void]
|
|
101
|
+
# @api public
|
|
95
102
|
def on_updated(&block)
|
|
96
103
|
@on_updated_block = block
|
|
97
104
|
end
|
|
98
105
|
|
|
99
106
|
# DSL method
|
|
107
|
+
# Overrides the response issued after a successful update. The default shows a flash and redirects to
|
|
108
|
+
# {#on_updated_redirect_path}. If you override this, {#on_updated_redirect_path} is no longer called.
|
|
109
|
+
# @yield Runs in the component's request context; expected to render or redirect.
|
|
110
|
+
# @return [void]
|
|
111
|
+
# @api public
|
|
100
112
|
def on_updated_respond(&block)
|
|
101
113
|
@on_updated_respond_block = block
|
|
102
114
|
end
|
|
103
115
|
|
|
104
116
|
# DSL method
|
|
117
|
+
# Overrides the redirect target used by the default {#on_updated_respond} (keeping the default flash).
|
|
118
|
+
# Defaults to the data's Show, the owner's Show, or the data's Index.
|
|
119
|
+
# @yield Runs in the component's request context; expected to return a Rails path (e.g. via `Compony.path`).
|
|
120
|
+
# @return [void]
|
|
121
|
+
# @api public
|
|
105
122
|
def on_updated_redirect_path(&block)
|
|
106
123
|
@on_updated_redirect_path_block = block
|
|
107
124
|
end
|
|
108
125
|
|
|
109
126
|
# DSL method
|
|
127
|
+
# Overrides the response issued when the update failed (`@update_succeeded` is not true).
|
|
128
|
+
# The default logs the errors with level `warn` and re-renders the component with HTTP 422 so the form shows errors.
|
|
129
|
+
# @yield Runs in the component's request context; expected to render or redirect.
|
|
130
|
+
# @return [void]
|
|
131
|
+
# @api public
|
|
110
132
|
def on_update_failed(&block)
|
|
111
133
|
@on_update_failed_block = block
|
|
112
134
|
end
|
|
135
|
+
|
|
136
|
+
# @!endgroup
|
|
113
137
|
end
|
|
114
138
|
end
|
|
115
139
|
end
|
|
@@ -52,7 +52,13 @@ module Compony
|
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
# DSL
|
|
55
|
+
# @!group DSL
|
|
56
|
+
|
|
57
|
+
# DSL method, use to set the form content (mandatory).
|
|
58
|
+
# The block holds the form inputs and is instance-exec'd in the form's request context where `field`, `pw_field` and `f` are available.
|
|
59
|
+
# @yield Builds the form body using Dyny + the form field helpers.
|
|
60
|
+
# @return [Proc,nil] When called without a block, returns the stored block.
|
|
61
|
+
# @api public
|
|
56
62
|
def form_fields(&block)
|
|
57
63
|
return @form_fields unless block_given?
|
|
58
64
|
@form_fields = block
|
|
@@ -97,9 +103,13 @@ module Compony
|
|
|
97
103
|
@controller = nil
|
|
98
104
|
end
|
|
99
105
|
|
|
100
|
-
#
|
|
101
|
-
#
|
|
102
|
-
#
|
|
106
|
+
# DSL method (inside `form_fields`). Renders a simple_form input inferred from the model field `name`.
|
|
107
|
+
# Respects per-field CanCanCan authorization; skipped fields render nothing.
|
|
108
|
+
# @param name [Symbol,String] The model field (use the association name, not the `_id`, for associations).
|
|
109
|
+
# @param multilang [Boolean] If true, generates one suffixed input per available locale and returns the array (useful with the "mobility" gem).
|
|
110
|
+
# @param input_opts [Hash] Passed to simple_form. Notable keys: `as:` (input type), `hidden: true`, `autofocus:`.
|
|
111
|
+
# @return [String,Array<String>] The input HTML (array when `multilang`).
|
|
112
|
+
# @api public
|
|
103
113
|
def field(name, multilang: false, **input_opts)
|
|
104
114
|
fail("The `field` method may only be called inside `form_fields` for #{inspect}.") unless @simpleform
|
|
105
115
|
|
|
@@ -134,9 +144,12 @@ module Compony
|
|
|
134
144
|
end
|
|
135
145
|
end
|
|
136
146
|
|
|
137
|
-
#
|
|
138
|
-
#
|
|
139
|
-
#
|
|
147
|
+
# DSL method (inside `form_fields`). Renders a password input; should be used for `:password` and `:password_confirmation`.
|
|
148
|
+
# Checks the `:set_password` CanCanCan ability; `:hidden` is intentionally unsupported here.
|
|
149
|
+
# @param name [Symbol,String] The password field name.
|
|
150
|
+
# @param input_opts [Hash] Passed to simple_form.
|
|
151
|
+
# @return [String,nil] The input HTML, or nil if not permitted.
|
|
152
|
+
# @api public
|
|
140
153
|
def pw_field(name, **input_opts)
|
|
141
154
|
fail("The `pw_field` method may only be called inside `form_fields` for #{inspect}.") unless @simpleform
|
|
142
155
|
name = name.to_sym
|
|
@@ -156,8 +169,10 @@ module Compony
|
|
|
156
169
|
return @simpleform.input name, **input_opts
|
|
157
170
|
end
|
|
158
171
|
|
|
159
|
-
#
|
|
160
|
-
#
|
|
172
|
+
# DSL method (inside `form_fields`). Returns the underlying simple_form builder, e.g. for `f.rich_text_area`
|
|
173
|
+
# or `f.simple_fields_for` (nested attributes).
|
|
174
|
+
# @return [SimpleForm::FormBuilder] The simple_form builder for the current form.
|
|
175
|
+
# @api public
|
|
161
176
|
def f
|
|
162
177
|
fail("The `f` method may only be called inside `form_fields` for #{inspect}.") unless @simpleform
|
|
163
178
|
return @simpleform
|
|
@@ -168,27 +183,41 @@ module Compony
|
|
|
168
183
|
Compony::ModelFields::Anchormodel.collect(...)
|
|
169
184
|
end
|
|
170
185
|
|
|
171
|
-
# DSL method, disables all inputs
|
|
186
|
+
# DSL method, disables all inputs.
|
|
187
|
+
# @return [void]
|
|
188
|
+
# @api public
|
|
172
189
|
def disable!
|
|
173
190
|
@form_disabled = true
|
|
174
191
|
end
|
|
175
192
|
|
|
176
|
-
# DSL method,
|
|
193
|
+
# DSL method, customizes the parameters given to `simple_form_for`.
|
|
194
|
+
# @param new_form_params [Hash] Extra kwargs forwarded to `simple_form_for`.
|
|
195
|
+
# @return [void]
|
|
196
|
+
# @api public
|
|
177
197
|
def form_params(**new_form_params)
|
|
178
198
|
@form_params = new_form_params
|
|
179
199
|
end
|
|
180
200
|
|
|
201
|
+
# @!endgroup
|
|
202
|
+
|
|
181
203
|
protected
|
|
182
204
|
|
|
183
|
-
# DSL
|
|
184
|
-
|
|
205
|
+
# @!group DSL
|
|
206
|
+
|
|
207
|
+
# DSL method, adds a Schemacop3 line whitelisting param(s) inside the schema's wrapper.
|
|
208
|
+
# @yield Runs in a Schemacop3 context, e.g. `str? :foo`.
|
|
209
|
+
# @return [void]
|
|
210
|
+
# @api public
|
|
185
211
|
def schema_line(&block)
|
|
186
212
|
@schema_lines_for_data << proc { |_data, _controller| block }
|
|
187
213
|
end
|
|
188
214
|
|
|
189
|
-
# DSL method,
|
|
190
|
-
#
|
|
191
|
-
#
|
|
215
|
+
# DSL method, whitelists a single field of `data_class` in the param schema, auto-generating the correct schema line.
|
|
216
|
+
# Respects per-field CanCanCan authorization.
|
|
217
|
+
# @param field_name [Symbol,String] The model field (association name, not `_id`, for associations).
|
|
218
|
+
# @param multilang [Boolean] If true, whitelists one suffixed field per available locale (useful with the "mobility" gem).
|
|
219
|
+
# @return [void]
|
|
220
|
+
# @api public
|
|
192
221
|
def schema_field(field_name, multilang: false)
|
|
193
222
|
if multilang
|
|
194
223
|
I18n.available_locales.each { |locale| schema_field("#{field_name}_#{locale}") }
|
|
@@ -209,8 +238,10 @@ module Compony
|
|
|
209
238
|
end
|
|
210
239
|
end
|
|
211
240
|
|
|
212
|
-
# DSL method,
|
|
213
|
-
#
|
|
241
|
+
# DSL method, whitelists a password param in the schema (checks the `:set_password` permission).
|
|
242
|
+
# @param field_name [Symbol,String] The password field name.
|
|
243
|
+
# @return [void]
|
|
244
|
+
# @api public
|
|
214
245
|
def schema_pw_field(field_name)
|
|
215
246
|
# This runs upon component setup.
|
|
216
247
|
@schema_lines_for_data << proc do |data, controller|
|
|
@@ -226,12 +257,19 @@ module Compony
|
|
|
226
257
|
end
|
|
227
258
|
end
|
|
228
259
|
|
|
229
|
-
# DSL method,
|
|
260
|
+
# DSL method, whitelists several fields at once (see {#schema_field}).
|
|
261
|
+
# @param field_names [Array<Symbol,String>] The model fields to whitelist.
|
|
262
|
+
# @return [void]
|
|
263
|
+
# @api public
|
|
230
264
|
def schema_fields(*field_names)
|
|
231
265
|
field_names.each { |field_name| schema_field(field_name) }
|
|
232
266
|
end
|
|
233
267
|
|
|
234
|
-
# DSL method,
|
|
268
|
+
# DSL method, replaces the form's schema and wrapper key with a completely manual Schemacop3 schema.
|
|
269
|
+
# @param wrapper_key [Symbol,String] The top-level params wrapper key (e.g. the model's singular name).
|
|
270
|
+
# @yield Runs in a Schemacop3 context defining the wrapped params.
|
|
271
|
+
# @return [void]
|
|
272
|
+
# @api public
|
|
235
273
|
def schema(wrapper_key, &block)
|
|
236
274
|
if block_given?
|
|
237
275
|
@schema_wrapper_key = wrapper_key
|
|
@@ -241,10 +279,14 @@ module Compony
|
|
|
241
279
|
end
|
|
242
280
|
end
|
|
243
281
|
|
|
244
|
-
# DSL method, skips adding autofocus to the first field
|
|
282
|
+
# DSL method, skips adding autofocus to the first field.
|
|
283
|
+
# @return [void]
|
|
284
|
+
# @api public
|
|
245
285
|
def skip_autofocus
|
|
246
286
|
@skip_autofocus = true
|
|
247
287
|
end
|
|
288
|
+
|
|
289
|
+
# @!endgroup
|
|
248
290
|
end
|
|
249
291
|
end
|
|
250
292
|
end
|
|
@@ -163,7 +163,7 @@ module Compony
|
|
|
163
163
|
end
|
|
164
164
|
|
|
165
165
|
# DSL method
|
|
166
|
-
# If a block is given: Enters the DSL where row intents can be added or removed (use from {Component
|
|
166
|
+
# If a block is given: Enters the DSL where row intents can be added or removed (use from {Compony::Component.setup} within the component).
|
|
167
167
|
# If no block is given: Builds the declared intents for the given record and returns them (use in `content` or `before_render`, pass kwarg `:data`).
|
|
168
168
|
def row_intents(**intent_opts, &block)
|
|
169
169
|
if block_given?
|
|
@@ -78,26 +78,50 @@ module Compony
|
|
|
78
78
|
end
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
+
# @!group DSL
|
|
82
|
+
|
|
81
83
|
# DSL method
|
|
82
|
-
# Sets
|
|
84
|
+
# Sets an optional hook evaluated (with backfire) after a successful create but before responding.
|
|
85
|
+
# Suitable for post-create side effects (like an `after_create` that only fires when this component created the record).
|
|
86
|
+
# Do not redirect or render here - use {#on_created_respond} / {#on_created_redirect_path} for that.
|
|
87
|
+
# @yield Runs in the component's request context after `@data` was saved successfully.
|
|
88
|
+
# @return [void]
|
|
89
|
+
# @api public
|
|
83
90
|
def on_created(&block)
|
|
84
91
|
@on_created_block = block
|
|
85
92
|
end
|
|
86
93
|
|
|
87
94
|
# DSL method
|
|
95
|
+
# Overrides the response issued after a successful create. The default shows a flash and redirects to
|
|
96
|
+
# {#on_created_redirect_path}. If you override this, {#on_created_redirect_path} is no longer called.
|
|
97
|
+
# @yield Runs in the component's request context; expected to render or redirect.
|
|
98
|
+
# @return [void]
|
|
99
|
+
# @api public
|
|
88
100
|
def on_created_respond(&block)
|
|
89
101
|
@on_created_respond_block = block
|
|
90
102
|
end
|
|
91
103
|
|
|
92
104
|
# DSL method
|
|
105
|
+
# Overrides the redirect target used by the default {#on_created_respond} (keeping the default flash).
|
|
106
|
+
# Defaults to the data's Show, the owner's Show, or the data's Index.
|
|
107
|
+
# @yield Runs in the component's request context; expected to return a Rails path (e.g. via `Compony.path`).
|
|
108
|
+
# @return [void]
|
|
109
|
+
# @api public
|
|
93
110
|
def on_created_redirect_path(&block)
|
|
94
111
|
@on_created_redirect_path_block = block
|
|
95
112
|
end
|
|
96
113
|
|
|
97
114
|
# DSL method
|
|
115
|
+
# Overrides the response issued when the create failed (`@create_succeeded` is not true).
|
|
116
|
+
# The default logs the errors with level `warn` and re-renders the component with HTTP 422 so the form shows errors.
|
|
117
|
+
# @yield Runs in the component's request context; expected to render or redirect.
|
|
118
|
+
# @return [void]
|
|
119
|
+
# @api public
|
|
98
120
|
def on_create_failed_respond(&block)
|
|
99
121
|
@on_create_failed_respond_block = block
|
|
100
122
|
end
|
|
123
|
+
|
|
124
|
+
# @!endgroup
|
|
101
125
|
end
|
|
102
126
|
end
|
|
103
127
|
end
|
|
@@ -22,8 +22,13 @@ module Compony
|
|
|
22
22
|
)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
# @!group DSL
|
|
26
|
+
|
|
25
27
|
# DSL method
|
|
26
|
-
# Sets or returns the
|
|
28
|
+
# Sets or returns the HTTP verb the twinned form submits with (`:post` for New, `:patch` for Edit).
|
|
29
|
+
# @param new_submit_verb [Symbol,nil] If given, sets the submit verb; must be a known HTTP verb.
|
|
30
|
+
# @return [Symbol] The (possibly just set) submit verb.
|
|
31
|
+
# @api public
|
|
27
32
|
def submit_verb(new_submit_verb = nil)
|
|
28
33
|
if new_submit_verb.present?
|
|
29
34
|
new_submit_verb = new_submit_verb.to_sym
|
|
@@ -35,13 +40,19 @@ module Compony
|
|
|
35
40
|
end
|
|
36
41
|
|
|
37
42
|
# DSL method
|
|
38
|
-
# Overrides the
|
|
43
|
+
# Overrides the Form component class instantiated by {#form_comp} (defaults to the same-family `Form`).
|
|
44
|
+
# @param new_form_comp_class [Class,nil] The Form component class to use.
|
|
45
|
+
# @return [Class,nil] The configured form component class.
|
|
46
|
+
# @api public
|
|
39
47
|
def form_comp_class(new_form_comp_class = nil)
|
|
40
48
|
@form_comp_class ||= new_form_comp_class
|
|
41
49
|
end
|
|
42
50
|
|
|
43
51
|
# DSL method
|
|
44
|
-
# Sets and gets the form's
|
|
52
|
+
# Sets and gets the form's CanCanCan action, used for per-field `permitted_attributes`. Pass `nil` to disable per-field auth.
|
|
53
|
+
# @param new_form_cancancan_action [Symbol,nil] The CanCanCan action (e.g. `:edit`); omit to read the current value.
|
|
54
|
+
# @return [Symbol,nil] The configured CanCanCan action.
|
|
55
|
+
# @api public
|
|
45
56
|
def form_cancancan_action(new_form_cancancan_action = :missing)
|
|
46
57
|
if new_form_cancancan_action != :missing
|
|
47
58
|
@form_cancancan_action = new_form_cancancan_action
|
|
@@ -50,11 +61,15 @@ module Compony
|
|
|
50
61
|
end
|
|
51
62
|
|
|
52
63
|
# DSL method
|
|
53
|
-
# Overrides the submit path which
|
|
54
|
-
#
|
|
64
|
+
# Overrides the submit path, which otherwise defaults to this component's own path.
|
|
65
|
+
# @yield [controller] Called with the controller; expected to return the Rails path the form submits to.
|
|
66
|
+
# @return [void]
|
|
67
|
+
# @api public
|
|
55
68
|
def submit_path(&new_submit_path_block)
|
|
56
69
|
@submit_path_block = new_submit_path_block
|
|
57
70
|
end
|
|
71
|
+
|
|
72
|
+
# @!endgroup
|
|
58
73
|
end
|
|
59
74
|
end
|
|
60
75
|
end
|
data/lib/compony/intent.rb
CHANGED
|
@@ -144,7 +144,7 @@ module Compony
|
|
|
144
144
|
# Renders this intent into a button defined by `style`.
|
|
145
145
|
# @param controller [ApplicationController] The controller from the request context, needed to render the button.
|
|
146
146
|
# @param parent_comp [Compony::Component] If called from within a component, pass the component to inform the button that it is nested within.
|
|
147
|
-
# @param style [Symbol] If present, overrides the class of the generated button component, defaults to {Compony
|
|
147
|
+
# @param style [Symbol] If present, overrides the class of the generated button component, defaults to {Compony.default_button_style}.
|
|
148
148
|
# @param button_arg_overrides [Hash] Any further kwargs are passed to the button component's initializer.
|
|
149
149
|
def render(controller, parent_comp = nil, style: nil, **button_arg_overrides)
|
|
150
150
|
# Abort if not authorized
|