compony 0.11.11 → 0.11.13
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/.rspec +2 -0
- data/CHANGELOG.md +13 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +145 -106
- data/README.md +12 -1
- data/Rakefile +10 -0
- data/TODO.md +2 -1
- data/VERSION +1 -1
- data/compony.gemspec +5 -3
- data/config/locales/es.yml +46 -0
- data/doc/ComponentGenerator.html +1 -1
- data/doc/Components.html +1 -1
- data/doc/ComponentsGenerator.html +1 -1
- data/doc/Compony/Component.html +1 -1
- 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 +1 -1
- data/doc/Compony/ComponentMixins/Default/Standalone/VerbDsl.html +1 -1
- data/doc/Compony/ComponentMixins/Default/Standalone.html +1 -1
- data/doc/Compony/ComponentMixins/Default.html +1 -1
- data/doc/Compony/ComponentMixins/Resourceful.html +1 -1
- 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 +1 -1
- data/doc/Compony/Components/Edit.html +1 -1
- data/doc/Compony/Components/Form.html +1 -1
- data/doc/Compony/Components/Index.html +1 -1
- data/doc/Compony/Components/List.html +1 -1
- data/doc/Compony/Components/New.html +1 -1
- data/doc/Compony/Components/Show.html +1 -1
- data/doc/Compony/Components/WithForm.html +1 -1
- 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 +1 -1
- data/doc/Compony/ManageIntentsDsl.html +2 -2
- 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 +8 -2
- 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 +1 -1
- data/doc/file.CHANGELOG.html +88 -76
- data/doc/file.README.html +21 -11
- data/doc/file.basic_component.html +14 -14
- data/doc/file.cookbook.html +27 -27
- data/doc/file.destroy.html +2 -2
- data/doc/file.dsl_reference.html +199 -199
- data/doc/file.edit.html +3 -3
- data/doc/file.example.html +13 -13
- data/doc/file.example_advanced.html +10 -10
- data/doc/file.feasibility.html +2 -2
- data/doc/file.form.html +7 -7
- data/doc/file.generators.html +3 -3
- data/doc/file.glossary.html +44 -44
- data/doc/file.gotchas.html +35 -35
- data/doc/file.index.html +10 -10
- data/doc/file.inheritance.html +5 -5
- data/doc/file.installation.html +9 -9
- data/doc/file.integrations.html +46 -46
- data/doc/file.intents.html +11 -11
- data/doc/file.internal_datastructures.html +6 -6
- data/doc/file.list.html +35 -35
- data/doc/file.maintaining.html +21 -21
- data/doc/file.model_fields.html +3 -3
- data/doc/file.nesting.html +5 -5
- data/doc/file.new.html +3 -3
- data/doc/file.ownership.html +2 -2
- data/doc/file.patterns.html +50 -50
- data/doc/file.pre_built_components.html +2 -2
- data/doc/file.resourceful.html +5 -5
- data/doc/file.show.html +17 -17
- data/doc/file.standalone.html +12 -12
- data/doc/file.virtual_models.html +2 -2
- data/doc/file.with_form.html +23 -23
- data/doc/index.html +21 -11
- data/doc/top-level-namespace.html +1 -1
- data/lib/compony/model_fields/base.rb +3 -0
- data/spec/README.md +22 -0
- data/spec/compony/component_spec.rb +80 -0
- data/spec/compony/compony_spec.rb +102 -0
- data/spec/compony/intent_spec.rb +94 -0
- data/spec/compony/method_accessible_hash_spec.rb +32 -0
- data/spec/compony/model_fields_spec.rb +70 -0
- data/spec/compony/model_mixin_spec.rb +81 -0
- data/spec/compony/natural_ordering_spec.rb +61 -0
- data/spec/dummy/app/components/statics/home.rb +17 -0
- data/spec/dummy/app/components/statics/secret.rb +15 -0
- data/spec/dummy/app/components/users/destroy.rb +2 -0
- data/spec/dummy/app/components/users/edit.rb +2 -0
- data/spec/dummy/app/components/users/form.rb +14 -0
- data/spec/dummy/app/components/users/index.rb +29 -0
- data/spec/dummy/app/components/users/new.rb +2 -0
- data/spec/dummy/app/components/users/show.rb +26 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/models/ability.rb +7 -0
- data/spec/dummy/app/models/application_record.rb +4 -0
- data/spec/dummy/app/models/user.rb +22 -0
- data/spec/dummy/app/views/layouts/application.html.erb +7 -0
- data/spec/dummy/config/application.rb +20 -0
- data/spec/dummy/config/database.yml +3 -0
- data/spec/dummy/config/environment.rb +3 -0
- data/spec/dummy/config/initializers/simple_form.rb +9 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/db/schema.rb +14 -0
- data/spec/rails_helper.rb +23 -0
- data/spec/requests/authorization_spec.rb +16 -0
- data/spec/requests/plain_component_spec.rb +9 -0
- data/spec/requests/routing_spec.rb +20 -0
- data/spec/requests/users_crud_spec.rb +99 -0
- metadata +63 -1
data/doc/file.gotchas.html
CHANGED
|
@@ -60,20 +60,20 @@
|
|
|
60
60
|
<div id="content"><div id='filecontents'>
|
|
61
61
|
<p><a href="/README_md.html#guide--documentation">Back to the guide</a></p>
|
|
62
62
|
|
|
63
|
-
<h1 id="
|
|
63
|
+
<h1 id="gotchas--anti-patterns">Gotchas / anti-patterns</h1>
|
|
64
64
|
|
|
65
65
|
<p>Known footguns, each with <strong>symptom → cause → fix</strong>. Skim before debugging.</p>
|
|
66
66
|
|
|
67
|
-
<h3 id="
|
|
67
|
+
<h3 id="1-standalone-without-an-explicit-path">1. <code>standalone</code> without an explicit <code>path:</code></h3>
|
|
68
68
|
<ul><li>
|
|
69
69
|
<p><strong>Symptom:</strong> <code>undefined method '..._comp_path'</code>, or no route generated for the component.</p>
|
|
70
70
|
</li><li>
|
|
71
71
|
<p><strong>Cause:</strong> <code>standalone</code> only emits a route when a <code>path:</code> is given.</p>
|
|
72
72
|
</li><li>
|
|
73
|
-
<p><strong>Fix:</strong> Always pass <code>standalone path: 'users/show/:id' do ... end</code>. A component with no
|
|
73
|
+
<p><strong>Fix:</strong> Always pass <code>standalone path: 'users/show/:id' do ... end</code>. A component with no standalone is valid but must be nested in another component (has no URL).</p>
|
|
74
74
|
</li></ul>
|
|
75
75
|
|
|
76
|
-
<h3 id="
|
|
76
|
+
<h3 id="2-renderintent--rendersubcomp-output-not-appearing">2. <code>render_intent</code> / <code>render_sub_comp</code> output not appearing</h3>
|
|
77
77
|
<ul><li>
|
|
78
78
|
<p><strong>Symptom:</strong> The button/list silently missing from the rendered page.</p>
|
|
79
79
|
</li><li>
|
|
@@ -82,25 +82,25 @@
|
|
|
82
82
|
<p><strong>Fix:</strong> Wrap it: <code>concat render_intent(:edit, user)</code> (Dyny’s equivalent of <code><%= %></code>).</p>
|
|
83
83
|
</li></ul>
|
|
84
84
|
|
|
85
|
-
<h3 id="
|
|
85
|
+
<h3 id="3-overriding-respond-skips-authorization">3. Overriding <code>respond</code> skips authorization</h3>
|
|
86
86
|
<ul><li>
|
|
87
87
|
<p><strong>Symptom:</strong> An endpoint is reachable without the expected permission check.</p>
|
|
88
88
|
</li><li>
|
|
89
|
-
<p><strong>Cause:</strong> <code>authorize</code> is evaluated inside the <em>default</em> <code>respond</code>. A custom <code>respond</code>
|
|
89
|
+
<p><strong>Cause:</strong> <code>authorize</code> is evaluated inside the <em>default</em> <code>respond</code>. A custom <code>respond</code> (especially the <code>nil</code>/all-formats one) replaces it.</p>
|
|
90
90
|
</li><li>
|
|
91
|
-
<p><strong>Fix:</strong> Re-check authorization yourself inside the custom <code>respond</code>, or keep a separate
|
|
91
|
+
<p><strong>Fix:</strong> Re-check authorization yourself inside the custom <code>respond</code>, or keep a separate default <code>respond</code> for the relevant format.</p>
|
|
92
92
|
</li></ul>
|
|
93
93
|
|
|
94
|
-
<h3 id="
|
|
94
|
+
<h3 id="4-schemafield-with-the-foreign-key-name">4. <code>schema_field</code> with the foreign key name</h3>
|
|
95
95
|
<ul><li>
|
|
96
96
|
<p><strong>Symptom:</strong> Association param rejected by Schemacop / not assigned.</p>
|
|
97
97
|
</li><li>
|
|
98
98
|
<p><strong>Cause:</strong> Compony adds <code>_id</code> for associations automatically.</p>
|
|
99
99
|
</li><li>
|
|
100
|
-
<p><strong>Fix:</strong> Use the <strong>association name</strong>: <code>schema_field :author</code>, not <code>schema_field :author_id</code>.
|
|
100
|
+
<p><strong>Fix:</strong> Use the <strong>association name</strong>: <code>schema_field :author</code>, not <code>schema_field :author_id</code>. Same for <code>field :author</code> in <code>form_fields</code>.</p>
|
|
101
101
|
</li></ul>
|
|
102
102
|
|
|
103
|
-
<h3 id="
|
|
103
|
+
<h3 id="5-model-without-label">5. Model without <code>label</code></h3>
|
|
104
104
|
<ul><li>
|
|
105
105
|
<p><strong>Symptom:</strong> Errors or blank text when Compony renders titles/links for the model.</p>
|
|
106
106
|
</li><li>
|
|
@@ -109,16 +109,16 @@
|
|
|
109
109
|
<p><strong>Fix:</strong> Implement <code>def label</code> on every Compony model (or have a <code>label</code> column).</p>
|
|
110
110
|
</li></ul>
|
|
111
111
|
|
|
112
|
-
<h3 id="
|
|
112
|
+
<h3 id="6-forgetting-to-forward-args-in-a-custom-initialize">6. Forgetting to forward args in a custom <code>initialize</code></h3>
|
|
113
113
|
<ul><li>
|
|
114
114
|
<p><strong>Symptom:</strong> <code>parent_comp</code>, <code>@data</code>, comp opts mysteriously <code>nil</code>; nesting broken.</p>
|
|
115
115
|
</li><li>
|
|
116
116
|
<p><strong>Cause:</strong> The base initializer wires essential state. Skipping <code>super</code> drops it.</p>
|
|
117
117
|
</li><li>
|
|
118
|
-
<p><strong>Fix:</strong> Call <code>super(*args, **kwargs, &block)</code> first, then set your own ivars. Prefer
|
|
118
|
+
<p><strong>Fix:</strong> Call <code>super(*args, **kwargs, &block)</code> first, then set your own ivars. Prefer putting logic in <code>setup</code> instead of overriding <code>initialize</code>.</p>
|
|
119
119
|
</li></ul>
|
|
120
120
|
|
|
121
|
-
<h3 id="
|
|
121
|
+
<h3 id="7-reading-a-label-without-its-block-argument">7. Reading a label without its block argument</h3>
|
|
122
122
|
<ul><li>
|
|
123
123
|
<p><strong>Symptom:</strong> <code>wrong number of arguments</code> from a label block.</p>
|
|
124
124
|
</li><li>
|
|
@@ -127,7 +127,7 @@
|
|
|
127
127
|
<p><strong>Fix:</strong> <code>label(User.first)</code> for resourceful; <code>label</code> (no arg) otherwise. At most one arg.</p>
|
|
128
128
|
</li></ul>
|
|
129
129
|
|
|
130
|
-
<h3 id="
|
|
130
|
+
<h3 id="8-content-name-inside-a-block-tries-to-render-another-components-block">8. <code>content :name</code> inside a block tries to render another component’s block</h3>
|
|
131
131
|
<ul><li>
|
|
132
132
|
<p><strong>Symptom:</strong> Content block not found / unexpected output.</p>
|
|
133
133
|
</li><li>
|
|
@@ -136,25 +136,25 @@
|
|
|
136
136
|
<p><strong>Fix:</strong> To embed another component use <code>render_sub_comp</code>, not nested <code>content</code>.</p>
|
|
137
137
|
</li></ul>
|
|
138
138
|
|
|
139
|
-
<h3 id="
|
|
139
|
+
<h3 id="9-multiple-pages-in-one-component">9. Multiple pages in one component</h3>
|
|
140
140
|
<ul><li>
|
|
141
141
|
<p><strong>Symptom:</strong> Tangled <code>standalone</code>/<code>verb</code>/<code>respond</code> tree, confusing routes.</p>
|
|
142
142
|
</li><li>
|
|
143
|
-
<p><strong>Cause:</strong> Extra <code>standalone</code> calls are for <em>companion</em> endpoints (AJAX tiles, autocomplete
|
|
143
|
+
<p><strong>Cause:</strong> Extra <code>standalone</code> calls are for <em>companion</em> endpoints (AJAX tiles, autocomplete JSON) of the <em>same</em> screen — not for separate pages.</p>
|
|
144
144
|
</li><li>
|
|
145
|
-
<p><strong>Fix:</strong> One screen = one component exposing one main route. Make another component for
|
|
145
|
+
<p><strong>Fix:</strong> One screen = one component exposing one main route. Make another component for another page.</p>
|
|
146
146
|
</li></ul>
|
|
147
147
|
|
|
148
|
-
<h3 id="
|
|
148
|
+
<h3 id="10-resourceful-component-on-a-path-without-id">10. Resourceful component on a path without <code>:id</code></h3>
|
|
149
149
|
<ul><li>
|
|
150
150
|
<p><strong>Symptom:</strong> <code>Couldn't find <Model> without an ID</code> (e.g. an Index at <code>/users</code>).</p>
|
|
151
151
|
</li><li>
|
|
152
152
|
<p><strong>Cause:</strong> Default <code>load_data</code> does <code>data_class.find(params[:id])</code>.</p>
|
|
153
153
|
</li><li>
|
|
154
|
-
<p><strong>Fix:</strong> Override <code>load_data { @data = User.all }</code> (or your scope) for collection/index
|
|
154
|
+
<p><strong>Fix:</strong> Override <code>load_data { @data = User.all }</code> (or your scope) for collection/index components.</p>
|
|
155
155
|
</li></ul>
|
|
156
156
|
|
|
157
|
-
<h3 id="
|
|
157
|
+
<h3 id="11-redirectto-with-a-hardcoded-path">11. <code>redirect_to</code> with a hardcoded path</h3>
|
|
158
158
|
<ul><li>
|
|
159
159
|
<p><strong>Symptom:</strong> Links break after renaming/moving a component.</p>
|
|
160
160
|
</li><li>
|
|
@@ -163,56 +163,56 @@
|
|
|
163
163
|
<p><strong>Fix:</strong> Use <code>redirect_to Compony.path(:index, :users)</code> / <code>Compony.path(:show, @data)</code>.</p>
|
|
164
164
|
</li></ul>
|
|
165
165
|
|
|
166
|
-
<h3 id="
|
|
166
|
+
<h3 id="12-activestorage-attachment-on-a-virtual-model">12. ActiveStorage attachment on a virtual model</h3>
|
|
167
167
|
<ul><li>
|
|
168
168
|
<p><strong>Symptom:</strong> Uploaded file not persisted for a <code>Compony::VirtualModel</code>.</p>
|
|
169
169
|
</li><li>
|
|
170
|
-
<p><strong>Cause:</strong> Virtual models aren’t backed by a real table; the default <code>store_data</code> save
|
|
170
|
+
<p><strong>Cause:</strong> Virtual models aren’t backed by a real table; the default <code>store_data</code> save doesn’t persist attachments.</p>
|
|
171
171
|
</li><li>
|
|
172
|
-
<p><strong>Fix:</strong> Override <code>store_data</code> to only validate (<code>@create_succeeded = @data.validate</code>) and
|
|
172
|
+
<p><strong>Fix:</strong> Override <code>store_data</code> to only validate (<code>@create_succeeded = @data.validate</code>) and perform the real mutation/attachment in <code>on_created_respond</code>. See <a href="/doc/guide/virtual_models_md.html">virtual_models.md</a>.</p>
|
|
173
173
|
</li></ul>
|
|
174
174
|
|
|
175
|
-
<h3 id="
|
|
175
|
+
<h3 id="13-tailwindcss-rails-purges-compony-styles">13. <code>tailwindcss-rails</code> purges Compony styles</h3>
|
|
176
176
|
<ul><li>
|
|
177
177
|
<p><strong>Symptom:</strong> Compony component markup unstyled in production.</p>
|
|
178
178
|
</li><li>
|
|
179
|
-
<p><strong>Cause:</strong> Tailwind’s unused-CSS purge doesn’t scan component classes (their HTML isn’t in
|
|
179
|
+
<p><strong>Cause:</strong> Tailwind’s unused-CSS purge doesn’t scan component classes (their HTML isn’t in <code>app/views</code>).</p>
|
|
180
180
|
</li><li>
|
|
181
|
-
<p><strong>Fix:</strong> Safelist the classes, or don’t use <code>tailwindcss-rails</code> with Compony (see
|
|
181
|
+
<p><strong>Fix:</strong> Safelist the classes, or don’t use <code>tailwindcss-rails</code> with Compony (see README “Caveats”).</p>
|
|
182
182
|
</li></ul>
|
|
183
183
|
|
|
184
|
-
<h3 id="
|
|
184
|
+
<h3 id="14-public-endpoint-still-401redirecting">14. Public endpoint still 401/redirecting</h3>
|
|
185
185
|
<ul><li>
|
|
186
186
|
<p><strong>Symptom:</strong> Webhook/public action blocked by app auth or CSRF.</p>
|
|
187
187
|
</li><li>
|
|
188
|
-
<p><strong>Cause:</strong> <code>skip_authentication!</code> alone doesn’t remove CSRF, and <code>authorize</code> is still
|
|
188
|
+
<p><strong>Cause:</strong> <code>skip_authentication!</code> alone doesn’t remove CSRF, and <code>authorize</code> is still mandatory.</p>
|
|
189
189
|
</li><li>
|
|
190
|
-
<p><strong>Fix:</strong> In the standalone: <code>skip_authentication!</code> + <code>skip_forgery_protection!</code>, and in
|
|
190
|
+
<p><strong>Fix:</strong> In the standalone: <code>skip_authentication!</code> + <code>skip_forgery_protection!</code>, and in the verb <code>authorize { true }</code> (then validate a bearer token yourself).</p>
|
|
191
191
|
</li></ul>
|
|
192
192
|
|
|
193
|
-
<h3 id="
|
|
193
|
+
<h3 id="15-hand-rolled-endpoint-where-a-pre-built-crud-component-exists">15. Hand-rolled endpoint where a pre-built CRUD component exists</h3>
|
|
194
194
|
<ul><li>
|
|
195
|
-
<p><strong>Symptom:</strong> A custom <code>Compony::Component</code> with manual <code>button_to</code>/standalone for
|
|
195
|
+
<p><strong>Symptom:</strong> A custom <code>Compony::Component</code> with manual <code>button_to</code>/standalone for delete/edit/create, duplicating routing, authorization, confirmation UI, styling.</p>
|
|
196
196
|
</li><li>
|
|
197
197
|
<p><strong>Cause:</strong> Reaching for a bespoke component instead of the pre-built one.</p>
|
|
198
198
|
</li><li>
|
|
199
|
-
<p><strong>Fix:</strong> For CRUD use the pre-built parents (<code>Destroy</code>/<code>Edit</code>/<code>New</code>/<code>Show</code>/<code>Index</code>) and
|
|
199
|
+
<p><strong>Fix:</strong> For CRUD use the pre-built parents (<code>Destroy</code>/<code>Edit</code>/<code>New</code>/<code>Show</code>/<code>Index</code>) and point with <code>render_intent(:destroy, record)</code>. Reserve custom <code>Compony::Component</code> standalones for genuinely non-CRUD actions (job dispatch, webhooks, multi-record ops). Put a resourceful component in the family of the model it operates on, not the family it is navigated from; pass parent context via path params.</p>
|
|
200
200
|
</li></ul>
|
|
201
201
|
|
|
202
|
-
<h3 id="
|
|
202
|
+
<h3 id="16-attraccessor-on-a-model-for-form-only-fields">16. <code>attr_accessor</code> on a model for form-only fields</h3>
|
|
203
203
|
<ul><li>
|
|
204
204
|
<p><strong>Symptom:</strong> Virtual form fields declared as <code>attr_accessor</code> on the ActiveRecord model.</p>
|
|
205
205
|
</li><li>
|
|
206
206
|
<p><strong>Cause:</strong> Polluting the persistent model with form-only concerns.</p>
|
|
207
207
|
</li><li>
|
|
208
|
-
<p><strong>Fix:</strong> Use an <code>ActiveType::Record[Model]</code> (or <code>Compony::VirtualModel</code>) inner class on
|
|
208
|
+
<p><strong>Fix:</strong> Use an <code>ActiveType::Record[Model]</code> (or <code>Compony::VirtualModel</code>) inner class on the component with <code>ar_attribute</code> + <code>field</code>, and set <code>data_class</code> to it. See <a href="/doc/guide/virtual_models_md.html">virtual_models.md</a>.</p>
|
|
209
209
|
</li></ul>
|
|
210
210
|
|
|
211
211
|
<p><a href="/README_md.html#guide--documentation">Guide index</a></p>
|
|
212
212
|
</div></div>
|
|
213
213
|
|
|
214
214
|
<div id="footer">
|
|
215
|
-
Generated on
|
|
215
|
+
Generated on Tue Aug 18 14:36:35 2026 by
|
|
216
216
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
217
217
|
0.9.34 (ruby-3.4.9).
|
|
218
218
|
</div>
|
data/doc/file.index.html
CHANGED
|
@@ -63,23 +63,23 @@
|
|
|
63
63
|
<p><a href="/doc/guide/pre_built_components_md.html">List of pre-built components</a></p>
|
|
64
64
|
</li></ul>
|
|
65
65
|
|
|
66
|
-
<h1 id="
|
|
66
|
+
<h1 id="pre-built-components-index">Pre-built components: Index</h1>
|
|
67
67
|
|
|
68
|
-
<p><code>Compony::Components::Index</code> is a resourceful standalone component corresponding to Rails’ <code>index</code> controller action. It holds a collection of records and is a thin wrapper that nests the href="./list_md.html"></a> component of the same family.</p>
|
|
68
|
+
<p><code>Compony::Components::Index</code> is a resourceful standalone component corresponding to Rails’ <code>index</code> controller action. It holds a collection of records and is a thin wrapper that nests the <a href="./list_md.html"><code>List</code></a> component of the same family.</p>
|
|
69
69
|
|
|
70
|
-
<h2 id="
|
|
70
|
+
<h2 id="what-it-does-by-default">What it does by default</h2>
|
|
71
71
|
|
|
72
72
|
<p>The shipped <code>setup</code> (see <code>lib/compony/components/index.rb</code>) is deliberately minimal:</p>
|
|
73
73
|
<ul><li>
|
|
74
|
-
<p><strong>Route:</strong> <code>standalone path: family_name</code> with a <code>verb :get</code> authorized by
|
|
74
|
+
<p><strong>Route:</strong> <code>standalone path: family_name</code> with a <code>verb :get</code> authorized by <code>can?(:index, data_class)</code>, e.g. <code>/users</code>.</p>
|
|
75
75
|
</li><li>
|
|
76
76
|
<p><strong>Label:</strong> <code>label(:all) { data_class.model_name.human(count: 2) }</code> — e.g. “Users”.</p>
|
|
77
77
|
</li><li>
|
|
78
|
-
<p><strong>Data:</strong> <code>load_data { @data = data_class.accessible_by(controller.current_ability) }</code>
|
|
78
|
+
<p><strong>Data:</strong> <code>load_data { @data = data_class.accessible_by(controller.current_ability) }</code> — the full <a href="https://github.com/CanCanCommunity/cancancan">CanCanCan</a>-scoped collection.</p>
|
|
79
79
|
</li><li>
|
|
80
|
-
<p><strong>Exposed intent:</strong> adds a <code>:new</code> intent (unless the model is
|
|
80
|
+
<p><strong>Exposed intent:</strong> adds a <code>:new</code> intent (unless the model is <a href="/doc/guide/ownership_md.html">owned</a> by another).</p>
|
|
81
81
|
</li><li>
|
|
82
|
-
<p><strong>Content:</strong> <code>concat render_sub_comp(:list, @data)</code> — delegates all rendering to the
|
|
82
|
+
<p><strong>Content:</strong> <code>concat render_sub_comp(:list, @data)</code> — delegates all rendering to the family’s <code>List</code>.</p>
|
|
83
83
|
</li></ul>
|
|
84
84
|
|
|
85
85
|
<p>So with both an <code>Index</code> and a <code>List</code> component present, a family lists out of the box:</p>
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
<span class='kw'>end</span>
|
|
91
91
|
</code></pre>
|
|
92
92
|
|
|
93
|
-
<h2 id="
|
|
93
|
+
<h2 id="typical-overrides">Typical overrides</h2>
|
|
94
94
|
|
|
95
95
|
<p>Narrow or order the collection:</p>
|
|
96
96
|
|
|
@@ -121,11 +121,11 @@
|
|
|
121
121
|
<span class='kw'>end</span>
|
|
122
122
|
</code></pre>
|
|
123
123
|
|
|
124
|
-
<p>In practice apps put the layout/markup chrome in a <code>BaseComponents::Index</code> and inherit from that — see <a href="../patterns_md.html#3-index--load_data-scope--nested-list">Real-world patterns</a>. For column/filter/sort configuration, see href="./list_md.html"></a>.</p>
|
|
124
|
+
<p>In practice apps put the layout/markup chrome in a <code>BaseComponents::Index</code> and inherit from that — see <a href="../patterns_md.html#3-index--load_data-scope--nested-list">Real-world patterns</a>. For column/filter/sort configuration, see <a href="./list_md.html"><code>List</code></a>.</p>
|
|
125
125
|
</div></div>
|
|
126
126
|
|
|
127
127
|
<div id="footer">
|
|
128
|
-
Generated on
|
|
128
|
+
Generated on Tue Aug 18 14:36:34 2026 by
|
|
129
129
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
130
130
|
0.9.34 (ruby-3.4.9).
|
|
131
131
|
</div>
|
data/doc/file.inheritance.html
CHANGED
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
<div id="content"><div id='filecontents'>
|
|
61
61
|
<p><a href="/README_md.html#guide--documentation">Back to the guide</a></p>
|
|
62
62
|
|
|
63
|
-
<h1 id="
|
|
63
|
+
<h1 id="inheritance">Inheritance</h1>
|
|
64
64
|
|
|
65
65
|
<p>Compony’s key advantage is that you can write DRYer code with it. To achieve this, you are encouraged to create abstract components, implement common functionality there and inherit from them in other components.</p>
|
|
66
66
|
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
<p>Perhaps you often implement the same kind of component, for instance an index component displaying a filterable list. In this case, create <code>BaseComponents::Index</code> and inherit as follows: <code>class Components::Users::Index < BaseComponents::Index</code>.</p>
|
|
72
72
|
</li></ul>
|
|
73
73
|
|
|
74
|
-
<h2 id="
|
|
74
|
+
<h2 id="behavior">Behavior</h2>
|
|
75
75
|
|
|
76
76
|
<p>When inheriting from another component class, <code>setup</code> can be called in the child as well in order to overwrite specified configurations. The parent’s <code>setup</code> block will be run first, then the child’s, then the grand-child’s and so on.</p>
|
|
77
77
|
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
<span class='kw'>end</span>
|
|
103
103
|
</code></pre>
|
|
104
104
|
|
|
105
|
-
<h2 id="
|
|
105
|
+
<h2 id="un-exposing-a-component">Un-exposing a component</h2>
|
|
106
106
|
|
|
107
107
|
<p>If a component’s parent class is <a href="./standalone_md.html">standalone</a> but the child should not be, use <code>clear_standalone!</code>:</p>
|
|
108
108
|
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
<span class='kw'>end</span>
|
|
112
112
|
</code></pre>
|
|
113
113
|
|
|
114
|
-
<h2 id="
|
|
114
|
+
<h2 id="best-practice">Best practice</h2>
|
|
115
115
|
|
|
116
116
|
<p>Compony has the following convention:</p>
|
|
117
117
|
<ul><li>
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
</div></div>
|
|
127
127
|
|
|
128
128
|
<div id="footer">
|
|
129
|
-
Generated on
|
|
129
|
+
Generated on Tue Aug 18 14:36:33 2026 by
|
|
130
130
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
131
131
|
0.9.34 (ruby-3.4.9).
|
|
132
132
|
</div>
|
data/doc/file.installation.html
CHANGED
|
@@ -60,9 +60,9 @@
|
|
|
60
60
|
<div id="content"><div id='filecontents'>
|
|
61
61
|
<p><a href="/README_md.html#guide--documentation">Back to the guide</a></p>
|
|
62
62
|
|
|
63
|
-
<h1 id="
|
|
63
|
+
<h1 id="installation">Installation</h1>
|
|
64
64
|
|
|
65
|
-
<h2 id="
|
|
65
|
+
<h2 id="installing-compony">Installing Compony</h2>
|
|
66
66
|
|
|
67
67
|
<p>First, add Compony to your Gemfile:</p>
|
|
68
68
|
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
<pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_include'>include</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/ModelMixin.html" title="Compony::ModelMixin (module)">ModelMixin</a></span></span>
|
|
79
79
|
</code></pre>
|
|
80
80
|
|
|
81
|
-
<h2 id="
|
|
81
|
+
<h2 id="installing-cancancan">Installing CanCanCan</h2>
|
|
82
82
|
|
|
83
83
|
<p>Create the file <code>app/models/ability.rb</code> with the following content:</p>
|
|
84
84
|
|
|
@@ -91,21 +91,21 @@
|
|
|
91
91
|
<span class='kw'>end</span>
|
|
92
92
|
</code></pre>
|
|
93
93
|
|
|
94
|
-
<p>This is an initial dummy ability that allows anyone to do anything. Most likely, you will want to adjust the file. For documentation, refer to <a href="https://github.com/CanCanCommunity/cancancan/">github.com/CanCanCommunity/cancancan/</a>.</p>
|
|
94
|
+
<p>This is an initial dummy ability that allows anyone to do anything. Most likely, you will want to adjust the file. For documentation, refer to <a href="https://github.com/CanCanCommunity/cancancan/">https://github.com/CanCanCommunity/cancancan/</a>.</p>
|
|
95
95
|
|
|
96
|
-
<h2 id="
|
|
96
|
+
<h2 id="optional-installing-anchormodel">Optional: installing anchormodel</h2>
|
|
97
97
|
|
|
98
|
-
<p>To take advantage of the anchormodel integration, follow the installation instructions under <a href="https://github.com/kalsan/anchormodel/">github.com/kalsan/anchormodel/</a>.</p>
|
|
98
|
+
<p>To take advantage of the anchormodel integration, follow the installation instructions under <a href="https://github.com/kalsan/anchormodel/">https://github.com/kalsan/anchormodel/</a>.</p>
|
|
99
99
|
|
|
100
|
-
<h2 id="
|
|
100
|
+
<h2 id="optional-installing-activetype">Optional: installing <code>active_type</code></h2>
|
|
101
101
|
|
|
102
|
-
<p>To take advantage of <a href="./virtual_models_md.html">virtual models</a> through the <code>active_type</code> integration, follow the instructions under <a href="https://github.com/makandra/active_type">github.com/makandra/active_type</a></p>
|
|
102
|
+
<p>To take advantage of <a href="./virtual_models_md.html">virtual models</a> through the <code>active_type</code> integration, follow the instructions under <a href="https://github.com/makandra/active_type">https://github.com/makandra/active_type</a></p>
|
|
103
103
|
|
|
104
104
|
<p><a href="/README_md.html#guide--documentation">Guide index</a></p>
|
|
105
105
|
</div></div>
|
|
106
106
|
|
|
107
107
|
<div id="footer">
|
|
108
|
-
Generated on
|
|
108
|
+
Generated on Tue Aug 18 14:36:33 2026 by
|
|
109
109
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
110
110
|
0.9.34 (ruby-3.4.9).
|
|
111
111
|
</div>
|
data/doc/file.integrations.html
CHANGED
|
@@ -60,11 +60,11 @@
|
|
|
60
60
|
<div id="content"><div id='filecontents'>
|
|
61
61
|
<p><a href="/README_md.html#guide--documentation">Back to the guide</a></p>
|
|
62
62
|
|
|
63
|
-
<h1 id="
|
|
63
|
+
<h1 id="integrations--companion-gems">Integrations & companion gems</h1>
|
|
64
64
|
|
|
65
|
-
<p>What Compony pulls in, what it optionally lights up, and what you are expected to add yourself. The authoritative source for hard dependencies and their version constraints is the <code>:gemspec</code> task in href="/Rakefile"></a> (it generates <code>compony.gemspec</code>); the table below mirrors it and must be updated together with it (see <a href="/doc/guide/maintaining_md.html">maintaining.md</a>).</p>
|
|
65
|
+
<p>What Compony pulls in, what it optionally lights up, and what you are expected to add yourself. The authoritative source for hard dependencies and their version constraints is the <code>:gemspec</code> task in <a href="/Rakefile"><code>Rakefile</code></a> (it generates <code>compony.gemspec</code>); the table below mirrors it and must be updated together with it (see <a href="/doc/guide/maintaining_md.html">maintaining.md</a>).</p>
|
|
66
66
|
|
|
67
|
-
<h2 id="
|
|
67
|
+
<h2 id="hard-runtime-dependencies-installed-automatically">Hard runtime dependencies (installed automatically)</h2>
|
|
68
68
|
|
|
69
69
|
<table role="table">
|
|
70
70
|
<thead>
|
|
@@ -76,44 +76,44 @@
|
|
|
76
76
|
</thead>
|
|
77
77
|
<tbody>
|
|
78
78
|
<tr>
|
|
79
|
-
<td
|
|
80
|
-
<td
|
|
79
|
+
<td><code>rails</code></td>
|
|
80
|
+
<td><code>>= 7.2.1</code></td>
|
|
81
81
|
<td>Routing, controllers, views Compony plugs into.</td>
|
|
82
82
|
</tr>
|
|
83
83
|
<tr>
|
|
84
|
-
<td
|
|
85
|
-
<td
|
|
86
|
-
<td>Per-request storage (e.g.
|
|
84
|
+
<td><code>request_store</code></td>
|
|
85
|
+
<td><code>>= 1.7</code></td>
|
|
86
|
+
<td>Per-request storage (e.g. <code>Compony.root_comp</code>).</td>
|
|
87
87
|
</tr>
|
|
88
88
|
<tr>
|
|
89
|
-
<td
|
|
90
|
-
<td
|
|
91
|
-
<td>HTML-as-Ruby templating used in
|
|
89
|
+
<td><code>dyny</code></td>
|
|
90
|
+
<td><code>>= 0.0.3</code></td>
|
|
91
|
+
<td>HTML-as-Ruby templating used in <code>content</code> blocks.</td>
|
|
92
92
|
</tr>
|
|
93
93
|
<tr>
|
|
94
|
-
<td
|
|
95
|
-
<td
|
|
96
|
-
<td>Strong-param schema validation behind
|
|
94
|
+
<td><code>schemacop</code></td>
|
|
95
|
+
<td><code>>= 3.0.17</code></td>
|
|
96
|
+
<td>Strong-param schema validation behind <code>schema_field</code> / <code>schema_line</code>.</td>
|
|
97
97
|
</tr>
|
|
98
98
|
<tr>
|
|
99
|
-
<td
|
|
100
|
-
<td
|
|
101
|
-
<td>The form builder behind the Form component’s
|
|
99
|
+
<td><code>simple_form</code></td>
|
|
100
|
+
<td><code>>= 5.3.1</code></td>
|
|
101
|
+
<td>The form builder behind the Form component’s <code>field</code>.</td>
|
|
102
102
|
</tr>
|
|
103
103
|
<tr>
|
|
104
|
-
<td
|
|
105
|
-
<td
|
|
106
|
-
<td>Powers the
|
|
104
|
+
<td><code>dslblend</code></td>
|
|
105
|
+
<td><code>>= 0.0.3</code></td>
|
|
106
|
+
<td>Powers the <code>RequestContext</code> multi-provider DSL.</td>
|
|
107
107
|
</tr>
|
|
108
108
|
<tr>
|
|
109
|
-
<td
|
|
110
|
-
<td
|
|
111
|
-
<td
|
|
109
|
+
<td><code>anchormodel</code></td>
|
|
110
|
+
<td><code>>= 0.3.0</code></td>
|
|
111
|
+
<td><code>anchormodel</code> model-field type + enum-like associations.</td>
|
|
112
112
|
</tr>
|
|
113
113
|
<tr>
|
|
114
|
-
<td
|
|
115
|
-
<td
|
|
116
|
-
<td>Authorization:
|
|
114
|
+
<td><code>cancancan</code></td>
|
|
115
|
+
<td><code>~> 3.6.1</code></td>
|
|
116
|
+
<td>Authorization: <code>authorize { can?(...) }</code>, <code>accessible_by</code>, per-field <code>permitted_attributes</code>.</td>
|
|
117
117
|
</tr>
|
|
118
118
|
</tbody>
|
|
119
119
|
</table>
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
<p>Version note: the gemspec requires <code>rails >= 7.2.1</code>. If the README’s prose mentions an older range, the gemspec wins — keep them in sync when bumping (see maintaining.md).</p>
|
|
125
125
|
</blockquote>
|
|
126
126
|
|
|
127
|
-
<h2 id="
|
|
127
|
+
<h2 id="optional--presence-unlocks-a-feature">Optional — presence unlocks a feature</h2>
|
|
128
128
|
|
|
129
129
|
<p>These are <strong>not</strong> declared dependencies; Compony detects them and enables behavior if they are in the host app’s bundle.</p>
|
|
130
130
|
|
|
@@ -137,17 +137,17 @@
|
|
|
137
137
|
</thead>
|
|
138
138
|
<tbody>
|
|
139
139
|
<tr>
|
|
140
|
-
<td
|
|
141
|
-
<td
|
|
140
|
+
<td><code>active_type</code></td>
|
|
141
|
+
<td><code>Compony::VirtualModel</code> (loaded only if <code>ActiveType::Object</code> is defined). Non-persistent / upload / wizard forms — <a href="/doc/guide/patterns_md.html#12-virtual-model-for-non-persistent--upload-forms">patterns §12</a>, <a href="/doc/guide/virtual_models_md.html">virtual_models.md</a>.</td>
|
|
142
142
|
</tr>
|
|
143
143
|
<tr>
|
|
144
|
-
<td
|
|
145
|
-
<td>List filtering, sorting links and the sort select in
|
|
144
|
+
<td><code>ransack</code></td>
|
|
145
|
+
<td>List filtering, sorting links and the sort select in <a href="/doc/guide/pre_built_components/list_md.html"><code>List</code></a>. Without it, declare no <code>filter</code>/<code>sort</code> and those UIs stay off.</td>
|
|
146
146
|
</tr>
|
|
147
147
|
</tbody>
|
|
148
148
|
</table>
|
|
149
149
|
|
|
150
|
-
<h2 id="
|
|
150
|
+
<h2 id="app-side-companions-you-add-these">App-side companions (you add these)</h2>
|
|
151
151
|
|
|
152
152
|
<p>Compony is UI- and auth-agnostic; these are conventional choices in real apps, pulled in by your app, not by Compony.</p>
|
|
153
153
|
|
|
@@ -162,45 +162,45 @@
|
|
|
162
162
|
<tbody>
|
|
163
163
|
<tr>
|
|
164
164
|
<td>Authentication</td>
|
|
165
|
-
<td>Devise, or a custom login component +
|
|
166
|
-
<td>Compony ships <strong>no</strong> auth (
|
|
165
|
+
<td>Devise, or a custom login component + <code>Compony.authentication_before_action=</code></td>
|
|
166
|
+
<td>Compony ships <strong>no</strong> auth (<a href="/README_md.html">README</a>); token-link flows → <a href="/doc/guide/patterns_md.html#18-signed-token-capability-links-auth-less-onboarding--magic-links">patterns §18</a></td>
|
|
167
167
|
</tr>
|
|
168
168
|
<tr>
|
|
169
169
|
<td>Turbo / Stimulus</td>
|
|
170
|
-
<td
|
|
171
|
-
<td>Compony fully supports Turbo Drive; inline-edit →
|
|
170
|
+
<td><code>turbo-rails</code>, <code>stimulus-rails</code></td>
|
|
171
|
+
<td>Compony fully supports Turbo Drive; inline-edit → <a href="/doc/guide/patterns_md.html#15-inline-edit-card-with-a-turbo-frame">patterns §15</a>, ajax PATCH → <a href="/doc/guide/patterns_md.html#17-inline-patch-without-a-form-reorder--quick-toggle">patterns §17</a></td>
|
|
172
172
|
</tr>
|
|
173
173
|
<tr>
|
|
174
174
|
<td>Select / date inputs</td>
|
|
175
|
-
<td>TomSelect, Flatpickr (as registered
|
|
176
|
-
<td
|
|
175
|
+
<td>TomSelect, Flatpickr (as registered <code>simple_form</code> inputs)</td>
|
|
176
|
+
<td><code>field(:x, as: :tom_select/:flatpickr_*)</code> — <a href="/doc/guide/patterns_md.html#5-custom-form--schemacop-kept-in-sync">patterns §5–6</a></td>
|
|
177
177
|
</tr>
|
|
178
178
|
<tr>
|
|
179
179
|
<td>i18n</td>
|
|
180
180
|
<td>Rails I18n and/or FastGettext</td>
|
|
181
|
-
<td>Component labels; gem ships
|
|
181
|
+
<td>Component labels; gem ships <code>config/locales/{de,en,fr}.yml</code></td>
|
|
182
182
|
</tr>
|
|
183
183
|
<tr>
|
|
184
184
|
<td>File handling</td>
|
|
185
185
|
<td>ActiveStorage (+ a variant/processor)</td>
|
|
186
|
-
<td>Attachment fields, virtual-model uploads —
|
|
186
|
+
<td>Attachment fields, virtual-model uploads — <a href="/doc/guide/patterns_md.html#12-virtual-model-for-non-persistent--upload-forms">patterns §12</a></td>
|
|
187
187
|
</tr>
|
|
188
188
|
<tr>
|
|
189
189
|
<td>PDF / CSV</td>
|
|
190
|
-
<td>Prawn / wicked_pdf, Ruby
|
|
191
|
-
<td>Export endpoints —
|
|
190
|
+
<td>Prawn / wicked_pdf, Ruby <code>CSV</code></td>
|
|
191
|
+
<td>Export endpoints — <a href="/doc/guide/patterns_md.html#10-csv--pdf-via-respond-format">patterns §10</a></td>
|
|
192
192
|
</tr>
|
|
193
193
|
<tr>
|
|
194
194
|
<td>Signed tokens</td>
|
|
195
|
-
<td
|
|
196
|
-
<td>Capability links —
|
|
195
|
+
<td><code>jwt</code></td>
|
|
196
|
+
<td>Capability links — <a href="/doc/guide/patterns_md.html#18-signed-token-capability-links-auth-less-onboarding--magic-links">patterns §18</a></td>
|
|
197
197
|
</tr>
|
|
198
198
|
</tbody>
|
|
199
199
|
</table>
|
|
200
200
|
|
|
201
201
|
<p>Incompatibility: <code>tailwindcss-rails</code> purges Compony component CSS (component HTML is not in <code>app/views</code>); see <a href="/doc/guide/gotchas_md.html#13-tailwindcss-rails-purges-compony-styles">gotchas.md #13</a>.</p>
|
|
202
202
|
|
|
203
|
-
<h2 id="
|
|
203
|
+
<h2 id="development-dependencies">Development dependencies</h2>
|
|
204
204
|
|
|
205
205
|
<p><code>yard >= 0.9.28</code> (docs), <code>rubocop >= 1.48</code>, <code>rubocop-rails >= 2.18.0</code> (lint).</p>
|
|
206
206
|
|
|
@@ -208,7 +208,7 @@
|
|
|
208
208
|
</div></div>
|
|
209
209
|
|
|
210
210
|
<div id="footer">
|
|
211
|
-
Generated on
|
|
211
|
+
Generated on Tue Aug 18 14:36:35 2026 by
|
|
212
212
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
213
213
|
0.9.34 (ruby-3.4.9).
|
|
214
214
|
</div>
|