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
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>
|
|
7
|
+
File: standalone
|
|
8
|
+
|
|
9
|
+
— Documentation by YARD 0.9.34
|
|
10
|
+
|
|
11
|
+
</title>
|
|
12
|
+
|
|
13
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" />
|
|
14
|
+
|
|
15
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" />
|
|
16
|
+
|
|
17
|
+
<script type="text/javascript">
|
|
18
|
+
pathId = "standalone";
|
|
19
|
+
relpath = '';
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
|
24
|
+
|
|
25
|
+
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
</head>
|
|
29
|
+
<body>
|
|
30
|
+
<div class="nav_wrap">
|
|
31
|
+
<iframe id="nav" src="file_list.html?1"></iframe>
|
|
32
|
+
<div id="resizer"></div>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<div id="main" tabindex="-1">
|
|
36
|
+
<div id="header">
|
|
37
|
+
<div id="menu">
|
|
38
|
+
|
|
39
|
+
<a href="_index.html">Index</a> »
|
|
40
|
+
<span class="title">File: standalone</span>
|
|
41
|
+
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<div id="search">
|
|
45
|
+
|
|
46
|
+
<a class="full_list_link" id="class_list_link"
|
|
47
|
+
href="class_list.html">
|
|
48
|
+
|
|
49
|
+
<svg width="24" height="24">
|
|
50
|
+
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
|
51
|
+
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
|
52
|
+
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
|
53
|
+
</svg>
|
|
54
|
+
</a>
|
|
55
|
+
|
|
56
|
+
</div>
|
|
57
|
+
<div class="clear"></div>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<div id="content"><div id='filecontents'>
|
|
61
|
+
<p><a href="/README_md.html#guide--documentation">Back to the guide</a></p>
|
|
62
|
+
|
|
63
|
+
<h1 id="label-Standalone+-28routing+to+components-29">Standalone (routing to components)</h1>
|
|
64
|
+
|
|
65
|
+
<p>As stated earlier, Compony can generate routes to your components. This is achieved by using the standalone DSL inside the setup block. The first step is calling the method <code>standalone</code> with a path. Inside this block, you will then specify which HTTP verbs (e.g. GET, PATCH etc.) the component should listen to. As soon as both are specified, Compony will generate an appropriate route.</p>
|
|
66
|
+
|
|
67
|
+
<p>Assume that you want to create a simple component <code>statics/welcome.rb</code> that displays a static welcome page. The component should be exposed under the route <code>'/welcome'</code> and respond to the GET method. Here is the complete code for making this happen:</p>
|
|
68
|
+
|
|
69
|
+
<pre class="code ruby"><code class="ruby"><span class='comment'># app/components/statics/welcome.rb
|
|
70
|
+
</span><span class='kw'>class</span> <span class='const'><span class='object_link'><a href="Components.html" title="Components (module)">Components</a></span></span><span class='op'>::</span><span class='const'>Statics</span><span class='op'>::</span><span class='const'>Welcome</span> <span class='op'><</span> <span class='const'><span class='object_link'><a href="Compony.html" title="Compony (module)">Compony</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Compony/Component.html" title="Compony::Component (class)">Component</a></span></span>
|
|
71
|
+
<span class='id identifier rubyid_setup'>setup</span> <span class='kw'>do</span>
|
|
72
|
+
<span class='id identifier rubyid_label'>label</span><span class='lparen'>(</span><span class='symbol'>:all</span><span class='rparen'>)</span> <span class='lbrace'>{</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Welcome</span><span class='tstring_end'>'</span></span> <span class='rbrace'>}</span>
|
|
73
|
+
|
|
74
|
+
<span class='id identifier rubyid_standalone'>standalone</span> <span class='label'>path:</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>welcome</span><span class='tstring_end'>'</span></span> <span class='kw'>do</span>
|
|
75
|
+
<span class='id identifier rubyid_verb'>verb</span> <span class='symbol'>:get</span> <span class='kw'>do</span>
|
|
76
|
+
<span class='id identifier rubyid_authorize'>authorize</span> <span class='lbrace'>{</span> <span class='kw'>true</span> <span class='rbrace'>}</span>
|
|
77
|
+
<span class='kw'>end</span>
|
|
78
|
+
<span class='kw'>end</span>
|
|
79
|
+
|
|
80
|
+
<span class='id identifier rubyid_content'>content</span> <span class='kw'>do</span>
|
|
81
|
+
<span class='id identifier rubyid_h1'>h1</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Welcome to my dummy site!</span><span class='tstring_end'>'</span></span>
|
|
82
|
+
<span class='kw'>end</span>
|
|
83
|
+
<span class='kw'>end</span>
|
|
84
|
+
<span class='kw'>end</span>
|
|
85
|
+
</code></pre>
|
|
86
|
+
|
|
87
|
+
<p>This is the minimal required code for standalone. For security, every verb config must provide an <code>authorize</code> block that specifies who has access to this standalone verb. The block is given the request context and is expected to return either true (access ok) or false (causing the request to fail with <code>Cancan::AccessDenied</code>).</p>
|
|
88
|
+
|
|
89
|
+
<p>Typically, you would use this block to check authorization using the CanCanCan gem, such as <code>authorize { can?(:read, :welcome) }</code>. However, since we skip authentication in this simple example, we pass <code>true</code> to allow all access.</p>
|
|
90
|
+
|
|
91
|
+
<p>The standalone DSL has more features than those presented in the minimal example above. Excluding <a href="./resourceful_md.html">resourceful</a> features, the full list is:</p>
|
|
92
|
+
<ul><li>
|
|
93
|
+
<p><code>standalone</code> can be called multiple times, for components that need to expose multiple paths, as described below. Inside each <code>standalone</code> call, you can call:</p>
|
|
94
|
+
</li><li>
|
|
95
|
+
<p><code>skip_authentication!</code> which disables authentication, in case you provided some. You need to implement <code>authorize</code> regardless.</p>
|
|
96
|
+
</li><li>
|
|
97
|
+
<p><code>skip_forgery_protection!</code> which disables CSRF protection for the controller action generated for this standalone configuration.</p>
|
|
98
|
+
</li><li>
|
|
99
|
+
<p><code>layout</code> which takes the file name of a Rails layout and defaults to <code>layouts/application</code>. Use this to have your Rails application look differently depending on the component.</p>
|
|
100
|
+
</li><li>
|
|
101
|
+
<p><code>verb</code> which takes an HTTP verb as a symbol, one of: <code>%i[get head post put delete connect options trace patch]</code>. <code>verb</code> can be called up to once per verb. Inside each <code>verb</code> call, you can call (in the non-resourceful case):</p>
|
|
102
|
+
<ul><li>
|
|
103
|
+
<p><code>authorize</code> is mandatory and explained above.</p>
|
|
104
|
+
</li><li>
|
|
105
|
+
<p><code>respond</code> can be used to implement special behavior that in plain Rails would be placed in a controller action. The default, which calls <code>before_render</code> and the <code>content</code> blocks, is usually the right choice, so you will rarely implement <code>respond</code> on your own. See below how <code>respond</code> can be used to handle different formats or redirecting clients. <strong>Caution:</strong> <code>authorize</code> is evaluated in the default implementation of <code>respond</code>, so when you override that block, you must perform authorization yourself!</p>
|
|
106
|
+
</li></ul>
|
|
107
|
+
</li></ul>
|
|
108
|
+
|
|
109
|
+
<h2 id="label-Exposing+multiple+paths+in+the+same+component+-28calling+standalone+multiple+times-29">Exposing multiple paths in the same component (calling standalone multiple times)</h2>
|
|
110
|
+
|
|
111
|
+
<p>If your component loads data dynamically from a JavaScript front-end (e.g. implemented via Stimulus), you will find yourself in the situation where you need an extra route for a functionality that inherently belongs to the same component. Example use cases would be search fields that load data as the user types, maps that load tiles, dynamic photo galleries etc.</p>
|
|
112
|
+
|
|
113
|
+
<p>In this case, you can call <code>standalone</code> a second time and provide a name for your extra route:</p>
|
|
114
|
+
|
|
115
|
+
<pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_setup'>setup</span> <span class='kw'>do</span>
|
|
116
|
+
<span class='comment'># Regular route for rendering the content
|
|
117
|
+
</span> <span class='id identifier rubyid_standalone'>standalone</span> <span class='label'>path:</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>map/viewer</span><span class='tstring_end'>'</span></span> <span class='kw'>do</span>
|
|
118
|
+
<span class='id identifier rubyid_verb'>verb</span> <span class='symbol'>:get</span> <span class='kw'>do</span>
|
|
119
|
+
<span class='id identifier rubyid_authorize'>authorize</span> <span class='lbrace'>{</span> <span class='kw'>true</span> <span class='rbrace'>}</span>
|
|
120
|
+
<span class='kw'>end</span>
|
|
121
|
+
<span class='kw'>end</span>
|
|
122
|
+
|
|
123
|
+
<span class='comment'># Extra route for loading tiles via AJAX
|
|
124
|
+
</span> <span class='id identifier rubyid_standalone'>standalone</span> <span class='symbol'>:tiles</span><span class='comma'>,</span> <span class='label'>path:</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>map/viewer/tiles</span><span class='tstring_end'>'</span></span> <span class='kw'>do</span>
|
|
125
|
+
<span class='id identifier rubyid_verb'>verb</span> <span class='symbol'>:get</span> <span class='kw'>do</span>
|
|
126
|
+
<span class='id identifier rubyid_respond'>respond</span> <span class='kw'>do</span> <span class='comment'># Again: overriding `respond` skips authorization! This is why we don't need to provide an `authorize` block here.
|
|
127
|
+
</span> <span class='id identifier rubyid_controller'>controller</span><span class='period'>.</span><span class='id identifier rubyid_render'>render</span><span class='lparen'>(</span><span class='label'>json:</span> <span class='const'>MapTiler</span><span class='period'>.</span><span class='id identifier rubyid_load'>load</span><span class='lparen'>(</span><span class='id identifier rubyid_params'>params</span><span class='comma'>,</span> <span class='id identifier rubyid_current_ability'>current_ability</span><span class='rparen'>)</span><span class='rparen'>)</span> <span class='comment'># current_ability is provided by CanCanCan and made available by Compony.
|
|
128
|
+
</span> <span class='kw'>end</span>
|
|
129
|
+
<span class='kw'>end</span>
|
|
130
|
+
<span class='kw'>end</span>
|
|
131
|
+
|
|
132
|
+
<span class='comment'># More code for labelling, content etc.
|
|
133
|
+
</span><span class='kw'>end</span>
|
|
134
|
+
</code></pre>
|
|
135
|
+
|
|
136
|
+
<p>Please note that the idea here is to package things that belong together, not to provide different kinds of content in a single component. For displaying different pages, use multiple components and have each expose a single route.</p>
|
|
137
|
+
|
|
138
|
+
<h2 id="label-Naming+of+exposed+routes">Naming of exposed routes</h2>
|
|
139
|
+
|
|
140
|
+
<p>The routes to standalone components are named and you can point to them using Rails’ <code>..._path</code> and <code>..._url</code> helpers. The naming scheme is: <code>[standalone]<em>[component]</em>[family]_comp</code>. Examples:</p>
|
|
141
|
+
<ul><li>
|
|
142
|
+
<p>Default standalone: <code>Components::Users::Index</code> exports <code>index_users_comp</code> and thus <code>index_users_comp_path</code> can be used.</p>
|
|
143
|
+
</li><li>
|
|
144
|
+
<p>Named standalone: If <code>standalone :foo, path: ...</code> is used within <code>Components::Users::Index</code>, the exported name is <code>foo_index_users_comp</code>.</p>
|
|
145
|
+
</li></ul>
|
|
146
|
+
|
|
147
|
+
<h2 id="label-Handling+formats">Handling formats</h2>
|
|
148
|
+
|
|
149
|
+
<p>Compony is capable of responding to formats like Rails does. This is useful to deliver PDFs, CSV files etc. to a user from within Compony. This can be achieved by specifying the <code>respond</code> block:</p>
|
|
150
|
+
|
|
151
|
+
<pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_setup'>setup</span> <span class='kw'>do</span>
|
|
152
|
+
<span class='id identifier rubyid_standalone'>standalone</span> <span class='label'>path:</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>generate/report</span><span class='tstring_end'>'</span></span> <span class='kw'>do</span>
|
|
153
|
+
<span class='id identifier rubyid_verb'>verb</span> <span class='symbol'>:get</span> <span class='kw'>do</span>
|
|
154
|
+
<span class='comment'># Respond with a file when generate/report.pdf is GETed:
|
|
155
|
+
</span> <span class='id identifier rubyid_respond'>respond</span> <span class='symbol'>:pdf</span> <span class='kw'>do</span>
|
|
156
|
+
<span class='id identifier rubyid_file'>file</span><span class='comma'>,</span> <span class='id identifier rubyid_filename'>filename</span> <span class='op'>=</span> <span class='const'>PdfGenerator</span><span class='period'>.</span><span class='id identifier rubyid_generate'>generate</span><span class='lparen'>(</span><span class='id identifier rubyid_params'>params</span><span class='comma'>,</span> <span class='id identifier rubyid_current_ability'>current_ability</span><span class='rparen'>)</span>
|
|
157
|
+
<span class='id identifier rubyid_send_data'>send_data</span><span class='lparen'>(</span><span class='id identifier rubyid_file'>file</span><span class='comma'>,</span> <span class='label'>filename:</span><span class='comma'>,</span> <span class='label'>type:</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>application/pdf</span><span class='tstring_end'>'</span></span><span class='rparen'>)</span>
|
|
158
|
+
<span class='kw'>end</span>
|
|
159
|
+
<span class='comment'># If someone visits generate/report, issue a 404:
|
|
160
|
+
</span> <span class='id identifier rubyid_respond'>respond</span> <span class='kw'>do</span>
|
|
161
|
+
<span class='id identifier rubyid_fail'>fail</span> <span class='const'>ActionController</span><span class='op'>::</span><span class='const'>RoutingError</span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>Unsupported format - please make sure your URL ends with `.pdf`.</span><span class='tstring_end'>'</span></span>
|
|
162
|
+
<span class='kw'>end</span>
|
|
163
|
+
<span class='kw'>end</span>
|
|
164
|
+
<span class='kw'>end</span>
|
|
165
|
+
<span class='kw'>end</span>
|
|
166
|
+
</code></pre>
|
|
167
|
+
|
|
168
|
+
<h2 id="label-Redirect+in+respond+or+in+before_render-3F">Redirect in <code>respond</code> or in <code>before_render</code>?</h2>
|
|
169
|
+
|
|
170
|
+
<p>Rails controller redirects can be issued both in a verb DSL’s <code>respond</code> block and in <code>before_render</code>. The rule of thumb that tells you which way to go is:</p>
|
|
171
|
+
<ul><li>
|
|
172
|
+
<p>If you want to redirect depending on the HTTP verb, use <code>respond</code>.</p>
|
|
173
|
+
</li><li>
|
|
174
|
+
<p>If you want to redirect depending on params, state, time etc. <strong>independently of the HTTP verb</strong>, use <code>before_render</code>, as this is more convenient than writing a standalone -> verb -> respond tree.</p>
|
|
175
|
+
</li></ul>
|
|
176
|
+
|
|
177
|
+
<h2 id="label-Path+constraints">Path constraints</h2>
|
|
178
|
+
|
|
179
|
+
<p>When calling <code>standalone</code>, you may specify the keyword <code>constraints</code> that will be passed to the route. For example:</p>
|
|
180
|
+
|
|
181
|
+
<pre class="code ruby"><code class="ruby"><span class='comment'># In your component
|
|
182
|
+
</span><span class='id identifier rubyid_standelone'>standelone</span> <span class='label'>path:</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>/:lang</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='label'>constraints:</span> <span class='lbrace'>{</span> <span class='label'>lang:</span> <span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>([a-z]{2})?</span><span class='regexp_end'>/i</span></span> <span class='rbrace'>}</span>
|
|
183
|
+
|
|
184
|
+
<span class='comment'># This will automatically lead to a route of this form:
|
|
185
|
+
</span><span class='id identifier rubyid_get'>get</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>:lang</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='label'>constraints:</span> <span class='lbrace'>{</span> <span class='label'>lang:</span> <span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>([a-z]{2})?</span><span class='regexp_end'>/i</span></span> <span class='rbrace'>}</span>
|
|
186
|
+
</code></pre>
|
|
187
|
+
|
|
188
|
+
<h2 id="label-Passing+scopes">Passing scopes</h2>
|
|
189
|
+
|
|
190
|
+
<p>When calling <code>standalone</code>, you may specify the keyword <code>scope</code> to wrap the component’s Rails route into a route scope. Additionally, you may specify a hash <code>scope_args</code>, which will be passed as keyword arguments to the <code>scope</code> call in the route:</p>
|
|
191
|
+
|
|
192
|
+
<pre class="code ruby"><code class="ruby"><span class='comment'># In your component
|
|
193
|
+
</span><span class='id identifier rubyid_standalone'>standalone</span> <span class='label'>path:</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>/welcome</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='label'>scope:</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>(:lang)</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='label'>scope_args:</span> <span class='lbrace'>{</span> <span class='label'>lang:</span> <span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>([a-z]{2})?</span><span class='regexp_end'>/i</span></span> <span class='rbrace'>}</span> <span class='kw'>do</span>
|
|
194
|
+
<span class='id identifier rubyid_verb'>verb</span> <span class='symbol'>:get</span> <span class='kw'>do</span>
|
|
195
|
+
<span class='comment'># ....
|
|
196
|
+
</span> <span class='kw'>end</span>
|
|
197
|
+
<span class='kw'>end</span>
|
|
198
|
+
|
|
199
|
+
<span class='comment'># This will automatically lead to a route of this form:
|
|
200
|
+
</span><span class='id identifier rubyid_scope'>scope</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>(:lang)</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='label'>lang:</span> <span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>([a-z]{2})?</span><span class='regexp_end'>/i</span></span> <span class='kw'>do</span>
|
|
201
|
+
<span class='id identifier rubyid_get'>get</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>welcome</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='label'>to:</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>compony#your_component</span><span class='tstring_end'>'</span></span>
|
|
202
|
+
<span class='kw'>end</span>
|
|
203
|
+
</code></pre>
|
|
204
|
+
|
|
205
|
+
<h2 id="label-Customizing+path+generation">Customizing path generation</h2>
|
|
206
|
+
|
|
207
|
+
<p>By implementing <code>path do ... end</code> inside the <code>setup</code> method of a component, you can override the way paths to that component are generated. Customizing the path generation will affect all mentioned methods mentioned here involving paths, such as <code>Compony.path</code>, <code>render_intent</code> etc.</p>
|
|
208
|
+
|
|
209
|
+
<p>The block runs <strong>outside</strong> the request context, so build URLs via <code>Rails.application.routes.url_helpers</code> (not <code>controller</code>/<code>helpers</code>). It is given an optional model, positional path-helper args, the <code>standalone_name:</code> kwarg, and any extra kwargs.</p>
|
|
210
|
+
|
|
211
|
+
<p>This is an advanced usage. Refer to the default implementation of <code>Component</code>‘s <code>path_block</code> to see the baseline example.</p>
|
|
212
|
+
|
|
213
|
+
<p>Where overriding <code>path</code> is genuinely useful:</p>
|
|
214
|
+
<ul><li>
|
|
215
|
+
<p><strong>Inject a derived/looked-up param.</strong> Callers pass a high-level argument and the block turns it into concrete path params.</p>
|
|
216
|
+
</li><li>
|
|
217
|
+
<p><strong>Mint a signed token into the URL</strong> so an unauthenticated link can authorize itself — a full worked recipe is in <a href="/doc/guide/patterns_md.html#18-signed-token-capability-links-auth-less-onboarding--magic-links">Real-world patterns §18 (signed-token capability links)</a> (magic login, password reset, invite/confirm links).</p>
|
|
218
|
+
</li><li>
|
|
219
|
+
<p><strong>Custom slugs / vanity paths</strong> that differ from the Rails route helper’s default shape.</p>
|
|
220
|
+
</li></ul>
|
|
221
|
+
|
|
222
|
+
<p><a href="/README_md.html#guide--documentation">Guide index</a></p>
|
|
223
|
+
</div></div>
|
|
224
|
+
|
|
225
|
+
<div id="footer">
|
|
226
|
+
Generated on Mon May 18 13:55:33 2026 by
|
|
227
|
+
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
228
|
+
0.9.34 (ruby-3.3.5).
|
|
229
|
+
</div>
|
|
230
|
+
|
|
231
|
+
</div>
|
|
232
|
+
</body>
|
|
233
|
+
</html>
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>
|
|
7
|
+
File: virtual_models
|
|
8
|
+
|
|
9
|
+
— Documentation by YARD 0.9.34
|
|
10
|
+
|
|
11
|
+
</title>
|
|
12
|
+
|
|
13
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" />
|
|
14
|
+
|
|
15
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" />
|
|
16
|
+
|
|
17
|
+
<script type="text/javascript">
|
|
18
|
+
pathId = "virtual_models";
|
|
19
|
+
relpath = '';
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
|
24
|
+
|
|
25
|
+
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
</head>
|
|
29
|
+
<body>
|
|
30
|
+
<div class="nav_wrap">
|
|
31
|
+
<iframe id="nav" src="file_list.html?1"></iframe>
|
|
32
|
+
<div id="resizer"></div>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<div id="main" tabindex="-1">
|
|
36
|
+
<div id="header">
|
|
37
|
+
<div id="menu">
|
|
38
|
+
|
|
39
|
+
<a href="_index.html">Index</a> »
|
|
40
|
+
<span class="title">File: virtual_models</span>
|
|
41
|
+
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<div id="search">
|
|
45
|
+
|
|
46
|
+
<a class="full_list_link" id="class_list_link"
|
|
47
|
+
href="class_list.html">
|
|
48
|
+
|
|
49
|
+
<svg width="24" height="24">
|
|
50
|
+
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
|
51
|
+
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
|
52
|
+
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
|
53
|
+
</svg>
|
|
54
|
+
</a>
|
|
55
|
+
|
|
56
|
+
</div>
|
|
57
|
+
<div class="clear"></div>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<div id="content"><div id='filecontents'>
|
|
61
|
+
<p><a href="/README_md.html#guide--documentation">Back to the guide</a></p>
|
|
62
|
+
|
|
63
|
+
<h1 id="label-Unleashing+virtual+models+through+Compony-27s+ActiveType+integration">Unleashing virtual models through Compony’s <code>ActiveType</code> integration</h1>
|
|
64
|
+
|
|
65
|
+
<p>Compony explicitely supports using virtual models using the <code>active_type</code> gem for its resourceful components. However, when doing so, your model should inherit from <code>Compony::VirtualModel</code> rather than from <code>ActiveType::Object</code>.</p>
|
|
66
|
+
|
|
67
|
+
<p>Combining Compony with virtual models enables programming patterns that are extremely powerful for use cases such as non-persistent wizards, filter forms, stateless launch forms for generators and much more.</p>
|
|
68
|
+
|
|
69
|
+
<p>For instance, let us consider an application that that generates configurable reports. In this example, the user workflow is to click on a “Generate report” button, fill in a configuration form (what kind of report the generator should produce, what timespan should be considered, which criteria to filter and group by etc.), and, by submitting the form, queueing a job that will perform the report in the background. To realize this, a simple approach would be the following:</p>
|
|
70
|
+
<ul><li>
|
|
71
|
+
<p>Add the <code>active_type</code> gem to your <code>Gemfile</code> and run <code>bundle install</code>.</p>
|
|
72
|
+
</li><li>
|
|
73
|
+
<p>Implement <code>Components::Reports::Request</code> which inherits from <code>Compony::Components::New</code>.</p>
|
|
74
|
+
</li><li>
|
|
75
|
+
<p>In the top section of the component class, define a class <code>VirtualModel < Compony::VirtualModel</code> (within the namespace of <code>Components::Reports::Request</code>). Use <code>active_type</code>‘s <code>attribute</code> method to add virtual columns for any kind of information your generator will need. Call Compony’s <code>field</code> method as you would with a normal Rails model and implement any suitable Rails validations. You may even use Rails associations such as <code>belongs_to</code> to a real (database-backed) Rails model by implementing an attribute with the following three lines:</p>
|
|
76
|
+
<ul><li>
|
|
77
|
+
<p><code>attribute :user_id, :bigint</code> (provided by <code>active_type</code>)</p>
|
|
78
|
+
</li><li>
|
|
79
|
+
<p><code>belongs_to :user</code> (provided by Rails)</p>
|
|
80
|
+
</li><li>
|
|
81
|
+
<p><code>field :user, :association</code> (provided by Compony)</p>
|
|
82
|
+
</li></ul>
|
|
83
|
+
</li><li>
|
|
84
|
+
<p>Implement <code>Components::Reports::RequestForm < Compony::Components::Form</code> and implement your configuration form there.</p>
|
|
85
|
+
</li><li>
|
|
86
|
+
<p>In your <code>Components::Reports::Request</code>:</p>
|
|
87
|
+
<ul><li>
|
|
88
|
+
<p>Call <code>standalone path: '/reports/request'</code> to avoid path conflicts with other components in the <code>Components::Reports</code> namespace inheriting from <code>New</code>.</p>
|
|
89
|
+
</li><li>
|
|
90
|
+
<p>Call <code>data_class VirtualModel</code> to tell the component to use the class you just created within the component’s namespace.</p>
|
|
91
|
+
</li><li>
|
|
92
|
+
<p>Call <code>form_comp_class Components::Reports::RequestForm</code> to inform the component to use the custom named form.</p>
|
|
93
|
+
</li><li>
|
|
94
|
+
<p>Call something like <code>label(:all) { ... }</code> to set a label for your component.</p>
|
|
95
|
+
</li><li>
|
|
96
|
+
<p>Implement <code>on_created_respond</code> to create the report job and redirect to a suitable location.</p>
|
|
97
|
+
</li></ul>
|
|
98
|
+
</li></ul>
|
|
99
|
+
|
|
100
|
+
<p>Why this works: As your <code>Components::Reports::Request</code> inherits from Compony’s <code>New</code> component, Compony will believe that the user is about to create a new resource, providing the Compony equivalents for the Rails controller actions <code>new</code> and <code>create</code>. When the user submits the form, Compony will run validations, re-render the form with error messages if they fail, or otherwise call <code>@data.save</code> which does nothing since the model is only virtual. This is why you take back control by overriding the <code>on_created_respond</code> block, which is called only if all validations have passed.</p>
|
|
101
|
+
|
|
102
|
+
<p>Note: it is even possible to combine this pattern with Rails’ <code>accepts_nested_attributes_for</code> and <code>simple_form</code>‘s <code>f.simple_fields_for</code> call, where the nested object is a real database-backed model. Even though the component’s resource is purely virtual, Rails will create or update the nested model when Compony calls <code>save</code> on the parent resource. This allows for very fast implementation of business logic creating multiple objects from a single form post by wrapping the resources in a virtual model.</p>
|
|
103
|
+
|
|
104
|
+
<p>If you intend to use this technique in combination with <code>ActiveStorage</code>, you must also override the <code>store_data</code> block to just validate the model instead of saving it, as the hook creating the attachment is bound to fail (the virtual model does not exist in the database and thus cannot be referenced from <code>ActiveStorage::Attachment</code>). For the same reason, you cannot call <code>blob.download</code>, but must find the file’s tempfile in the request parameters in order to process the file attached by the user.</p>
|
|
105
|
+
|
|
106
|
+
<p><a href="/README_md.html#guide--documentation">Guide index</a></p>
|
|
107
|
+
</div></div>
|
|
108
|
+
|
|
109
|
+
<div id="footer">
|
|
110
|
+
Generated on Mon May 18 13:55:33 2026 by
|
|
111
|
+
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
112
|
+
0.9.34 (ruby-3.3.5).
|
|
113
|
+
</div>
|
|
114
|
+
|
|
115
|
+
</div>
|
|
116
|
+
</body>
|
|
117
|
+
</html>
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>
|
|
7
|
+
File: with_form
|
|
8
|
+
|
|
9
|
+
— Documentation by YARD 0.9.34
|
|
10
|
+
|
|
11
|
+
</title>
|
|
12
|
+
|
|
13
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" />
|
|
14
|
+
|
|
15
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" />
|
|
16
|
+
|
|
17
|
+
<script type="text/javascript">
|
|
18
|
+
pathId = "with_form";
|
|
19
|
+
relpath = '';
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
|
24
|
+
|
|
25
|
+
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
</head>
|
|
29
|
+
<body>
|
|
30
|
+
<div class="nav_wrap">
|
|
31
|
+
<iframe id="nav" src="file_list.html?1"></iframe>
|
|
32
|
+
<div id="resizer"></div>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<div id="main" tabindex="-1">
|
|
36
|
+
<div id="header">
|
|
37
|
+
<div id="menu">
|
|
38
|
+
|
|
39
|
+
<a href="_index.html">Index</a> »
|
|
40
|
+
<span class="title">File: with_form</span>
|
|
41
|
+
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<div id="search">
|
|
45
|
+
|
|
46
|
+
<a class="full_list_link" id="class_list_link"
|
|
47
|
+
href="class_list.html">
|
|
48
|
+
|
|
49
|
+
<svg width="24" height="24">
|
|
50
|
+
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
|
51
|
+
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
|
52
|
+
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
|
53
|
+
</svg>
|
|
54
|
+
</a>
|
|
55
|
+
|
|
56
|
+
</div>
|
|
57
|
+
<div class="clear"></div>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<div id="content"><div id='filecontents'><ul><li>
|
|
61
|
+
<p><a href="/README_md.html#guide--documentation">Back to the guide</a></p>
|
|
62
|
+
</li><li>
|
|
63
|
+
<p><a href="/doc/guide/pre_built_components_md.html">List of pre-built components</a></p>
|
|
64
|
+
</li></ul>
|
|
65
|
+
|
|
66
|
+
<h1 id="label-Pre-built+components-3A+WithForm">Pre-built components: WithForm</h1>
|
|
67
|
+
|
|
68
|
+
<p><code>Compony::Components::WithForm</code> is the abstract base for components that render and submit a form. It is <strong>twinned</strong> with a href="./form_md.html"></a> component: WithForm provides the route, authorization and resource handling; the Form provides the inputs and param schema. href="./new_md.html"></a> and href="./edit_md.html"></a> both inherit from WithForm — you rarely subclass it directly, but understanding the twinning explains how they work.</p>
|
|
69
|
+
|
|
70
|
+
<p>A WithForm component may be resourceful (New/Edit are) but does not have to be.</p>
|
|
71
|
+
|
|
72
|
+
<h2 id="label-How+the+twinning+works">How the twinning works</h2>
|
|
73
|
+
<ul><li>
|
|
74
|
+
<p><code>form_comp</code> returns the Form instance, built lazily. It defaults to the component named <code>Form</code> in the <strong>same family</strong>, instantiated with this component as <code>parent_comp</code> and passed <code>submit_verb</code>, <code>submit_path</code> and <code>cancancan_action</code>.</p>
|
|
75
|
+
</li><li>
|
|
76
|
+
<p>The Form renders inside this component’s <code>content</code> (e.g. New/Edit do <code>concat form_comp.render(controller, data: @data)</code>).</p>
|
|
77
|
+
</li><li>
|
|
78
|
+
<p>The form’s <code><form></code> posts back to <code>submit_path</code> using <code>submit_verb</code>; that same component handles the submit verb (POST for New, PATCH for Edit) and runs the resourceful lifecycle (<code>assign_attributes</code> → <code>store_data</code> → <code>respond</code>).</p>
|
|
79
|
+
</li></ul>
|
|
80
|
+
|
|
81
|
+
<h2 id="label-DSL+methods">DSL methods</h2>
|
|
82
|
+
|
|
83
|
+
<table role="table">
|
|
84
|
+
<thead>
|
|
85
|
+
<tr>
|
|
86
|
+
<th>Method</th>
|
|
87
|
+
<th>Signature</th>
|
|
88
|
+
<th>Description</th>
|
|
89
|
+
</tr>
|
|
90
|
+
</thead>
|
|
91
|
+
<tbody>
|
|
92
|
+
<tr>
|
|
93
|
+
<td>‘submit_verb`</td>
|
|
94
|
+
<td>‘submit_verb(:patch)`</td>
|
|
95
|
+
<td>HTTP verb the twinned form submits with. Mandatory (New sets ‘:post`, Edit `:patch`).</td>
|
|
96
|
+
</tr>
|
|
97
|
+
<tr>
|
|
98
|
+
<td>‘form_comp_class`</td>
|
|
99
|
+
<td>‘form_comp_class(Components::Users::SignupForm)`</td>
|
|
100
|
+
<td>Use a specific Form class instead of the same-family ‘Form`.</td>
|
|
101
|
+
</tr>
|
|
102
|
+
<tr>
|
|
103
|
+
<td>‘submit_path`</td>
|
|
104
|
+
<td>‘submit_path { Compony.path(:create, :users) }`</td>
|
|
105
|
+
<td>Override where the form submits. Block is given the controller; defaults to this component’s own path.</td>
|
|
106
|
+
</tr>
|
|
107
|
+
<tr>
|
|
108
|
+
<td>‘form_cancancan_action`</td>
|
|
109
|
+
<td>‘form_cancancan_action(:edit)`</td>
|
|
110
|
+
<td>CanCanCan action used by the Form for per-field ‘permitted_attributes` (New sets `:new`, Edit `:edit`). Pass `nil` to disable per-field auth.</td>
|
|
111
|
+
</tr>
|
|
112
|
+
<tr>
|
|
113
|
+
<td>‘form_comp`</td>
|
|
114
|
+
<td>‘form_comp`</td>
|
|
115
|
+
<td>(Not DSL — a reader.) The Form instance; override in a subclass for full control.</td>
|
|
116
|
+
</tr>
|
|
117
|
+
</tbody>
|
|
118
|
+
</table>
|
|
119
|
+
|
|
120
|
+
<h2 id="label-Example-3A+a+custom+non-default+form">Example: a custom non-default form</h2>
|
|
121
|
+
|
|
122
|
+
<pre class="code ruby"><code class="ruby"><span class='kw'>class</span> <span class='const'><span class='object_link'><a href="Components.html" title="Components (module)">Components</a></span></span><span class='op'>::</span><span class='const'>Users</span><span class='op'>::</span><span class='const'>Signup</span> <span class='op'><</span> <span class='const'><span class='object_link'><a href="Compony.html" title="Compony (module)">Compony</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Compony/Components.html" title="Compony::Components (module)">Components</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Compony/Components/New.html" title="Compony::Components::New (class)">New</a></span></span>
|
|
123
|
+
<span class='id identifier rubyid_setup'>setup</span> <span class='kw'>do</span>
|
|
124
|
+
<span class='id identifier rubyid_standalone'>standalone</span> <span class='label'>path:</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>signup</span><span class='tstring_end'>'</span></span> <span class='kw'>do</span>
|
|
125
|
+
<span class='id identifier rubyid_skip_authentication!'>skip_authentication!</span>
|
|
126
|
+
<span class='id identifier rubyid_verb'>verb</span> <span class='symbol'>:get</span> <span class='kw'>do</span> <span class='id identifier rubyid_authorize'>authorize</span> <span class='lbrace'>{</span> <span class='kw'>true</span> <span class='rbrace'>}</span> <span class='kw'>end</span>
|
|
127
|
+
<span class='id identifier rubyid_verb'>verb</span> <span class='symbol'>:post</span> <span class='kw'>do</span> <span class='id identifier rubyid_authorize'>authorize</span> <span class='lbrace'>{</span> <span class='kw'>true</span> <span class='rbrace'>}</span> <span class='kw'>end</span>
|
|
128
|
+
<span class='kw'>end</span>
|
|
129
|
+
<span class='id identifier rubyid_form_comp_class'>form_comp_class</span> <span class='const'><span class='object_link'><a href="Components.html" title="Components (module)">Components</a></span></span><span class='op'>::</span><span class='const'>Users</span><span class='op'>::</span><span class='const'>SignupForm</span> <span class='comment'># not the default Users::Form
|
|
130
|
+
</span> <span class='id identifier rubyid_on_created_redirect_path'>on_created_redirect_path</span> <span class='lbrace'>{</span> <span class='const'><span class='object_link'><a href="Compony.html" title="Compony (module)">Compony</a></span></span><span class='period'>.</span><span class='id identifier rubyid_path'><span class='object_link'><a href="Compony.html#path-class_method" title="Compony.path (method)">path</a></span></span><span class='lparen'>(</span><span class='symbol'>:show</span><span class='comma'>,</span> <span class='ivar'>@data</span><span class='rparen'>)</span> <span class='rbrace'>}</span>
|
|
131
|
+
<span class='kw'>end</span>
|
|
132
|
+
<span class='kw'>end</span>
|
|
133
|
+
|
|
134
|
+
<span class='kw'>class</span> <span class='const'><span class='object_link'><a href="Components.html" title="Components (module)">Components</a></span></span><span class='op'>::</span><span class='const'>Users</span><span class='op'>::</span><span class='const'>SignupForm</span> <span class='op'><</span> <span class='const'><span class='object_link'><a href="Compony.html" title="Compony (module)">Compony</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Compony/Components.html" title="Compony::Components (module)">Components</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Compony/Components/Form.html" title="Compony::Components::Form (class)">Form</a></span></span>
|
|
135
|
+
<span class='id identifier rubyid_setup'>setup</span> <span class='kw'>do</span>
|
|
136
|
+
<span class='id identifier rubyid_form_fields'>form_fields</span> <span class='kw'>do</span>
|
|
137
|
+
<span class='id identifier rubyid_concat'>concat</span> <span class='id identifier rubyid_field'>field</span><span class='lparen'>(</span><span class='symbol'>:email</span><span class='rparen'>)</span>
|
|
138
|
+
<span class='id identifier rubyid_concat'>concat</span> <span class='id identifier rubyid_pw_field'>pw_field</span><span class='lparen'>(</span><span class='symbol'>:password</span><span class='rparen'>)</span>
|
|
139
|
+
<span class='kw'>end</span>
|
|
140
|
+
<span class='id identifier rubyid_schema_field'>schema_field</span> <span class='symbol'>:email</span>
|
|
141
|
+
<span class='id identifier rubyid_schema_pw_field'>schema_pw_field</span> <span class='symbol'>:password</span>
|
|
142
|
+
<span class='kw'>end</span>
|
|
143
|
+
<span class='kw'>end</span>
|
|
144
|
+
</code></pre>
|
|
145
|
+
|
|
146
|
+
<p>For the full submit/redirect behavior see href="./new_md.html"></a> and href="./edit_md.html"></a>; for the form input/schema DSL see href="./form_md.html"></a>; for the lifecycle hooks see <a href="/doc/guide/resourceful_md.html">Resourceful</a>. Multi-step and clone flows that reuse this machinery are in <a href="../patterns_md.html#11-non-crud-job-dispatch-toggles-clone">Real-world patterns</a>.</p>
|
|
147
|
+
</div></div>
|
|
148
|
+
|
|
149
|
+
<div id="footer">
|
|
150
|
+
Generated on Mon May 18 13:55:33 2026 by
|
|
151
|
+
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
152
|
+
0.9.34 (ruby-3.3.5).
|
|
153
|
+
</div>
|
|
154
|
+
|
|
155
|
+
</div>
|
|
156
|
+
</body>
|
|
157
|
+
</html>
|