tramway 2.2.2.7 → 2.2.3
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/README.md +42 -31
- data/app/components/tailwinds/button_component.html.haml +15 -15
- data/app/components/tailwinds/button_component.rb +14 -14
- data/app/components/tailwinds/form/builder.rb +1 -1
- data/app/components/tramway/entity_component.html.haml +2 -1
- data/docs/AGENTS.md +280 -8
- data/lib/tramway/helpers/views_helper.rb +4 -5
- data/lib/tramway/version.rb +1 -1
- metadata +1 -3
- data/app/components/tailwinds/form/submit_button_component.html.haml +0 -11
- data/app/components/tailwinds/form/submit_button_component.rb +0 -18
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 073b1293c7f3778243b4402bd9db528eea16b9897145f5ac7a50bb0751607dfd
|
|
4
|
+
data.tar.gz: 980e71accc0572795aaa87764af580f50d883fa504b4b148fd5224826941c110
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4819641881ea15d5ef0211470aab28fad0c758ac2f733bab1c8b2a319ae0b4794973df321a45d0bc054c273c9d567db1c86325a9b2739e40a818b101106c9b3a
|
|
7
|
+
data.tar.gz: 331ddb0387c6ee4339e1988a69c79cb9851d5f33f2ccd519036dec9d88c5b8d7fcd3744418e881550c915f568a6efb8fe352c4e80d0a08eb79b3833469221662
|
data/README.md
CHANGED
|
@@ -264,7 +264,7 @@ Tramway.configure do |config|
|
|
|
264
264
|
end
|
|
265
265
|
```
|
|
266
266
|
|
|
267
|
-
**
|
|
267
|
+
**fields method**
|
|
268
268
|
|
|
269
269
|
Use `form_fields` in your form class to customize which form helpers get rendered and which options are passed to them.
|
|
270
270
|
Each field must map to a form helper method name. When you need to pass options, use a hash where `:type` is the helper
|
|
@@ -275,6 +275,7 @@ class UserForm < Tramway::BaseForm
|
|
|
275
275
|
properties :email, :about_me
|
|
276
276
|
|
|
277
277
|
fields email: :email,
|
|
278
|
+
name: :text,
|
|
278
279
|
about_me: {
|
|
279
280
|
type: :text_area,
|
|
280
281
|
rows: 5
|
|
@@ -287,6 +288,7 @@ The configuration above renders:
|
|
|
287
288
|
```erb
|
|
288
289
|
<%= tramway_form_for .... do |f| %>
|
|
289
290
|
<%= f.email_field :email %>
|
|
291
|
+
<%= f.text_field :name %>
|
|
290
292
|
<%= f.text_area :about_me, rows: 5 %>
|
|
291
293
|
```
|
|
292
294
|
|
|
@@ -893,13 +895,46 @@ component applies.
|
|
|
893
895
|
|
|
894
896
|
Tramway ships with helpers for common UI patterns built on top of Tailwind components.
|
|
895
897
|
|
|
896
|
-
|
|
897
|
-
options such as `color`, `type`, and `size`. It uses Rails' `button_to` helper by default (or when `link: false` is passed),
|
|
898
|
-
and switches to `link_to` when you set `link: true`.
|
|
898
|
+
`tramway_button` helper is designed for developers who don't want to think about what type of button must be used now. It can render 3 types of buttons: `a` (links), `button`, `form` with button.
|
|
899
899
|
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
900
|
+
You can set a type to render explicitly:
|
|
901
|
+
|
|
902
|
+
```ruby
|
|
903
|
+
tramway_button tag: :a, text: 'Link' #=> <a class=BUTTON_CLASSES>Link</a>
|
|
904
|
+
tramway_button tag: :button, text: 'Link' #=> <button class=BUTTON_CLASSES>Link</button>
|
|
905
|
+
tramway_button tag: :form, text: 'Link' #=> <form><button class=BUTTON_CLASSES>Link</button></form>
|
|
906
|
+
```
|
|
907
|
+
|
|
908
|
+
OR `tramway_button` choose the most appropriate button type by the arguments received.
|
|
909
|
+
|
|
910
|
+
#### `tramway_button` options
|
|
911
|
+
|
|
912
|
+
**path**
|
|
913
|
+
|
|
914
|
+
Example 1: rendering link
|
|
915
|
+
```erb
|
|
916
|
+
<%= tramway_button path: '/projects', text: 'Projects' %>
|
|
917
|
+
|
|
918
|
+
#=> <a href='/projects' class="...">Projects</a>
|
|
919
|
+
```
|
|
920
|
+
|
|
921
|
+
Example 2: rendering form
|
|
922
|
+
```erb
|
|
923
|
+
<%= tramway_button path: '/projects/1', text: 'Destroy', method: :delete %>
|
|
924
|
+
|
|
925
|
+
#> <form action="/projects/1" method="post">
|
|
926
|
+
#> ....
|
|
927
|
+
#> <button class: "..." type="submit">
|
|
928
|
+
#> Delete
|
|
929
|
+
#> </button>
|
|
930
|
+
```
|
|
931
|
+
|
|
932
|
+
Example 3: rendering button
|
|
933
|
+
```
|
|
934
|
+
<%= tramway_button path: '/projects/1', text: 'Edit', tag: :button %>
|
|
935
|
+
|
|
936
|
+
#> <button onclick="window.location.href='/projects/1' class="...">Edit</button>
|
|
937
|
+
```
|
|
903
938
|
|
|
904
939
|
All additional keyword arguments are forwarded to the underlying component as HTML attributes.
|
|
905
940
|
|
|
@@ -914,30 +949,6 @@ Tramway ships with helpers for common UI patterns built on top of Tailwind compo
|
|
|
914
949
|
|
|
915
950
|
The `type` option maps semantic intent to [Lantern Color Palette](https://github.com/TrinityMonsters/tramway/blob/main/README.md#lantern-color-palette).
|
|
916
951
|
|
|
917
|
-
If none of the predefined semantic types fit your needs, you can supply a Tailwind color family directly using the `color`
|
|
918
|
-
option—for example: `color: :gray`. When you pass a custom color ensure the corresponding utility classes exist in your
|
|
919
|
-
Tailwind configuration. Add the following safelist entries (adjusting the color name as needed) to `config/tailwind.config.js`:
|
|
920
|
-
|
|
921
|
-
```js
|
|
922
|
-
// config/tailwind.config.js
|
|
923
|
-
module.exports = {
|
|
924
|
-
// ...
|
|
925
|
-
safelist: [
|
|
926
|
-
// existing entries …
|
|
927
|
-
{
|
|
928
|
-
pattern: /(bg|hover:bg|dark:bg|dark:hover:bg)-gray-(500|600|700|800)/,
|
|
929
|
-
},
|
|
930
|
-
],
|
|
931
|
-
}
|
|
932
|
-
```
|
|
933
|
-
|
|
934
|
-
Tailwind will then emit the `bg-gray-500`, `hover:bg-gray-700`, `dark:bg-gray-600`, and `dark:hover:bg-gray-800` classes that
|
|
935
|
-
Tramway buttons expect when you opt into a custom color.
|
|
936
|
-
|
|
937
|
-
```erb
|
|
938
|
-
<%= tramway_button path: user_path(user), text: 'View profile', color: :emerald, data: { turbo: false } %>
|
|
939
|
-
```
|
|
940
|
-
|
|
941
952
|
* `tramway_badge` renders a Tailwind-styled badge with the provided `text`. Pass a semantic `type` (for example, `:success` or
|
|
942
953
|
`:danger`) to use the built-in color mappings, or supply a custom Tailwind color family with `color:`. When you opt into a
|
|
943
954
|
custom color, ensure the corresponding background utilities are available in your Tailwind safelist.
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
- if text.present?
|
|
2
|
-
-
|
|
2
|
+
- case @tag
|
|
3
|
+
- when :a
|
|
3
4
|
= link_to text, path, class: classes, **render_options
|
|
4
|
-
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
= button_to text, path, method:, form: form_options, class: classes, **render_options
|
|
5
|
+
- when :button
|
|
6
|
+
%button{ class: classes, **render_options }
|
|
7
|
+
= text
|
|
8
|
+
- when :form
|
|
9
|
+
= helpers.button_to text, path, method:, form: form_options, class: classes, **render_options
|
|
10
10
|
- else
|
|
11
|
-
-
|
|
11
|
+
- case @tag
|
|
12
|
+
- when :a
|
|
12
13
|
= link_to path, class: classes, **render_options do
|
|
13
14
|
= content
|
|
14
|
-
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
=
|
|
20
|
-
= content
|
|
15
|
+
- when :button
|
|
16
|
+
%button{ type: :submit, name: :commit, class: classes, **render_options }
|
|
17
|
+
= content
|
|
18
|
+
- when :form
|
|
19
|
+
= helpers.button_to path, method:, class: classes, form: form_options, **render_options do
|
|
20
|
+
= content
|
|
@@ -10,10 +10,21 @@ module Tailwinds
|
|
|
10
10
|
option :type, optional: true
|
|
11
11
|
option :size, default: -> { :medium }
|
|
12
12
|
option :method, optional: true, default: -> { :get }
|
|
13
|
-
option :
|
|
13
|
+
option :tag, optional: true, default: -> { false }
|
|
14
14
|
option :options, optional: true, default: -> { {} }
|
|
15
15
|
option :form_options, optional: true, default: -> { {} }
|
|
16
16
|
|
|
17
|
+
def before_render
|
|
18
|
+
return if tag.present?
|
|
19
|
+
return @tag = :button if type == :submit
|
|
20
|
+
|
|
21
|
+
URI.parse(path)
|
|
22
|
+
|
|
23
|
+
return @tag = :a if method.to_s.downcase == 'get'
|
|
24
|
+
|
|
25
|
+
@tag = :form
|
|
26
|
+
end
|
|
27
|
+
|
|
17
28
|
def size_classes
|
|
18
29
|
unless size.in?(%i[small medium large])
|
|
19
30
|
raise ArgumentError, "Invalid size: #{size}. Valid sizes are :small, :medium, :large."
|
|
@@ -29,7 +40,7 @@ module Tailwinds
|
|
|
29
40
|
def classes
|
|
30
41
|
(default_classes +
|
|
31
42
|
color_classes +
|
|
32
|
-
(
|
|
43
|
+
(@tag == :a ? %w[px-1 h-fit w-fit] : [cursor_class])).compact.join(' ')
|
|
33
44
|
end
|
|
34
45
|
|
|
35
46
|
def default_classes
|
|
@@ -57,17 +68,6 @@ module Tailwinds
|
|
|
57
68
|
options[:disabled] || false
|
|
58
69
|
end
|
|
59
70
|
|
|
60
|
-
def render_a_tag?
|
|
61
|
-
return true if link
|
|
62
|
-
return true if path == '#' && type != :submit
|
|
63
|
-
|
|
64
|
-
uri = URI.parse(path)
|
|
65
|
-
|
|
66
|
-
return true if method.to_s.downcase == 'get' && uri.query && !uri.query.empty?
|
|
67
|
-
|
|
68
|
-
false
|
|
69
|
-
end
|
|
70
|
-
|
|
71
71
|
def render_options
|
|
72
72
|
base_options = options.except(:class)
|
|
73
73
|
return base_options unless stop_cell_propagation?
|
|
@@ -88,7 +88,7 @@ module Tailwinds
|
|
|
88
88
|
end
|
|
89
89
|
|
|
90
90
|
def cursor_class
|
|
91
|
-
if
|
|
91
|
+
if @tag != :a && !disabled?
|
|
92
92
|
'cursor-pointer'
|
|
93
93
|
else
|
|
94
94
|
'cursor-not-allowed'
|
|
@@ -92,7 +92,7 @@ module Tailwinds
|
|
|
92
92
|
def submit(action, **options, &)
|
|
93
93
|
sanitized_options = sanitize_options(options)
|
|
94
94
|
|
|
95
|
-
render(Tailwinds::
|
|
95
|
+
render(Tailwinds::ButtonComponent.new(text: action, size: form_size, type: :submit, **sanitized_options), &)
|
|
96
96
|
end
|
|
97
97
|
|
|
98
98
|
private
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
= tramway_button text: t('tramway.actions.edit'),
|
|
10
10
|
path: Tramway::Engine.routes.url_helpers.public_send(entity.routes.edit, item.id),
|
|
11
11
|
type: :will,
|
|
12
|
-
size: :small
|
|
12
|
+
size: :small,
|
|
13
|
+
tag: :form
|
|
13
14
|
|
|
14
15
|
- if @entity.page(:destroy).present?
|
|
15
16
|
= tramway_button text: t('tramway.actions.destroy'),
|
data/docs/AGENTS.md
CHANGED
|
@@ -78,14 +78,285 @@ config/
|
|
|
78
78
|
|
|
79
79
|
## Rules
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
81
|
+
### Rule 1
|
|
82
|
+
If CRUD is requested or some default actions like (index, show, create, update, destroy) are requestsed, use Tramway Entities by default unless custom behavior is needed. Configure in `config/initializers/tramway.rb`. Do not create controllers, views, or routes manually for CRUD actions if Tramway Entities can handle it.
|
|
83
|
+
|
|
84
|
+
When `namespace` is mentioned in the request, configure it in the entity definition.
|
|
85
|
+
|
|
86
|
+
Example of CRUD configuration for model `Participant`:
|
|
87
|
+
|
|
88
|
+
*config/initializers/tramway.rb*:
|
|
89
|
+
```ruby
|
|
90
|
+
Tramway.configure do |config|
|
|
91
|
+
config.entities = [
|
|
92
|
+
{
|
|
93
|
+
name: :participant,
|
|
94
|
+
pages: [
|
|
95
|
+
{ action: :index },
|
|
96
|
+
{ action: :show },
|
|
97
|
+
{ action: :create },
|
|
98
|
+
{ action: :update },
|
|
99
|
+
{ action: :destroy }
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
]
|
|
103
|
+
end
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Rule 2
|
|
107
|
+
Normalize input with `normalizes` (from Tramway) for attributes like email, phone, etc. Don't use `normalizes` in model unless it requested explicitly.
|
|
108
|
+
|
|
109
|
+
### Rule 3
|
|
110
|
+
Use Tramway Navbar for navigation
|
|
111
|
+
|
|
112
|
+
### Rule 4
|
|
113
|
+
Use Tramway Flash for user notifications.
|
|
114
|
+
|
|
115
|
+
### Rule 5
|
|
116
|
+
Use Tramway Table for tabular data display.
|
|
117
|
+
|
|
118
|
+
### Rule 6
|
|
119
|
+
Use Tramway Button for buttons.
|
|
120
|
+
|
|
121
|
+
### Rule 7
|
|
122
|
+
Use `tramway_form_for` instead `form_with`, `form_for`
|
|
123
|
+
|
|
124
|
+
### Rule 8
|
|
125
|
+
Inherit all components from Tramway::BaseComponent
|
|
126
|
+
|
|
127
|
+
### Rule 9
|
|
128
|
+
If page `create` or `update` is configured for an entity, use Tramway Form pattern for forms. Visible fields are configured via `form_fields` method.
|
|
129
|
+
|
|
130
|
+
Use form_fields in your form class to customize which form helpers get rendered and which options are passed to them. Each field must map to a form helper method name. When you need to pass options, use a hash where :type is the helper method name and the remaining keys are passed as named arguments.
|
|
131
|
+
|
|
132
|
+
Example:
|
|
133
|
+
|
|
134
|
+
*app/forms/user_form.rb*:
|
|
135
|
+
```ruby
|
|
136
|
+
class UserForm < Tramway::BaseForm
|
|
137
|
+
properties :email, :about_me
|
|
138
|
+
|
|
139
|
+
fields email: :email,
|
|
140
|
+
name: :text,
|
|
141
|
+
about_me: {
|
|
142
|
+
type: :text_area,
|
|
143
|
+
rows: 5
|
|
144
|
+
}
|
|
145
|
+
end
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Rule 10
|
|
149
|
+
Do not use `strong_parameters` in controllers. Use Tramway Form pattern for parameter whitelisting.
|
|
150
|
+
|
|
151
|
+
### Rule 11
|
|
152
|
+
Create tests for show models pages inside `spec/features/#{pluralized model_name}/show_spec.rb` using RSpec and Capybara if it needed.
|
|
153
|
+
|
|
154
|
+
Here is an example for `Task` model:
|
|
155
|
+
|
|
156
|
+
```ruby
|
|
157
|
+
describe 'Tasks Show Page', type: :feature do
|
|
158
|
+
let!(:task) do
|
|
159
|
+
create(:task)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it 'displays the task' do
|
|
163
|
+
visit task_path(task)
|
|
164
|
+
|
|
165
|
+
expect(page).to have_current_path(task_path(task))
|
|
166
|
+
expect(page).to have_content(task.name)
|
|
167
|
+
expect(page).to have_content('Pending')
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Rule 12
|
|
173
|
+
Create tests for index models pages inside `spec/features/#{pluralized model_name}/index_spec.rb` using RSpec and Capybara if it needed.
|
|
174
|
+
|
|
175
|
+
Here is an example for `Project` model:
|
|
176
|
+
|
|
177
|
+
```ruby
|
|
178
|
+
describe 'Projects Index Page', type: :feature do
|
|
179
|
+
let!(:projects) { create_list(:project, 3) }
|
|
180
|
+
|
|
181
|
+
describe 'visiting the index page' do
|
|
182
|
+
before do
|
|
183
|
+
visit projects_path
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it 'displays all projects' do
|
|
187
|
+
expect(page).to have_current_path(projects_path)
|
|
188
|
+
|
|
189
|
+
projects.each do |project|
|
|
190
|
+
expect(page).to have_content(project.name)
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Rule 13
|
|
198
|
+
Create tests for create models pages inside `spec/features/#{pluralized model_name}/create_spec.rb` using RSpec and Capybara if it needed.
|
|
199
|
+
|
|
200
|
+
Here is an example for `Project` model:
|
|
201
|
+
|
|
202
|
+
```ruby
|
|
203
|
+
describe 'Projects Create', type: :feature do
|
|
204
|
+
let!(:project_attributes) do
|
|
205
|
+
attributes_for(:project)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
let(:project) { Project.last }
|
|
209
|
+
|
|
210
|
+
it 'creates a new project' do
|
|
211
|
+
visit new_project_path
|
|
212
|
+
|
|
213
|
+
expect(page).to have_current_path(new_project_path)
|
|
214
|
+
|
|
215
|
+
fill_in 'project[name]', with: project_attributes[:name]
|
|
216
|
+
fill_in 'project[description]', with: project_attributes[:description]
|
|
217
|
+
select project_attributes[:project_type], from: 'project[project_type]'
|
|
218
|
+
|
|
219
|
+
click_on 'Save'
|
|
220
|
+
|
|
221
|
+
expect(project).to have_attributes(
|
|
222
|
+
name: project_attributes[:name],
|
|
223
|
+
description: project_attributes[:description],
|
|
224
|
+
)
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Rule 14
|
|
230
|
+
Create tests for update models pages inside `spec/features/#{pluralized model_name}/update_spec.rb` using RSpec and Capybara if it needed.
|
|
231
|
+
|
|
232
|
+
Here is an example for `Project` model:
|
|
233
|
+
|
|
234
|
+
```ruby
|
|
235
|
+
describe 'Projects Update', type: :feature do
|
|
236
|
+
let!(:project) do
|
|
237
|
+
create('project', user: current_user)
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
let!(:project_attributes) do
|
|
241
|
+
attributes_for(:project)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
it 'updates the project' do
|
|
245
|
+
visit edit_project_path(project)
|
|
246
|
+
|
|
247
|
+
expect(page).to have_current_path(edit_project_path(project))
|
|
248
|
+
|
|
249
|
+
fill_in 'project[name]', with: project_attributes[:name]
|
|
250
|
+
fill_in 'project[description]', with: project_attributes[:description]
|
|
251
|
+
|
|
252
|
+
click_on 'Save'
|
|
253
|
+
|
|
254
|
+
expect(page).to have_content('Project was successfully updated.')
|
|
255
|
+
expect(page).to have_content(project_attributes[:name])
|
|
256
|
+
expect(page).to have_content(project_attributes[:description])
|
|
257
|
+
|
|
258
|
+
project.reload
|
|
259
|
+
|
|
260
|
+
expect(project).to have_attributes(
|
|
261
|
+
name: project_attributes[:name],
|
|
262
|
+
description: project_attributes[:description]
|
|
263
|
+
)
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Rule 15
|
|
269
|
+
Create tests for destroy models pages inside `spec/features/#{pluralized model_name}/destroy_spec.rb` using RSpec and Capybara if it needed.
|
|
270
|
+
|
|
271
|
+
Here is an example for `Project` model:
|
|
272
|
+
|
|
273
|
+
```ruby
|
|
274
|
+
describe 'Project Destroy', type: :feature do
|
|
275
|
+
let!(:project) do
|
|
276
|
+
create('project')
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
it 'destroys the project' do
|
|
280
|
+
visit project_path(project)
|
|
281
|
+
|
|
282
|
+
expect(page).to have_current_path(project_path(project))
|
|
283
|
+
|
|
284
|
+
click_on 'Delete'
|
|
285
|
+
|
|
286
|
+
expect(page).to have_content('Project was successfully destroyed.')
|
|
287
|
+
|
|
288
|
+
expect { Project.find(project.id) }.to raise_error(ActiveRecord::RecordNotFound)
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Rule 16
|
|
294
|
+
If you created any tests for Tramway Entities pages, make sure to add this to `spec/rails_helper.rb`.
|
|
295
|
+
|
|
296
|
+
*spec/rails_helper.rb*:
|
|
297
|
+
```ruby
|
|
298
|
+
RSpec.configure do |config|
|
|
299
|
+
config.include Tramway::Helpers::RoutesHelper, type: :feature
|
|
300
|
+
end
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Rule 17
|
|
304
|
+
If application has authentication in the web then use `application_controller` config in `config/initializers/tramway.rb` to setup authentication method for Tramway Entities.
|
|
305
|
+
|
|
306
|
+
*config/initializers/tramway.rb*:
|
|
307
|
+
```ruby
|
|
308
|
+
Tramway.configure do |config|
|
|
309
|
+
config.application_controller = 'ApplicationController'
|
|
310
|
+
end
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Rule 18
|
|
314
|
+
If you use `index` page for Tramway Entity, make sure to create `index_attributes` method in the entity decorator.
|
|
315
|
+
|
|
316
|
+
Example for `Participant` model:
|
|
317
|
+
|
|
318
|
+
*app/decorators/participant_decorator.rb*:
|
|
319
|
+
```ruby
|
|
320
|
+
class ParticipantDecorator < Tramway::BaseDecorator
|
|
321
|
+
def self.index_attributes
|
|
322
|
+
[
|
|
323
|
+
:id,
|
|
324
|
+
:name,
|
|
325
|
+
:email,
|
|
326
|
+
:created_at
|
|
327
|
+
]
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Rule 19
|
|
333
|
+
In specs ALWAYS use factories (FactoryBot gem) to create models and attributes hash. In case there is no factory for the model, create one inside `spec/factories/#{pluralized model_name}.rb`.
|
|
334
|
+
|
|
335
|
+
### Rule 20
|
|
336
|
+
In case you need enumerize for model attribute, make sure to use `enumerize` gem for that. DO NOT use `boolean` or `integer` types for enumerations.
|
|
337
|
+
|
|
338
|
+
### Rule 21
|
|
339
|
+
In case you need something that looks like enumerize but it's a process state, use `aasm` gem for that.
|
|
340
|
+
|
|
341
|
+
### Rule 22
|
|
342
|
+
Use model scopes instead of creating private methods for object collections.
|
|
343
|
+
|
|
344
|
+
### Rule 23
|
|
345
|
+
Use `tramway_title` for the main title on pages
|
|
346
|
+
|
|
347
|
+
Example
|
|
348
|
+
*app/models/user.rb*
|
|
349
|
+
```ruby
|
|
350
|
+
class User < ApplicationRecord
|
|
351
|
+
scope :this_month_registered_users, -> { where(created_at: Time.current.all_month) }
|
|
352
|
+
end
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### Rule 24
|
|
356
|
+
In case you implementing API, use `api` namespaces for forms and decorators.
|
|
357
|
+
|
|
358
|
+
### Rule 25
|
|
359
|
+
DO NOT use `#{model_name}_params` method with `permit` method inside controllers. When you use `tramway_form`, it's unnecessary.
|
|
89
360
|
|
|
90
361
|
## Controller Patterns
|
|
91
362
|
|
|
@@ -141,6 +412,7 @@ class ParticipantsController < ApplicationController
|
|
|
141
412
|
end
|
|
142
413
|
```
|
|
143
414
|
|
|
415
|
+
|
|
144
416
|
---
|
|
145
417
|
|
|
146
418
|
## Tailwind Practices
|
|
@@ -40,12 +40,11 @@ module Tramway
|
|
|
40
40
|
component 'tailwinds/table/cell', &
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
def tramway_button(path: nil, text: nil, method: :get, form_options: {}, **options, &)
|
|
44
|
+
component 'tailwinds/button', text:, path:, method:, form_options:, color: options.delete(:color),
|
|
45
|
+
type: options.delete(:type), size: options.delete(:size),
|
|
46
|
+
tag: options.delete(:tag), options:, &
|
|
47
47
|
end
|
|
48
|
-
# rubocop:enable Metrics/ParameterLists
|
|
49
48
|
|
|
50
49
|
def tramway_back_button
|
|
51
50
|
component 'tailwinds/back_button'
|
data/lib/tramway/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tramway
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.2.
|
|
4
|
+
version: 2.2.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- kalashnikovisme
|
|
@@ -178,8 +178,6 @@ files:
|
|
|
178
178
|
- app/components/tailwinds/form/number_field_component.rb
|
|
179
179
|
- app/components/tailwinds/form/select_component.html.haml
|
|
180
180
|
- app/components/tailwinds/form/select_component.rb
|
|
181
|
-
- app/components/tailwinds/form/submit_button_component.html.haml
|
|
182
|
-
- app/components/tailwinds/form/submit_button_component.rb
|
|
183
181
|
- app/components/tailwinds/form/text_area_component.html.haml
|
|
184
182
|
- app/components/tailwinds/form/text_area_component.rb
|
|
185
183
|
- app/components/tailwinds/form/text_field_component.html.haml
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Tailwinds
|
|
4
|
-
module Form
|
|
5
|
-
# Tailwind-styled submit button
|
|
6
|
-
class SubmitButtonComponent < TailwindComponent
|
|
7
|
-
def initialize(action, size: :medium, **options)
|
|
8
|
-
unless size.in?(%i[small medium large])
|
|
9
|
-
raise ArgumentError, "Invalid size: #{size}. Valid sizes are :small, :medium, :large."
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
@text = action.is_a?(String) ? action : action.to_s.capitalize
|
|
13
|
-
|
|
14
|
-
super(input: nil, attribute: nil, value: nil, options: options.except(:type), label: nil, for: nil, size:)
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|