dynamic_scaffold 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +465 -0
- data/Rakefile +32 -0
- data/app/assets/config/dynamic_scaffold_manifest.js +0 -0
- data/app/assets/images/dynamic_scaffold/fontawesome/README.md +9 -0
- data/app/assets/images/dynamic_scaffold/fontawesome/angle-double-down.svg +1 -0
- data/app/assets/images/dynamic_scaffold/fontawesome/angle-double-up.svg +1 -0
- data/app/assets/images/dynamic_scaffold/fontawesome/chevron-down.svg +1 -0
- data/app/assets/images/dynamic_scaffold/fontawesome/chevron-left.svg +1 -0
- data/app/assets/images/dynamic_scaffold/fontawesome/chevron-right.svg +1 -0
- data/app/assets/images/dynamic_scaffold/fontawesome/chevron-up.svg +1 -0
- data/app/assets/images/dynamic_scaffold/fontawesome/exclamation-circle.svg +1 -0
- data/app/assets/images/dynamic_scaffold/fontawesome/hdd.svg +1 -0
- data/app/assets/images/dynamic_scaffold/fontawesome/pencil-alt.svg +1 -0
- data/app/assets/images/dynamic_scaffold/fontawesome/plus.svg +1 -0
- data/app/assets/images/dynamic_scaffold/fontawesome/step-backward.svg +1 -0
- data/app/assets/images/dynamic_scaffold/fontawesome/step-forward.svg +1 -0
- data/app/assets/images/dynamic_scaffold/fontawesome/times.svg +1 -0
- data/app/assets/javascripts/dynamic_scaffold/common.js +95 -0
- data/app/assets/javascripts/dynamic_scaffold/delete.js +57 -0
- data/app/assets/javascripts/dynamic_scaffold/pagination.js +26 -0
- data/app/assets/javascripts/dynamic_scaffold/sorter.js +120 -0
- data/app/assets/javascripts/dynamic_scaffold.js +4 -0
- data/app/assets/stylesheets/dynamic_scaffold/bootstrap3.scss +22 -0
- data/app/assets/stylesheets/dynamic_scaffold/bootstrap4.scss +34 -0
- data/app/assets/stylesheets/dynamic_scaffold/common.scss +130 -0
- data/app/assets/stylesheets/dynamic_scaffold/resplist.scss +155 -0
- data/app/views/dynamic_scaffold/bootstrap/_edit.html.erb +1 -0
- data/app/views/dynamic_scaffold/bootstrap/_form.html.erb +53 -0
- data/app/views/dynamic_scaffold/bootstrap/_list.html.erb +88 -0
- data/app/views/dynamic_scaffold/bootstrap/_new.html.erb +1 -0
- data/app/views/dynamic_scaffold/bootstrap/_pagination.html.erb +5 -0
- data/app/views/dynamic_scaffold/bootstrap/_save_order.html.erb +7 -0
- data/app/views/dynamic_scaffold/bootstrap/kaminari/_first_page.html.erb +7 -0
- data/app/views/dynamic_scaffold/bootstrap/kaminari/_gap.html.erb +3 -0
- data/app/views/dynamic_scaffold/bootstrap/kaminari/_last_page.html.erb +7 -0
- data/app/views/dynamic_scaffold/bootstrap/kaminari/_next_page.html.erb +7 -0
- data/app/views/dynamic_scaffold/bootstrap/kaminari/_page.html.erb +9 -0
- data/app/views/dynamic_scaffold/bootstrap/kaminari/_paginator.html.erb +17 -0
- data/app/views/dynamic_scaffold/bootstrap/kaminari/_prev_page.html.erb +7 -0
- data/config/locales/en.yml +19 -0
- data/config/locales/ja.yml +28 -0
- data/config/routes.rb +2 -0
- data/lib/dynamic_scaffold/config.rb +263 -0
- data/lib/dynamic_scaffold/controller.rb +116 -0
- data/lib/dynamic_scaffold/controller_utilities.rb +115 -0
- data/lib/dynamic_scaffold/engine.rb +18 -0
- data/lib/dynamic_scaffold/error/base.rb +6 -0
- data/lib/dynamic_scaffold/error/controller.rb +6 -0
- data/lib/dynamic_scaffold/error/invalid_icon.rb +6 -0
- data/lib/dynamic_scaffold/form/item/base.rb +106 -0
- data/lib/dynamic_scaffold/form/item/block.rb +16 -0
- data/lib/dynamic_scaffold/form/item/single_option.rb +21 -0
- data/lib/dynamic_scaffold/form/item/two_options.rb +28 -0
- data/lib/dynamic_scaffold/form/item/two_options_with_block.rb +19 -0
- data/lib/dynamic_scaffold/icons/fontawesome.rb +47 -0
- data/lib/dynamic_scaffold/list/item.rb +35 -0
- data/lib/dynamic_scaffold/routes.rb +23 -0
- data/lib/dynamic_scaffold/version.rb +3 -0
- data/lib/dynamic_scaffold.rb +12 -0
- data/lib/generators/dynamic_scaffold/USAGE +19 -0
- data/lib/generators/dynamic_scaffold/dynamic_scaffold_generator.rb +25 -0
- data/lib/generators/dynamic_scaffold/templates/controller.erb +100 -0
- data/lib/generators/dynamic_scaffold/templates/views/edit.erb +1 -0
- data/lib/generators/dynamic_scaffold/templates/views/index.erb +1 -0
- data/lib/generators/dynamic_scaffold/templates/views/new.erb +1 -0
- data/lib/tasks/dynamic_scaffold_tasks.rake +4 -0
- metadata +355 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 503b558204f2955326a5c0f2de8b6f53221a2d26
|
4
|
+
data.tar.gz: df41bb6e67d8199f9fa2eaea9b3a06efbac340e6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d57e575315a2c80f8e5d5595ca4b4ce06a4eb14c91d71e2c7a8d03693b882330ee1d42a934e7882597e4e276a45c6833e33e48be171e66b80a9eef5e9021e135
|
7
|
+
data.tar.gz: e665811c6ff308e2e40ccef3e33a98b7ccbf1757e27c9690062e5b9b7ad8e0607ff18941a134034684779196245983de5d0efd58cfd774f94e291ac2aa087fcd
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2017 Masamoto Miyata
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,465 @@
|
|
1
|
+
# DynamicScaffold
|
2
|
+
The Scaffold system which dynamically generates CRUD and sort functions.
|
3
|
+
|
4
|
+
## Feature
|
5
|
+
|
6
|
+
* This is generate the pages using same views dynamically.
|
7
|
+
* Support the responsive design and touch UI.
|
8
|
+
* Support sort and pagination.
|
9
|
+
* This has the views with the Twitter Bootstrap. Support bootstrap3/4.
|
10
|
+
* Customizable and flexible.
|
11
|
+
|
12
|
+
<img src="images/list_with_pager.png">
|
13
|
+
|
14
|
+
|
15
|
+
<img src="images/form.png">
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
## Installation
|
20
|
+
|
21
|
+
Add this line to your application's Gemfile:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
gem 'dynamic_scaffold', '~> 0.1'
|
25
|
+
```
|
26
|
+
|
27
|
+
And then execute:
|
28
|
+
```bash
|
29
|
+
$ bundle
|
30
|
+
```
|
31
|
+
|
32
|
+
## Usage
|
33
|
+
|
34
|
+
### Routes
|
35
|
+
|
36
|
+
Please call `dynamic_scaffold_for` method with the resource name.
|
37
|
+
|
38
|
+
```rb
|
39
|
+
# config/routes.rb
|
40
|
+
Rails.application.routes.draw do
|
41
|
+
dynamic_scaffold_for 'shops'
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
45
|
+
This will generate the following routes.
|
46
|
+
|
47
|
+
```
|
48
|
+
sort_or_destroy_controls_master_shops PATCH /:locale/controls/master/shops/sort_or_destroy(.:format) controls/shops#sort_or_destroy
|
49
|
+
controls_master_shops GET /:locale/controls/master/shops(.:format) controls/shops#index
|
50
|
+
POST /:locale/controls/master/shops(.:format) controls/shops#create
|
51
|
+
new_controls_master_shop GET /:locale/controls/master/shops/new(.:format) controls/shops#new
|
52
|
+
edit_controls_master_shop GET /:locale/controls/master/shops/:id/edit(.:format) controls/shops#edit
|
53
|
+
controls_master_shop PATCH /:locale/controls/master/shops/:id(.:format) controls/shops#update
|
54
|
+
PUT /:locale/controls/master/shops/:id(.:format) controls/shops#update
|
55
|
+
```
|
56
|
+
|
57
|
+
### Generate controller and views
|
58
|
+
|
59
|
+
First, you need a model of the target table. If you have not generate it yet, please generate the model.
|
60
|
+
|
61
|
+
```
|
62
|
+
rails generate model Shop
|
63
|
+
```
|
64
|
+
|
65
|
+
Next, execute the following command for generate the controller and views.
|
66
|
+
|
67
|
+
```
|
68
|
+
rails generate dynamic_scaffold shops
|
69
|
+
create app/controllers/shops_controller.rb
|
70
|
+
create app/views/shops/edit.html.erb
|
71
|
+
create app/views/shops/index.html.erb
|
72
|
+
create app/views/shops/new.html.erb
|
73
|
+
```
|
74
|
+
|
75
|
+
You can also specify namespaces and the model name if you want.
|
76
|
+
|
77
|
+
```
|
78
|
+
rails generate dynamic_scaffold namespace/plural_model
|
79
|
+
rails generate dynamic_scaffold namespace/controller Model
|
80
|
+
```
|
81
|
+
|
82
|
+
### Prepare CSS and Javascript
|
83
|
+
|
84
|
+
You need to load the files for CSS and Javascript. Currently, we support the Bootstrap 3 and Bootstrap 4.
|
85
|
+
|
86
|
+
```sass
|
87
|
+
# app/assets/stylesheets/application.scss
|
88
|
+
@import 'dynamic_scaffold/bootstrap3'
|
89
|
+
# or
|
90
|
+
@import 'dynamic_scaffold/bootstrap4'
|
91
|
+
```
|
92
|
+
|
93
|
+
```js
|
94
|
+
// app/assets/javascripts/application.js
|
95
|
+
//= require dynamic_scaffold
|
96
|
+
```
|
97
|
+
|
98
|
+
### Customization
|
99
|
+
|
100
|
+
You can customize each items in the block passed as dynamic_scaffold method argument.
|
101
|
+
|
102
|
+
```rb
|
103
|
+
# app/controllers/shops_controller.rb
|
104
|
+
class ShopController < ApplicationController
|
105
|
+
include DynamicScaffold::Controller
|
106
|
+
dynamic_scaffold Shop do |config|
|
107
|
+
# customize here
|
108
|
+
# `config` is DynamicScaffold::Config
|
109
|
+
end
|
110
|
+
end
|
111
|
+
```
|
112
|
+
|
113
|
+
#### Customize list
|
114
|
+
|
115
|
+
|
116
|
+
You can customize the list through the `DynamicScaffold::Config#list` property.
|
117
|
+
|
118
|
+
```rb
|
119
|
+
# app/controllers/shops_controller.rb
|
120
|
+
class ShopController < ApplicationController
|
121
|
+
include DynamicScaffold::Controller
|
122
|
+
dynamic_scaffold Shop do |config|
|
123
|
+
# You can set each title in the list through title method.
|
124
|
+
# Pass the attribute name,
|
125
|
+
# config.list.title(:name)
|
126
|
+
# or
|
127
|
+
# config.list.title do |record|
|
128
|
+
# record.name
|
129
|
+
# end
|
130
|
+
|
131
|
+
# First arg is attribute name of model.
|
132
|
+
# Last hash arg is given to HTML attributes options.
|
133
|
+
# `label` method change the label (I18n model attribute name is default).
|
134
|
+
config.list.item(:id, style: 'width: 80px').label('Number')
|
135
|
+
config.list.item :name, style: 'width: 120px'
|
136
|
+
|
137
|
+
# If you want to call a model method, specify the block.
|
138
|
+
config.list.item :updated_at, style: 'width: 180px' do |rec, name|
|
139
|
+
rec.fdate name, '%Y-%m-%d %H:%M:%S'
|
140
|
+
end
|
141
|
+
|
142
|
+
# The `label` method also accepts block.
|
143
|
+
config.list.item(:created_at, style: 'width: 180px').label 'Create Date' do |rec, name|
|
144
|
+
rec.fdate name, '%Y-%m-%d %H:%M:%S'
|
145
|
+
end
|
146
|
+
|
147
|
+
# The first argument can also be omitted, to display item that is not model attribute.
|
148
|
+
# The block is executed in the context of view, so you can call the method of view.
|
149
|
+
config.list.item do |rec, name|
|
150
|
+
link_to "Show #{rec.name}", controls_master_shops_path
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
```
|
155
|
+
|
156
|
+
#### Customize form
|
157
|
+
|
158
|
+
You can customize the form through the `DynamicScaffold::Config#form` property.
|
159
|
+
|
160
|
+
```rb
|
161
|
+
# app/controllers/shops_controller.rb
|
162
|
+
class ShopController < ApplicationController
|
163
|
+
include DynamicScaffold::Controller
|
164
|
+
dynamic_scaffold Shop do |config|
|
165
|
+
# config.form.item(type, name, html_attributes)
|
166
|
+
# or
|
167
|
+
# config.form.item(type, name, options, html_attributes)
|
168
|
+
#
|
169
|
+
# You can use form helper methods for type,
|
170
|
+
# text_field, check_box, radio_button, password_field, hidden_field, file_field, text_area, color_field,
|
171
|
+
# collection_check_boxes, collection_radio_buttons, collection_select, grouped_collection_select,
|
172
|
+
# time_select, date_select, datetime_select
|
173
|
+
|
174
|
+
|
175
|
+
# Default label is I18n model attribute name.
|
176
|
+
config.form.item :text_field, :name
|
177
|
+
# You can specify `label`.
|
178
|
+
config.form.item(:text_field, :name).label 'Shop Name'
|
179
|
+
# You can set default value for new action.
|
180
|
+
config.form.item(:text_field, :name).default('Foo Bar')
|
181
|
+
|
182
|
+
# If you use hidden_field, the label will also be hidden.
|
183
|
+
config.form.item :hidden_field, :id
|
184
|
+
# but if you specify the label explicitly it will be displayed.
|
185
|
+
config.form.item(:hidden_field, :id).label 'ID'
|
186
|
+
|
187
|
+
# Last hash arg is given to HTML attributes.
|
188
|
+
config.form.item :text_area, :memo, rows: 8
|
189
|
+
|
190
|
+
# Methods of the collection conform to the [ActionView::Helpers::FormBuilder](https://apidock.com/rails/ActionView/Helpers/FormBuilder) method.
|
191
|
+
config.form.item(:collection_select,
|
192
|
+
:category_id, Category.all, :id, :name, include_blank: 'Select Category'
|
193
|
+
)
|
194
|
+
config.form.item(:collection_check_boxes, :state_ids, State.all, :id, :name)
|
195
|
+
config.form.item(:collection_radio_buttons, :status, Shop.statuses.map{|k, v| [v, k.titleize]}, :first, :last)
|
196
|
+
|
197
|
+
# If you want to display more free form field, use block.
|
198
|
+
# The block is executed in the context of view, so you can call the method of view.
|
199
|
+
config.form.item :block, :free do |form, field|
|
200
|
+
content_tag :div, class: 'foobar' do
|
201
|
+
form.text_field field.name, class: 'foobar'
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
# The label of block method also accepts block.
|
206
|
+
config.form.item(:block, :free).label 'Free Value' do |form, field|
|
207
|
+
content_tag :div, class: 'foobar' do
|
208
|
+
form.text_field field.name, class: 'foobar'
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
# You can also add a note to the form field.
|
213
|
+
config.form.item(:text_field, :name).note do
|
214
|
+
content_tag :p do
|
215
|
+
out = []
|
216
|
+
out << 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, '
|
217
|
+
out << 'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'
|
218
|
+
out << tag(:br)
|
219
|
+
out << 'Ut enim ad minim veniam, quis nostrud exercitation ullamco '
|
220
|
+
out << 'laboris nisi ut aliquip ex ea commodo consequat. '
|
221
|
+
out << tag(:br)
|
222
|
+
safe_join(out)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
```
|
228
|
+
|
229
|
+
### Sorting
|
230
|
+
|
231
|
+
You can sort records having integer column for order in the list page.
|
232
|
+
|
233
|
+
```rb
|
234
|
+
class CreateCountries < ActiveRecord::Migration[5.1]
|
235
|
+
def change
|
236
|
+
create_table :countries do |t|
|
237
|
+
t.string :name
|
238
|
+
t.integer :sequence
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
```
|
243
|
+
|
244
|
+
```
|
245
|
+
rails generate dynamic_scaffold countries
|
246
|
+
```
|
247
|
+
|
248
|
+
```rb
|
249
|
+
# app/controllers/countries_controller.rb
|
250
|
+
class CountriesController < ApplicationController
|
251
|
+
include DynamicScaffold::Controller
|
252
|
+
dynamic_scaffold Country do |config|
|
253
|
+
config.list.sorter sequence: :desc
|
254
|
+
...
|
255
|
+
```
|
256
|
+
|
257
|
+
<img src="images/sorter.gif">
|
258
|
+
|
259
|
+
### Pagination
|
260
|
+
|
261
|
+
You can enable pagination with [kaminari](https://github.com/kaminari/kaminari).
|
262
|
+
|
263
|
+
```rb
|
264
|
+
# app/controllers/shops_controller.rb
|
265
|
+
class ShopController < ApplicationController
|
266
|
+
include DynamicScaffold::Controller
|
267
|
+
dynamic_scaffold Shop do |config|
|
268
|
+
config.list.pagination per_page: 20
|
269
|
+
...
|
270
|
+
```
|
271
|
+
|
272
|
+
The following options are available for the pagination.
|
273
|
+
|
274
|
+
```
|
275
|
+
window: 0, # kaminari options
|
276
|
+
outer_window: 0, # kaminari options
|
277
|
+
left: 0, # kaminari options
|
278
|
+
right: 0, # kaminari options
|
279
|
+
param_name: :page, # kaminari options
|
280
|
+
total_count: true, # Whether to display total count and active page, like `2/102`.
|
281
|
+
end_buttons: true, # Whether to display buttons to the first and last page.
|
282
|
+
neighbor_buttons: true, # Whether to display buttons to the next and prev page.
|
283
|
+
gap_buttons: false, # Whether to display gap buttons.
|
284
|
+
highlight_current: false, # Whether to highlight the current page.
|
285
|
+
```
|
286
|
+
|
287
|
+
### Scoping
|
288
|
+
|
289
|
+
You can scoping for target items by url param.
|
290
|
+
|
291
|
+
For example, you create the Scaffold of users for each role.
|
292
|
+
```rb
|
293
|
+
create_table :users do |t|
|
294
|
+
t.string :email, null: false
|
295
|
+
t.string :encrypted_password, null: false
|
296
|
+
t.integer :role, limit: 2, null: false
|
297
|
+
end
|
298
|
+
|
299
|
+
class User < ApplicationRecord
|
300
|
+
enum role: { admin: 1, staff: 2, member: 3 }
|
301
|
+
end
|
302
|
+
```
|
303
|
+
|
304
|
+
Set the route as follows.
|
305
|
+
|
306
|
+
```rb
|
307
|
+
Rails.application.routes.draw do
|
308
|
+
dynamic_scaffold_for 'users/:role', controller: 'users', as: 'users', role: Regexp.new(User.roles.keys.join('|'))
|
309
|
+
end
|
310
|
+
```
|
311
|
+
|
312
|
+
```
|
313
|
+
sort_or_destroy_controls_master_users PATCH /:locale/controls/master/users/:role/sort_or_destroy(.:format) controls/users#sort_or_destroy {:role=>/admin|staff|member/}
|
314
|
+
controls_master_users GET /:locale/controls/master/users/:role(.:format) controls/users#index {:role=>/admin|staff|member/}
|
315
|
+
POST /:locale/controls/master/users/:role(.:format) controls/users#create {:role=>/admin|staff|member/}
|
316
|
+
new_controls_master_user GET /:locale/controls/master/users/:role/new(.:format) controls/users#new {:role=>/admin|staff|member/}
|
317
|
+
edit_controls_master_user GET /:locale/controls/master/users/:role/:id/edit(.:format) controls/users#edit {:role=>/admin|staff|member/}
|
318
|
+
controls_master_user PATCH /:locale/controls/master/users/:role/:id(.:format) controls/users#update {:role=>/admin|staff|member/}
|
319
|
+
PUT /:locale/controls/master/users/:role/:id(.:format) controls/users#update {:role=>/admin|staff|member/}
|
320
|
+
```
|
321
|
+
|
322
|
+
For the controller, as follows.
|
323
|
+
|
324
|
+
```rb
|
325
|
+
# app/controllers/users_controller.rb
|
326
|
+
class UsersController < ApplicationController
|
327
|
+
include DynamicScaffold::Controller
|
328
|
+
dynamic_scaffold User do |c|
|
329
|
+
c.scope [:role]
|
330
|
+
...
|
331
|
+
```
|
332
|
+
|
333
|
+
|
334
|
+
### View helper
|
335
|
+
|
336
|
+
#### dynamic_scaffold.title
|
337
|
+
|
338
|
+
|
339
|
+
You can set and get the title of the pages.
|
340
|
+
|
341
|
+
|
342
|
+
```erb
|
343
|
+
# app/views/your_resources/list.html.erb
|
344
|
+
<%= dynamic_scaffold.title.current.name %>
|
345
|
+
<!-- Shop -->
|
346
|
+
|
347
|
+
<%= dynamic_scaffold.title.current.action %>
|
348
|
+
<!-- List -->
|
349
|
+
|
350
|
+
<%= dynamic_scaffold.title.current.full %>
|
351
|
+
<!-- Shop List -->
|
352
|
+
```
|
353
|
+
|
354
|
+
You can get another action title through the action name method too.
|
355
|
+
|
356
|
+
```erb
|
357
|
+
# app/views/your_resources/list.html.erb
|
358
|
+
<%= dynamic_scaffold.title.new.full %>
|
359
|
+
<!-- Create Shop -->
|
360
|
+
```
|
361
|
+
|
362
|
+
If you want change from the model name, set `config.title.name`.
|
363
|
+
|
364
|
+
```rb
|
365
|
+
# app/controllers/shops_controller.rb
|
366
|
+
class ShopController < ApplicationController
|
367
|
+
include DynamicScaffold::Controller
|
368
|
+
dynamic_scaffold Shop do |config|
|
369
|
+
config.title.name = 'Model'
|
370
|
+
...
|
371
|
+
```
|
372
|
+
|
373
|
+
If you want to dynamically set according to url parameters, you can also use block.
|
374
|
+
|
375
|
+
```rb
|
376
|
+
# app/controllers/shops_controller.rb
|
377
|
+
class ShopController < ApplicationController
|
378
|
+
include DynamicScaffold::Controller
|
379
|
+
dynamic_scaffold Shop do |config|
|
380
|
+
config.title.name do |params|
|
381
|
+
I18n.t "enum.user.role.#{params[role]}", default: params[role].titleize
|
382
|
+
end
|
383
|
+
```
|
384
|
+
|
385
|
+
#### dynamic_scaffold_path
|
386
|
+
|
387
|
+
You can get the path by specifying the action name. Below is an example of displaying breadcrumbs.
|
388
|
+
|
389
|
+
```erb
|
390
|
+
<ol class="breadcrumb">
|
391
|
+
<%= yield :breadcrumb_before %>
|
392
|
+
<% if params['action'] == 'index' %>
|
393
|
+
<li class="active"><%= dynamic_scaffold.title.current.name %></li>
|
394
|
+
<% else %>
|
395
|
+
<li><%= link_to dynamic_scaffold.title.index.name, dynamic_scaffold_path(:index) %></li>
|
396
|
+
<li class="active"><%= dynamic_scaffold.title.current.action %></li>
|
397
|
+
<% end %>
|
398
|
+
</ol>
|
399
|
+
```
|
400
|
+
|
401
|
+
#### dynamic_scaffold.vars
|
402
|
+
|
403
|
+
You can cache, such as data to be displayed multiple times in a view using `dynamic_scaffold.vars`.
|
404
|
+
|
405
|
+
```rb
|
406
|
+
# app/controllers/shops_controller.rb
|
407
|
+
class ShopController < ApplicationController
|
408
|
+
include DynamicScaffold::Controller
|
409
|
+
dynamic_scaffold Shop do |config|
|
410
|
+
config.title.vars :shop_type do
|
411
|
+
ShopType.find(params['shop_type_id'])
|
412
|
+
end
|
413
|
+
...
|
414
|
+
```
|
415
|
+
|
416
|
+
```rb
|
417
|
+
# in your view
|
418
|
+
<%= dynamic_scaffold.vars.shop_type.name %>
|
419
|
+
```
|
420
|
+
|
421
|
+
### Password Handling Tips
|
422
|
+
|
423
|
+
Passwords are not displayed on the editing screen and should be skipped validation when sent with empty.
|
424
|
+
|
425
|
+
You can do it by preparing virtual attributes for the edit action, and switching between edit and new action.
|
426
|
+
|
427
|
+
```rb
|
428
|
+
class User < ApplicationRecord
|
429
|
+
validates :password, presence: true
|
430
|
+
|
431
|
+
attr_reader :password_edit
|
432
|
+
|
433
|
+
def password_edit=(value)
|
434
|
+
@password_edit = value
|
435
|
+
self.password = value if value.present?
|
436
|
+
end
|
437
|
+
end
|
438
|
+
```
|
439
|
+
|
440
|
+
```rb
|
441
|
+
class UsersController < ScaffoldController
|
442
|
+
include DynamicScaffold::Controller
|
443
|
+
dynamic_scaffold User do |config|
|
444
|
+
|
445
|
+
# If the block given to the `if` method returns false, the element is ignored.
|
446
|
+
# The block argument is `params` in controller.
|
447
|
+
config.form.item(:password_field, :password)
|
448
|
+
.if {|p| %w[new create].include? p[:action] }
|
449
|
+
|
450
|
+
# When you call the `proxy` method, the element's error messages and label will be used for the specified attribute.
|
451
|
+
config.form.item(:password_field, :password_edit)
|
452
|
+
.proxy(:password)
|
453
|
+
.if {|p| %w[edit update].include? p[:action] }
|
454
|
+
end
|
455
|
+
end
|
456
|
+
```
|
457
|
+
|
458
|
+
|
459
|
+
## Contributing
|
460
|
+
|
461
|
+
* We use rspec for test.
|
462
|
+
* Check code with [rubocop](https://github.com/bbatsov/rubocop).
|
463
|
+
|
464
|
+
## License
|
465
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'DynamicScaffold'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path('../spec/dummy/Rakefile', __FILE__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
load 'rails/tasks/statistics.rake'
|
21
|
+
|
22
|
+
require 'bundler/gem_tasks'
|
23
|
+
|
24
|
+
require 'rake/testtask'
|
25
|
+
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
27
|
+
t.libs << 'test'
|
28
|
+
t.pattern = 'test/**/*_test.rb'
|
29
|
+
t.verbose = false
|
30
|
+
end
|
31
|
+
|
32
|
+
task default: :test
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M143 256.3L7 120.3c-9.4-9.4-9.4-24.6 0-33.9l22.6-22.6c9.4-9.4 24.6-9.4 33.9 0l96.4 96.4 96.4-96.4c9.4-9.4 24.6-9.4 33.9 0L313 86.3c9.4 9.4 9.4 24.6 0 33.9l-136 136c-9.4 9.5-24.6 9.5-34 .1zm34 192l136-136c9.4-9.4 9.4-24.6 0-33.9l-22.6-22.6c-9.4-9.4-24.6-9.4-33.9 0L160 352.1l-96.4-96.4c-9.4-9.4-24.6-9.4-33.9 0L7 278.3c-9.4 9.4-9.4 24.6 0 33.9l136 136c9.4 9.5 24.6 9.5 34 .1z"/></svg>
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M177 255.7l136 136c9.4 9.4 9.4 24.6 0 33.9l-22.6 22.6c-9.4 9.4-24.6 9.4-33.9 0L160 351.9l-96.4 96.4c-9.4 9.4-24.6 9.4-33.9 0L7 425.7c-9.4-9.4-9.4-24.6 0-33.9l136-136c9.4-9.5 24.6-9.5 34-.1zm-34-192L7 199.7c-9.4 9.4-9.4 24.6 0 33.9l22.6 22.6c9.4 9.4 24.6 9.4 33.9 0l96.4-96.4 96.4 96.4c9.4 9.4 24.6 9.4 33.9 0l22.6-22.6c9.4-9.4 9.4-24.6 0-33.9l-136-136c-9.2-9.4-24.4-9.4-33.8 0z"/></svg>
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M207.029 381.476L12.686 187.132c-9.373-9.373-9.373-24.569 0-33.941l22.667-22.667c9.357-9.357 24.522-9.375 33.901-.04L224 284.505l154.745-154.021c9.379-9.335 24.544-9.317 33.901.04l22.667 22.667c9.373 9.373 9.373 24.569 0 33.941L240.971 381.476c-9.373 9.372-24.569 9.372-33.942 0z"/></svg>
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M34.52 239.03L228.87 44.69c9.37-9.37 24.57-9.37 33.94 0l22.67 22.67c9.36 9.36 9.37 24.52.04 33.9L131.49 256l154.02 154.75c9.34 9.38 9.32 24.54-.04 33.9l-22.67 22.67c-9.37 9.37-24.57 9.37-33.94 0L34.52 272.97c-9.37-9.37-9.37-24.57 0-33.94z"/></svg>
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg>
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M240.971 130.524l194.343 194.343c9.373 9.373 9.373 24.569 0 33.941l-22.667 22.667c-9.357 9.357-24.522 9.375-33.901.04L224 227.495 69.255 381.516c-9.379 9.335-24.544 9.317-33.901-.04l-22.667-22.667c-9.373-9.373-9.373-24.569 0-33.941L207.03 130.525c9.372-9.373 24.568-9.373 33.941-.001z"/></svg>
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"/></svg>
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M567.403 235.642L462.323 84.589A48 48 0 0 0 422.919 64H153.081a48 48 0 0 0-39.404 20.589L8.597 235.642A48.001 48.001 0 0 0 0 263.054V400c0 26.51 21.49 48 48 48h480c26.51 0 48-21.49 48-48V263.054c0-9.801-3-19.366-8.597-27.412zM153.081 112h269.838l77.913 112H75.168l77.913-112zM528 400H48V272h480v128zm-32-64c0 17.673-14.327 32-32 32s-32-14.327-32-32 14.327-32 32-32 32 14.327 32 32zm-96 0c0 17.673-14.327 32-32 32s-32-14.327-32-32 14.327-32 32-32 32 14.327 32 32z"/></svg>
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"/></svg>
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M448 294.2v-76.4c0-13.3-10.7-24-24-24H286.2V56c0-13.3-10.7-24-24-24h-76.4c-13.3 0-24 10.7-24 24v137.8H24c-13.3 0-24 10.7-24 24v76.4c0 13.3 10.7 24 24 24h137.8V456c0 13.3 10.7 24 24 24h76.4c13.3 0 24-10.7 24-24V318.2H424c13.3 0 24-10.7 24-24z"/></svg>
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M64 468V44c0-6.6 5.4-12 12-12h48c6.6 0 12 5.4 12 12v176.4l195.5-181C352.1 22.3 384 36.6 384 64v384c0 27.4-31.9 41.7-52.5 24.6L136 292.7V468c0 6.6-5.4 12-12 12H76c-6.6 0-12-5.4-12-12z"/></svg>
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M384 44v424c0 6.6-5.4 12-12 12h-48c-6.6 0-12-5.4-12-12V291.6l-195.5 181C95.9 489.7 64 475.4 64 448V64c0-27.4 31.9-41.7 52.5-24.6L312 219.3V44c0-6.6 5.4-12 12-12h48c6.6 0 12 5.4 12 12z"/></svg>
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path d="M323.1 441l53.9-53.9c9.4-9.4 9.4-24.5 0-33.9L279.8 256l97.2-97.2c9.4-9.4 9.4-24.5 0-33.9L323.1 71c-9.4-9.4-24.5-9.4-33.9 0L192 168.2 94.8 71c-9.4-9.4-24.5-9.4-33.9 0L7 124.9c-9.4 9.4-9.4 24.5 0 33.9l97.2 97.2L7 353.2c-9.4 9.4-9.4 24.5 0 33.9L60.9 441c9.4 9.4 24.5 9.4 33.9 0l97.2-97.2 97.2 97.2c9.3 9.3 24.5 9.3 33.9 0z"/></svg>
|