agent-notes 2.0.4__py3-none-any.whl
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.
- agent_notes/VERSION +1 -0
- agent_notes/__init__.py +1 -0
- agent_notes/__main__.py +4 -0
- agent_notes/cli.py +348 -0
- agent_notes/commands/__init__.py +27 -0
- agent_notes/commands/_install_helpers.py +262 -0
- agent_notes/commands/build.py +170 -0
- agent_notes/commands/doctor.py +112 -0
- agent_notes/commands/info.py +95 -0
- agent_notes/commands/install.py +99 -0
- agent_notes/commands/list.py +169 -0
- agent_notes/commands/memory.py +430 -0
- agent_notes/commands/regenerate.py +152 -0
- agent_notes/commands/set_role.py +143 -0
- agent_notes/commands/uninstall.py +26 -0
- agent_notes/commands/update.py +169 -0
- agent_notes/commands/validate.py +199 -0
- agent_notes/commands/wizard.py +720 -0
- agent_notes/config.py +154 -0
- agent_notes/data/agents/agents.yaml +352 -0
- agent_notes/data/agents/analyst.md +45 -0
- agent_notes/data/agents/api-reviewer.md +47 -0
- agent_notes/data/agents/architect.md +46 -0
- agent_notes/data/agents/coder.md +28 -0
- agent_notes/data/agents/database-specialist.md +45 -0
- agent_notes/data/agents/debugger.md +47 -0
- agent_notes/data/agents/devil.md +47 -0
- agent_notes/data/agents/devops.md +38 -0
- agent_notes/data/agents/explorer.md +23 -0
- agent_notes/data/agents/integrations.md +44 -0
- agent_notes/data/agents/lead.md +216 -0
- agent_notes/data/agents/performance-profiler.md +44 -0
- agent_notes/data/agents/refactorer.md +48 -0
- agent_notes/data/agents/reviewer.md +44 -0
- agent_notes/data/agents/security-auditor.md +44 -0
- agent_notes/data/agents/system-auditor.md +38 -0
- agent_notes/data/agents/tech-writer.md +32 -0
- agent_notes/data/agents/test-runner.md +36 -0
- agent_notes/data/agents/test-writer.md +39 -0
- agent_notes/data/cli/claude.yaml +25 -0
- agent_notes/data/cli/copilot.yaml +18 -0
- agent_notes/data/cli/opencode.yaml +22 -0
- agent_notes/data/commands/brainstorm.md +8 -0
- agent_notes/data/commands/debug.md +9 -0
- agent_notes/data/commands/review.md +10 -0
- agent_notes/data/global-claude.md +290 -0
- agent_notes/data/global-copilot.md +27 -0
- agent_notes/data/global-opencode.md +40 -0
- agent_notes/data/hooks/session-context.md.tpl +19 -0
- agent_notes/data/models/claude-haiku-4-5.yaml +15 -0
- agent_notes/data/models/claude-opus-4-1.yaml +16 -0
- agent_notes/data/models/claude-opus-4-5.yaml +16 -0
- agent_notes/data/models/claude-opus-4-6.yaml +16 -0
- agent_notes/data/models/claude-opus-4-7.yaml +15 -0
- agent_notes/data/models/claude-sonnet-4-5.yaml +16 -0
- agent_notes/data/models/claude-sonnet-4-6.yaml +15 -0
- agent_notes/data/models/claude-sonnet-4.yaml +16 -0
- agent_notes/data/pricing.yaml +33 -0
- agent_notes/data/roles/orchestrator.yaml +5 -0
- agent_notes/data/roles/reasoner.yaml +5 -0
- agent_notes/data/roles/scout.yaml +5 -0
- agent_notes/data/roles/worker.yaml +5 -0
- agent_notes/data/rules/code-quality.md +9 -0
- agent_notes/data/rules/safety.md +10 -0
- agent_notes/data/scripts/cost-report +211 -0
- agent_notes/data/skills/brainstorming/SKILL.md +57 -0
- agent_notes/data/skills/code-review/SKILL.md +64 -0
- agent_notes/data/skills/debugging-protocol/SKILL.md +51 -0
- agent_notes/data/skills/docker-compose/SKILL.md +318 -0
- agent_notes/data/skills/docker-compose-advanced/SKILL.md +575 -0
- agent_notes/data/skills/docker-dockerfile/SKILL.md +385 -0
- agent_notes/data/skills/docker-dockerfile-languages/SKILL.md +293 -0
- agent_notes/data/skills/git/SKILL.md +87 -0
- agent_notes/data/skills/rails-active-storage/SKILL.md +321 -0
- agent_notes/data/skills/rails-broadcasting/SKILL.md +374 -0
- agent_notes/data/skills/rails-concerns/SKILL.md +806 -0
- agent_notes/data/skills/rails-controllers/SKILL.md +510 -0
- agent_notes/data/skills/rails-controllers-advanced/SKILL.md +441 -0
- agent_notes/data/skills/rails-helpers/SKILL.md +677 -0
- agent_notes/data/skills/rails-initializers/SKILL.md +79 -0
- agent_notes/data/skills/rails-javascript/SKILL.md +567 -0
- agent_notes/data/skills/rails-jobs/SKILL.md +700 -0
- agent_notes/data/skills/rails-kamal/SKILL.md +483 -0
- agent_notes/data/skills/rails-lib/SKILL.md +101 -0
- agent_notes/data/skills/rails-mailers/SKILL.md +321 -0
- agent_notes/data/skills/rails-migrations/SKILL.md +268 -0
- agent_notes/data/skills/rails-models/SKILL.md +459 -0
- agent_notes/data/skills/rails-models-advanced/SKILL.md +398 -0
- agent_notes/data/skills/rails-routes/SKILL.md +804 -0
- agent_notes/data/skills/rails-style/SKILL.md +538 -0
- agent_notes/data/skills/rails-testing-controllers/SKILL.md +343 -0
- agent_notes/data/skills/rails-testing-models/SKILL.md +296 -0
- agent_notes/data/skills/rails-testing-system/SKILL.md +375 -0
- agent_notes/data/skills/rails-validations/SKILL.md +108 -0
- agent_notes/data/skills/rails-view-components/SKILL.md +511 -0
- agent_notes/data/skills/rails-view-components-advanced/SKILL.md +376 -0
- agent_notes/data/skills/rails-views/SKILL.md +413 -0
- agent_notes/data/skills/rails-views-advanced/SKILL.md +450 -0
- agent_notes/data/skills/refactoring-protocol/SKILL.md +64 -0
- agent_notes/data/skills/tdd/SKILL.md +57 -0
- agent_notes/data/templates/__init__.py +1 -0
- agent_notes/data/templates/__pycache__/__init__.cpython-314.pyc +0 -0
- agent_notes/data/templates/frontmatter/__init__.py +1 -0
- agent_notes/data/templates/frontmatter/__pycache__/__init__.cpython-314.pyc +0 -0
- agent_notes/data/templates/frontmatter/__pycache__/claude.cpython-314.pyc +0 -0
- agent_notes/data/templates/frontmatter/__pycache__/cursor.cpython-314.pyc +0 -0
- agent_notes/data/templates/frontmatter/__pycache__/opencode.cpython-314.pyc +0 -0
- agent_notes/data/templates/frontmatter/claude.py +44 -0
- agent_notes/data/templates/frontmatter/opencode.py +104 -0
- agent_notes/doctor_checks.py +189 -0
- agent_notes/domain/__init__.py +17 -0
- agent_notes/domain/agent.py +34 -0
- agent_notes/domain/cli_backend.py +40 -0
- agent_notes/domain/diagnostics.py +29 -0
- agent_notes/domain/diff.py +44 -0
- agent_notes/domain/model.py +27 -0
- agent_notes/domain/role.py +13 -0
- agent_notes/domain/rule.py +13 -0
- agent_notes/domain/skill.py +15 -0
- agent_notes/domain/state.py +46 -0
- agent_notes/install_state.py +11 -0
- agent_notes/registries/__init__.py +16 -0
- agent_notes/registries/_base.py +46 -0
- agent_notes/registries/agent_registry.py +107 -0
- agent_notes/registries/cli_registry.py +89 -0
- agent_notes/registries/model_registry.py +85 -0
- agent_notes/registries/role_registry.py +64 -0
- agent_notes/registries/rule_registry.py +80 -0
- agent_notes/registries/skill_registry.py +141 -0
- agent_notes/services/__init__.py +8 -0
- agent_notes/services/diagnostics/__init__.py +47 -0
- agent_notes/services/diagnostics/_checks.py +272 -0
- agent_notes/services/diagnostics/_display.py +346 -0
- agent_notes/services/diagnostics/_fix.py +169 -0
- agent_notes/services/diff.py +349 -0
- agent_notes/services/fs.py +195 -0
- agent_notes/services/install_state_builder.py +210 -0
- agent_notes/services/installer.py +293 -0
- agent_notes/services/memory_backend.py +155 -0
- agent_notes/services/rendering.py +329 -0
- agent_notes/services/session_context.py +23 -0
- agent_notes/services/settings_writer.py +79 -0
- agent_notes/services/state_store.py +249 -0
- agent_notes/services/ui.py +419 -0
- agent_notes/services/user_config.py +62 -0
- agent_notes/services/validation.py +67 -0
- agent_notes/state.py +21 -0
- agent_notes-2.0.4.dist-info/METADATA +14 -0
- agent_notes-2.0.4.dist-info/RECORD +162 -0
- agent_notes-2.0.4.dist-info/WHEEL +5 -0
- agent_notes-2.0.4.dist-info/entry_points.txt +2 -0
- agent_notes-2.0.4.dist-info/licenses/LICENSE +21 -0
- agent_notes-2.0.4.dist-info/top_level.txt +2 -0
- tests/conftest.py +20 -0
- tests/functional/__init__.py +0 -0
- tests/functional/test_build_commands.py +88 -0
- tests/functional/test_registries.py +128 -0
- tests/integration/__init__.py +0 -0
- tests/integration/test_build_output.py +129 -0
- tests/plugins/__init__.py +0 -0
- tests/plugins/test_agents.py +93 -0
- tests/plugins/test_skills.py +77 -0
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rails-views
|
|
3
|
+
description: "Rails views: templates, partials, layouts, caching, and forms"
|
|
4
|
+
group: rails
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Views Guide
|
|
8
|
+
|
|
9
|
+
Comprehensive guide for Rails views, partials, and templates.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Philosophy
|
|
14
|
+
|
|
15
|
+
1. **Views are for presentation only** - No business logic
|
|
16
|
+
2. **Keep views dumb** - Complex logic goes in helpers or models
|
|
17
|
+
3. **DRY with partials** - Extract reusable view fragments
|
|
18
|
+
4. **Explicit locals** - Always pass data explicitly to partials
|
|
19
|
+
5. **Fragment caching** - Cache expensive view fragments
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## File Structure
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
app/views/
|
|
27
|
+
├── layouts/
|
|
28
|
+
│ ├── application.html.erb # Main layout
|
|
29
|
+
│ ├── mailer.html.erb # Email layout
|
|
30
|
+
│ └── admin.html.erb # Admin layout
|
|
31
|
+
├── cards/
|
|
32
|
+
│ ├── index.html.erb # Template
|
|
33
|
+
│ ├── show.html.erb
|
|
34
|
+
│ ├── _card.html.erb # Partial (starts with _)
|
|
35
|
+
│ ├── _form.html.erb
|
|
36
|
+
│ └── display/ # Nested partials
|
|
37
|
+
│ ├── _preview.html.erb
|
|
38
|
+
│ └── _details.html.erb
|
|
39
|
+
└── shared/
|
|
40
|
+
├── _header.html.erb # Shared partials
|
|
41
|
+
└── _footer.html.erb
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Basic Template Structure
|
|
47
|
+
|
|
48
|
+
### Standard View Template
|
|
49
|
+
|
|
50
|
+
```erb
|
|
51
|
+
<%# app/views/cards/show.html.erb %>
|
|
52
|
+
|
|
53
|
+
<%# Set page title %>
|
|
54
|
+
<% content_for :title, @card.title %>
|
|
55
|
+
|
|
56
|
+
<%# Set meta tags %>
|
|
57
|
+
<% content_for :head do %>
|
|
58
|
+
<%= card_social_tags(@card) %>
|
|
59
|
+
<% end %>
|
|
60
|
+
|
|
61
|
+
<div class="card-container">
|
|
62
|
+
<header class="card-header">
|
|
63
|
+
<h1><%= @card.title %></h1>
|
|
64
|
+
<%= render "cards/metadata", card: @card %>
|
|
65
|
+
</header>
|
|
66
|
+
|
|
67
|
+
<div class="card-body">
|
|
68
|
+
<%= render "cards/description", card: @card %>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<footer class="card-footer">
|
|
72
|
+
<%= render "cards/actions", card: @card %>
|
|
73
|
+
</footer>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<%# Render comments %>
|
|
77
|
+
<section id="comments">
|
|
78
|
+
<%= render @card.comments %>
|
|
79
|
+
</section>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Index Template
|
|
83
|
+
|
|
84
|
+
```erb
|
|
85
|
+
<%# app/views/cards/index.html.erb %>
|
|
86
|
+
|
|
87
|
+
<div class="cards-header">
|
|
88
|
+
<h1>Cards</h1>
|
|
89
|
+
<%= link_to "New Card", new_card_path, class: "btn btn-primary" %>
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
<div class="cards-grid">
|
|
93
|
+
<%= render @cards %>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<%# Pagination %>
|
|
97
|
+
<%= paginate @cards %>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Form Template
|
|
101
|
+
|
|
102
|
+
```erb
|
|
103
|
+
<%# app/views/cards/new.html.erb %>
|
|
104
|
+
|
|
105
|
+
<h1>New Card</h1>
|
|
106
|
+
|
|
107
|
+
<%= render "form", card: @card %>
|
|
108
|
+
|
|
109
|
+
<%= link_to "Back", cards_path %>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Partials
|
|
115
|
+
|
|
116
|
+
### Basic Partial
|
|
117
|
+
|
|
118
|
+
```erb
|
|
119
|
+
<%# app/views/cards/_card.html.erb %>
|
|
120
|
+
|
|
121
|
+
<article class="card" id="<%= dom_id(card) %>">
|
|
122
|
+
<h3><%= link_to card.title, card %></h3>
|
|
123
|
+
|
|
124
|
+
<div class="card-meta">
|
|
125
|
+
<span class="author">by <%= card.creator.name %></span>
|
|
126
|
+
<time datetime="<%= card.created_at.iso8601 %>">
|
|
127
|
+
<%= time_ago_in_words(card.created_at) %> ago
|
|
128
|
+
</time>
|
|
129
|
+
</div>
|
|
130
|
+
|
|
131
|
+
<% if card.description.present? %>
|
|
132
|
+
<div class="card-description">
|
|
133
|
+
<%= truncate(card.description.to_plain_text, length: 200) %>
|
|
134
|
+
</div>
|
|
135
|
+
<% end %>
|
|
136
|
+
</article>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Partial with Explicit Locals
|
|
140
|
+
|
|
141
|
+
```erb
|
|
142
|
+
<%# app/views/cards/_metadata.html.erb %>
|
|
143
|
+
|
|
144
|
+
<div class="metadata">
|
|
145
|
+
<span class="status">
|
|
146
|
+
<%= content_tag :span, card.status.humanize, class: "badge badge-#{card.status}" %>
|
|
147
|
+
</span>
|
|
148
|
+
|
|
149
|
+
<% if show_board %>
|
|
150
|
+
<span class="board">
|
|
151
|
+
<%= link_to card.board.name, card.board %>
|
|
152
|
+
</span>
|
|
153
|
+
<% end %>
|
|
154
|
+
|
|
155
|
+
<% if card.tags.any? %>
|
|
156
|
+
<div class="tags">
|
|
157
|
+
<%= render card.tags %>
|
|
158
|
+
</div>
|
|
159
|
+
<% end %>
|
|
160
|
+
</div>
|
|
161
|
+
|
|
162
|
+
<%# Usage with explicit locals: %>
|
|
163
|
+
<%# <%= render "cards/metadata", card: @card, show_board: true %> %>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Partial Collection
|
|
167
|
+
|
|
168
|
+
```erb
|
|
169
|
+
<%# Renders cards/_card.html.erb for each card %>
|
|
170
|
+
<%= render @cards %>
|
|
171
|
+
|
|
172
|
+
<%# Same as: %>
|
|
173
|
+
<%= render partial: "cards/card", collection: @cards %>
|
|
174
|
+
|
|
175
|
+
<%# With custom local name: %>
|
|
176
|
+
<%= render partial: "cards/card", collection: @cards, as: :item %>
|
|
177
|
+
|
|
178
|
+
<%# With spacer: %>
|
|
179
|
+
<%= render partial: "cards/card", collection: @cards, spacer_template: "cards/spacer" %>
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Partial with Counter
|
|
183
|
+
|
|
184
|
+
```erb
|
|
185
|
+
<%# app/views/cards/_card.html.erb %>
|
|
186
|
+
|
|
187
|
+
<article class="card" data-index="<%= card_counter %>">
|
|
188
|
+
<h3>#<%= card_counter + 1 %> - <%= card.title %></h3>
|
|
189
|
+
</article>
|
|
190
|
+
|
|
191
|
+
<%# When rendering collection, card_counter is automatically available %>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Conditional Partials
|
|
195
|
+
|
|
196
|
+
```erb
|
|
197
|
+
<% if user_signed_in? %>
|
|
198
|
+
<%= render "cards/actions", card: @card %>
|
|
199
|
+
<% end %>
|
|
200
|
+
|
|
201
|
+
<% if @card.published? %>
|
|
202
|
+
<%= render "cards/public_info", card: @card %>
|
|
203
|
+
<% else %>
|
|
204
|
+
<%= render "cards/draft_notice", card: @card %>
|
|
205
|
+
<% end %>
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Layouts
|
|
211
|
+
|
|
212
|
+
### Application Layout
|
|
213
|
+
|
|
214
|
+
```erb
|
|
215
|
+
<%# app/views/layouts/application.html.erb %>
|
|
216
|
+
|
|
217
|
+
<!DOCTYPE html>
|
|
218
|
+
<html>
|
|
219
|
+
<head>
|
|
220
|
+
<title><%= content_for?(:title) ? yield(:title) : "My App" %></title>
|
|
221
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
222
|
+
<%= csrf_meta_tags %>
|
|
223
|
+
<%= csp_meta_tag %>
|
|
224
|
+
|
|
225
|
+
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
|
|
226
|
+
<%= javascript_importmap_tags %>
|
|
227
|
+
|
|
228
|
+
<%= yield :head %>
|
|
229
|
+
</head>
|
|
230
|
+
|
|
231
|
+
<body>
|
|
232
|
+
<%= render "shared/header" %>
|
|
233
|
+
|
|
234
|
+
<main>
|
|
235
|
+
<% if notice.present? %>
|
|
236
|
+
<div class="alert alert-notice"><%= notice %></div>
|
|
237
|
+
<% end %>
|
|
238
|
+
|
|
239
|
+
<% if alert.present? %>
|
|
240
|
+
<div class="alert alert-alert"><%= alert %></div>
|
|
241
|
+
<% end %>
|
|
242
|
+
|
|
243
|
+
<%= yield %>
|
|
244
|
+
</main>
|
|
245
|
+
|
|
246
|
+
<%= render "shared/footer" %>
|
|
247
|
+
</body>
|
|
248
|
+
</html>
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Custom Layout
|
|
252
|
+
|
|
253
|
+
```erb
|
|
254
|
+
<%# app/views/layouts/admin.html.erb %>
|
|
255
|
+
|
|
256
|
+
<!DOCTYPE html>
|
|
257
|
+
<html>
|
|
258
|
+
<head>
|
|
259
|
+
<title>Admin - <%= content_for?(:title) ? yield(:title) : "Dashboard" %></title>
|
|
260
|
+
<%= csrf_meta_tags %>
|
|
261
|
+
<%= stylesheet_link_tag "admin", "data-turbo-track": "reload" %>
|
|
262
|
+
</head>
|
|
263
|
+
|
|
264
|
+
<body class="admin-layout">
|
|
265
|
+
<%= render "admin/sidebar" %>
|
|
266
|
+
|
|
267
|
+
<main class="admin-content">
|
|
268
|
+
<%= yield %>
|
|
269
|
+
</main>
|
|
270
|
+
</body>
|
|
271
|
+
</html>
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Content For
|
|
275
|
+
|
|
276
|
+
```erb
|
|
277
|
+
<%# In view: %>
|
|
278
|
+
<% content_for :title, "Custom Page Title" %>
|
|
279
|
+
|
|
280
|
+
<% content_for :head do %>
|
|
281
|
+
<meta name="description" content="Page description">
|
|
282
|
+
<% end %>
|
|
283
|
+
|
|
284
|
+
<% content_for :sidebar do %>
|
|
285
|
+
<nav>
|
|
286
|
+
<%= link_to "Link 1", path1 %>
|
|
287
|
+
<%= link_to "Link 2", path2 %>
|
|
288
|
+
</nav>
|
|
289
|
+
<% end %>
|
|
290
|
+
|
|
291
|
+
<%# In layout: %>
|
|
292
|
+
<title><%= yield :title %></title>
|
|
293
|
+
<%= yield :head %>
|
|
294
|
+
<aside><%= yield :sidebar %></aside>
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## Caching
|
|
300
|
+
|
|
301
|
+
### Fragment Caching
|
|
302
|
+
|
|
303
|
+
```erb
|
|
304
|
+
<%# Cache a partial %>
|
|
305
|
+
<% cache @card do %>
|
|
306
|
+
<%= render @card %>
|
|
307
|
+
<% end %>
|
|
308
|
+
|
|
309
|
+
<%# Cache with custom key %>
|
|
310
|
+
<% cache ["card", @card.id, @card.updated_at] do %>
|
|
311
|
+
<%= render @card %>
|
|
312
|
+
<% end %>
|
|
313
|
+
|
|
314
|
+
<%# Cache with multiple dependencies %>
|
|
315
|
+
<% cache [@card, @card.tags.maximum(:updated_at)] do %>
|
|
316
|
+
<%= render "cards/card_with_tags", card: @card %>
|
|
317
|
+
<% end %>
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Collection Caching
|
|
321
|
+
|
|
322
|
+
```erb
|
|
323
|
+
<%# Automatically caches each item %>
|
|
324
|
+
<%= render partial: "cards/card", collection: @cards, cached: true %>
|
|
325
|
+
|
|
326
|
+
<%# With custom cache key %>
|
|
327
|
+
<%= render partial: "cards/card", collection: @cards, cached: -> card { [card, "v2"] } %>
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### Conditional Caching
|
|
331
|
+
|
|
332
|
+
```erb
|
|
333
|
+
<% cache_if user_signed_in?, @card do %>
|
|
334
|
+
<%= render @card %>
|
|
335
|
+
<% end %>
|
|
336
|
+
|
|
337
|
+
<% cache_unless @card.draft?, @card do %>
|
|
338
|
+
<%= render @card %>
|
|
339
|
+
<% end %>
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## Forms
|
|
345
|
+
|
|
346
|
+
### Form Builder
|
|
347
|
+
|
|
348
|
+
```erb
|
|
349
|
+
<%# app/views/cards/_form.html.erb %>
|
|
350
|
+
|
|
351
|
+
<%= form_with model: card do |form| %>
|
|
352
|
+
<% if card.errors.any? %>
|
|
353
|
+
<div class="error-messages">
|
|
354
|
+
<h3><%= pluralize(card.errors.count, "error") %> prohibited this card from being saved:</h3>
|
|
355
|
+
<ul>
|
|
356
|
+
<% card.errors.full_messages.each do |message| %>
|
|
357
|
+
<li><%= message %></li>
|
|
358
|
+
<% end %>
|
|
359
|
+
</ul>
|
|
360
|
+
</div>
|
|
361
|
+
<% end %>
|
|
362
|
+
|
|
363
|
+
<div class="field">
|
|
364
|
+
<%= form.label :title %>
|
|
365
|
+
<%= form.text_field :title, autofocus: true, class: "form-control" %>
|
|
366
|
+
</div>
|
|
367
|
+
|
|
368
|
+
<div class="field">
|
|
369
|
+
<%= form.label :description %>
|
|
370
|
+
<%= form.rich_text_area :description %>
|
|
371
|
+
</div>
|
|
372
|
+
|
|
373
|
+
<div class="field">
|
|
374
|
+
<%= form.label :status %>
|
|
375
|
+
<%= form.select :status, Card.statuses.keys, {}, class: "form-control" %>
|
|
376
|
+
</div>
|
|
377
|
+
|
|
378
|
+
<div class="field">
|
|
379
|
+
<%= form.label :board_id %>
|
|
380
|
+
<%= form.collection_select :board_id, current_user.boards, :id, :name, {}, class: "form-control" %>
|
|
381
|
+
</div>
|
|
382
|
+
|
|
383
|
+
<div class="actions">
|
|
384
|
+
<%= form.submit class: "btn btn-primary" %>
|
|
385
|
+
</div>
|
|
386
|
+
<% end %>
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### Nested Forms
|
|
390
|
+
|
|
391
|
+
```erb
|
|
392
|
+
<%= form_with model: @card do |card_form| %>
|
|
393
|
+
<%= card_form.text_field :title %>
|
|
394
|
+
|
|
395
|
+
<h3>Steps</h3>
|
|
396
|
+
<%= card_form.fields_for :steps do |step_form| %>
|
|
397
|
+
<%= render "step_fields", form: step_form %>
|
|
398
|
+
<% end %>
|
|
399
|
+
|
|
400
|
+
<%= link_to "Add Step", "#", data: { action: "nested-form#add" } %>
|
|
401
|
+
|
|
402
|
+
<%= card_form.submit %>
|
|
403
|
+
<% end %>
|
|
404
|
+
|
|
405
|
+
<%# _step_fields.html.erb %>
|
|
406
|
+
<div class="nested-fields">
|
|
407
|
+
<%= form.text_field :title %>
|
|
408
|
+
<%= form.check_box :completed %>
|
|
409
|
+
<%= link_to "Remove", "#", data: { action: "nested-form#remove" } %>
|
|
410
|
+
</div>
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
---
|