dynamic_scaffold 0.8.5 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ee8bcbe45496d6f41503b4e9ea97197176366b5c57c359be10f48972184df97d
4
- data.tar.gz: 678ba1879ca352131a1c4320e1d9139e8463b8bd25d316222d8e507490d0ae0e
3
+ metadata.gz: 0b9f66a15ba06068661f6bfe62b02db517fbab32f368036939704b54b2ceec8e
4
+ data.tar.gz: f9263e830b2d891eef486565407e89106d0c4afec3d07e6781a6f0b7bf4bd63a
5
5
  SHA512:
6
- metadata.gz: 76e6c4845be245930504f2322121cf03351a79a96b03a4a07526afa0164dd8c4531bd1b0aa3506b664a470c78f4e32d4b521186e1b91c0ff7e047cec12e6dd18
7
- data.tar.gz: d93e3fff877d7facf41b1bfa9f835ba2ce85523d35963df34a537a90ad5f387ed40f113f675ba23e5ab7108ced59373b7ec0c74c3b6fc6f59f42d4062fdf97fb
6
+ metadata.gz: 942fcfb0203d16dc3f549d313eff8fd0e1c0b925155ea33ae1c021c2df16e9f302ada3630e8ba87c1a7a4e5e0b1631edeb812d66d3046f7405426ada1ace2c23
7
+ data.tar.gz: 808f74e475722ae05ae0515a7cdf3b53049adc520cd97cca8bf9f2a8be7eda2c4e63423d93d0b88f7ba5d227089e894d6126192f1afebfb383ad0ba8f808b91d
data/README.md CHANGED
@@ -8,6 +8,7 @@ The Scaffold system which dynamically generates CRUD and sort functions.
8
8
  * Support sort and pagination.
9
9
  * Support image upload with preview.
10
10
  * Support image crop.
11
+ * Support [globalize](https://github.com/globalize/globalize) form fields.
11
12
  * This has the views with the Twitter Bootstrap. Support bootstrap3/4.
12
13
  * Customizable and flexible.
13
14
 
@@ -235,19 +236,6 @@ class ShopController < ApplicationController
235
236
  config.form.item(:collection_check_boxes, :state_ids, State.all, :id, :name)
236
237
  config.form.item(:collection_radio_buttons, :status, Shop.statuses.map{|k, _v| [k, k.titleize]}, :first, :last)
237
238
 
238
- # You can add an image uploader with preview to the form. The save and remove part to the model corresponds to [carrierwave](https://github.com/carrierwaveuploader/carrierwave).
239
- # In the example below, you need to mount the carrierwave uploader on the thumb column of the model.
240
- #
241
- # class Shop < ApplicationRecord
242
- # mount_uploader :thumb, ShopThumbUploader
243
- #
244
- config.form.item(
245
- :carrierwave_image,
246
- :thumb,
247
- preview_max_size: {width: '300px', height: '300px'},
248
- removable: false # If you want to require image, please set removable to false. the default is true.
249
- )
250
-
251
239
  # If you want to display more free form field, use block.
252
240
  # The block is executed in the context of view, so you can call the method of view.
253
241
  config.form.item :block, :free do |form, field|
@@ -292,7 +280,54 @@ class ShopController < ApplicationController
292
280
  end
293
281
  ```
294
282
 
295
- `carrierwave_image` supports [cropper](https://github.com/fengyuanchen/cropperjs). For details, please read [Crop the image](https://github.com/gomo/dynamic_scaffold/wiki/Crop-the-image).
283
+ ##### carrierwave_image
284
+
285
+ You can add an image uploader with preview to the form. It uses [carrierwave](https://github.com/carrierwaveuploader/carrierwave) to save images and associate with records.
286
+
287
+ For example, you mount the carrierwave uploader on the `thumb` column of Shop model.
288
+
289
+ ```rb
290
+ class Shop < ApplicationRecord
291
+ mount_uploader :thumb, ShopThumbUploader
292
+ ```
293
+
294
+ The controller code is as follows.
295
+
296
+ ```rb
297
+ class ShopController < ApplicationController
298
+ include DynamicScaffold::Controller
299
+ dynamic_scaffold Shop do |config|
300
+ ...
301
+ config.form.item(
302
+ :carrierwave_image,
303
+ :thumb,
304
+ preview_max_size: {width: '300px', height: '300px'},
305
+ removable: false # If you want to require image, please set removable to false. the default is true.
306
+ )
307
+ ```
308
+
309
+ The `carrierwave_image` supports [cropper](https://github.com/fengyuanchen/cropperjs) too. For details, please read [Crop the image](https://github.com/gomo/dynamic_scaffold/wiki/Crop-the-image).
310
+
311
+
312
+ ##### globalize_fields
313
+
314
+ We support [globalize](https://github.com/globalize/globalize). Below is the controller code.
315
+
316
+ ```rb
317
+ class ShopController < ApplicationController
318
+ include DynamicScaffold::Controller
319
+ dynamic_scaffold Shop do |config|
320
+ ...
321
+ c.form
322
+ # Each language input field specified in the second argument will generate.
323
+ .item(:globalize_fields, { en: 'English', ja: 'Japanese' }, style: 'width: 78px;')
324
+ # You can specify the type of element to generate to `for` method. it support `:text_field` or `:text_area` for type.
325
+ # Specify the attribute name in the second argument of the `for` method.
326
+ .for(:text_field, :keyword)
327
+ ```
328
+
329
+ Setting the model for globalize_fields with validates is [here](https://github.com/gomo/dynamic_scaffold/wiki/Model-setting-for-globalize).
330
+
296
331
 
297
332
  ### Sorting
298
333
 
@@ -411,6 +446,17 @@ class UsersController < ApplicationController
411
446
  ...
412
447
  ```
413
448
 
449
+ By default, the value can not update to a value other than the value specified in the scope( or parameter). This behavior can change with `changeable` option.
450
+
451
+ ```rb
452
+ # app/controllers/users_controller.rb
453
+ class UsersController < ApplicationController
454
+ include DynamicScaffold::Controller
455
+ dynamic_scaffold User do |c|
456
+ c.scope([:role], changeable: true)
457
+ ...
458
+ ```
459
+
414
460
  #### Limit count
415
461
 
416
462
  You can specify the maximum count of registrations.
@@ -132,4 +132,36 @@
132
132
  // Fixed a problem that font-awesome icon and text link do not match in height.
133
133
  .page-link{
134
134
  line-height: 1.6;
135
+ }
136
+
137
+
138
+ .ds-globalize-group{
139
+ margin-bottom: 7px;
140
+ display: flex;
141
+ .ds-globalize-lang{
142
+ display: flex;
143
+ font-size: 12px;
144
+ color: #495057;
145
+ text-align: center;
146
+ white-space: nowrap;
147
+ background-color: #e9ecef;
148
+ border: 1px solid #ced4da;
149
+ border-radius: .25rem;
150
+ border-top-right-radius: 0;
151
+ border-bottom-right-radius: 0;
152
+ border-right: none;
153
+ justify-content: center;
154
+ align-items: center;
155
+ }
156
+
157
+ &.has-error{
158
+ .ds-globalize-lang{
159
+ border-color: #a94442;
160
+ }
161
+ }
162
+
163
+ .form-control{
164
+ border-top-left-radius: 0;
165
+ border-bottom-left-radius: 0;
166
+ }
135
167
  }
@@ -0,0 +1,14 @@
1
+ module DynamicScaffoldHelper
2
+ def render_form_errors(errors)
3
+ return '' if errors.blank?
4
+ tag.ul(class: 'list-unstyled ds-error-message') do
5
+ errors.each do |message|
6
+ concat tag.li("#{dynamic_scaffold_icon :error} #{message}".html_safe) # rubocop:disable Rails/OutputSafety
7
+ end
8
+ end
9
+ end
10
+
11
+ def dynamic_scaffold_icon(name)
12
+ instance_exec name, &::Rails.application.config.dynamic_scaffold.icons
13
+ end
14
+ end
@@ -56,6 +56,19 @@
56
56
  <%end%>
57
57
  <%= form.hidden_field "#{elem.name}_cache" %>
58
58
  </div>
59
+ <% elsif elem.type? :globalize_fields %>
60
+ <% elem.locales.each do |locale, name| %>
61
+ <%- locale_errors = elem.locale_errors(locale, @record) -%>
62
+ <%= form.globalize_fields_for(locale) do |gform|%>
63
+ <div class="<%= class_names('ds-globalize-group', 'has-error': locale_errors.present?) %>">
64
+ <%= tag.span(elem.lang_attributes('ds-globalize-lang')) do%>
65
+ <%= name %>
66
+ <%end%>
67
+ <%= elem.render(self, gform, class_names('form-control', {'is-invalid': locale_errors.present?})) %>
68
+ </div>
69
+ <%= render_form_errors(locale_errors) -%>
70
+ <%end%>
71
+ <% end %>
59
72
  <% else %>
60
73
  <%= elem.render(self, form, class_names('form-control', {'is-invalid': errors.present?})) %>
61
74
  <% end %>
@@ -63,13 +76,7 @@
63
76
  <%= self.instance_exec(@record, &block) %>
64
77
  <%-end-%>
65
78
  </div>
66
- <%- if errors.present? -%>
67
- <ul class="list-unstyled ds-error-message">
68
- <% errors.each do |err|%>
69
- <li><%= dynamic_scaffold_icon :error %> <%= err %></li>
70
- <%end%>
71
- </ul>
72
- <%- end -%>
79
+ <%= render_form_errors(errors) -%>
73
80
  <%if elem.notes?%>
74
81
  <div class="form-text text-muted"><%= elem.render_notes(form.object, self) %></div>
75
82
  <%end%>
@@ -119,7 +119,16 @@ module DynamicScaffold
119
119
  end
120
120
 
121
121
  class Config
122
- attr_reader :model, :form, :list, :title, :controller, :lock_before_count, :max_count_options
122
+ attr_reader(
123
+ :model,
124
+ :form,
125
+ :list,
126
+ :title,
127
+ :controller,
128
+ :lock_before_count,
129
+ :max_count_options,
130
+ :scope_options
131
+ )
123
132
  def initialize(model, controller)
124
133
  @model = model
125
134
  @controller = controller
@@ -139,8 +148,11 @@ module DynamicScaffold
139
148
  end
140
149
  end
141
150
 
142
- def scope(scopes = nil)
143
- @scope = scopes unless scopes.nil?
151
+ def scope(*args)
152
+ if args.present?
153
+ @scope_options = args.extract_options!
154
+ @scope = args[0]
155
+ end
144
156
  @scope
145
157
  end
146
158
 
@@ -274,40 +286,8 @@ module DynamicScaffold
274
286
  end
275
287
  end
276
288
 
277
- def item(type, *args, &block) # rubocop:disable Metrics/MethodLength
278
- case type
279
- when
280
- :check_box,
281
- :radio_button,
282
- :text_area,
283
- :text_field,
284
- :password_field,
285
- :hidden_field,
286
- :file_field,
287
- :color_field,
288
- :number_field,
289
- :telephone_field then
290
- item = Form::Item::SingleOption.new(@config, type, *args)
291
- when
292
- :time_select,
293
- :date_select,
294
- :datetime_select,
295
- :collection_select,
296
- :grouped_collection_select then
297
- item = Form::Item::TwoOptions.new(@config, type, *args)
298
- when
299
- :collection_check_boxes,
300
- :collection_radio_buttons then
301
- item = Form::Item::TwoOptionsWithBlock.new(@config, type, *args)
302
- when
303
- :block then
304
- item = Form::Item::Block.new(@config, type, *args, block)
305
- when
306
- :carrierwave_image then
307
- item = Form::Item::CarrierWaveImage.new(@config, type, *args)
308
- else
309
- raise DynamicScaffold::Error::InvalidParameter, "Unknown form item type #{type}"
310
- end
289
+ def item(type, *args, &block)
290
+ item = Form::Item::Base.create(@config, type, *args, &block)
311
291
  @items << item
312
292
  item
313
293
  end
@@ -4,7 +4,8 @@ module DynamicScaffold
4
4
  include ControllerUtilities
5
5
 
6
6
  included do
7
- helper_method :dynamic_scaffold_path, :dynamic_scaffold_icon, :dynamic_scaffold, :primary_key_value, :request_queries
7
+ helper_method :dynamic_scaffold_path, :dynamic_scaffold, :request_queries
8
+ helper DynamicScaffoldHelper
8
9
  attr_reader :dynamic_scaffold
9
10
  before_action lambda {
10
11
  @dynamic_scaffold = Config.new(self.class.dynamic_scaffold_model, self)
@@ -42,10 +42,14 @@ module DynamicScaffold
42
42
  # Get paramters for update record.
43
43
  def update_values # rubocop:disable Metrics/AbcSize
44
44
  # set the parameters of carrierwave_image at the end for validates.
45
- permitting = dynamic_scaffold.form.items.map {|f| f.strong_parameter unless f.type?(:carrierwave_image) }.compact
45
+ permitting = []
46
+ dynamic_scaffold.form.items.reject {|i| i.type?(:carrierwave_image) }.each do |item|
47
+ item.extract_parameters(permitting)
48
+ end
46
49
  permitting.concat(dynamic_scaffold.form.permit_params)
47
- permitting.concat(dynamic_scaffold.form.items.map {|f| f.strong_parameter if f.type?(:carrierwave_image) }.compact)
48
- permitting.flatten!
50
+ dynamic_scaffold.form.items.select {|i| i.type?(:carrierwave_image) }.each do |item|
51
+ item.extract_parameters(permitting)
52
+ end
49
53
 
50
54
  values = params
51
55
  .require(dynamic_scaffold.model.name.underscore)
@@ -60,6 +64,7 @@ module DynamicScaffold
60
64
 
61
65
  # Check if there are inconsistent scopes in update parameters
62
66
  def valid_for_scope?(update_params)
67
+ return true if dynamic_scaffold.scope_options[:changeable]
63
68
  result = true
64
69
  scope_params.each do |key, value|
65
70
  if update_params.key?(key) && update_params[key] != value
@@ -110,14 +115,6 @@ module DynamicScaffold
110
115
  public_send("#{route.name}_path", options)
111
116
  end
112
117
 
113
- def dynamic_scaffold_icon(name)
114
- view_context.instance_exec name, &::Rails.application.config.dynamic_scaffold.icons
115
- end
116
-
117
- def primary_key_value(record)
118
- [*record.class.primary_key].each_with_object({}) {|col, res| res[col] = record[col] }
119
- end
120
-
121
118
  def bind_sorter_value(record)
122
119
  attr = dynamic_scaffold.list.sorter_attribute
123
120
  value = dynamic_scaffold.model.maximum(attr)
@@ -1,7 +1,52 @@
1
1
  module DynamicScaffold
2
2
  module Form
3
3
  module Item
4
- class Base
4
+ class Base # rubocop:disable Metrics/ClassLength
5
+ ITEM_TYPES = {
6
+ check_box: Form::Item::SingleOption,
7
+ radio_button: Form::Item::SingleOption,
8
+ text_area: Form::Item::SingleOption,
9
+ text_field: Form::Item::SingleOption,
10
+ password_field: Form::Item::SingleOption,
11
+ hidden_field: Form::Item::SingleOption,
12
+ file_field: Form::Item::SingleOption,
13
+ color_field: Form::Item::SingleOption,
14
+ number_field: Form::Item::SingleOption,
15
+ telephone_field: Form::Item::SingleOption,
16
+
17
+ time_select: Form::Item::TwoOptions,
18
+ date_select: Form::Item::TwoOptions,
19
+ datetime_select: Form::Item::TwoOptions,
20
+ collection_select: Form::Item::TwoOptions,
21
+ grouped_collection_select: Form::Item::TwoOptions,
22
+
23
+ collection_check_boxes: Form::Item::TwoOptionsWithBlock,
24
+ collection_radio_buttons: Form::Item::TwoOptionsWithBlock,
25
+
26
+ block: Form::Item::Block,
27
+
28
+ carrierwave_image: Form::Item::CarrierWaveImage,
29
+
30
+ globalize_fields: Form::Item::GlobalizeFields
31
+ }.freeze
32
+
33
+ class << self
34
+ def create(config, type, *args, &block)
35
+ if ITEM_TYPES[type].nil?
36
+ raise(
37
+ DynamicScaffold::Error::InvalidParameter,
38
+ "Unknown form item type #{type}. supported: #{ITEM_TYPES.keys.join(', ')}"
39
+ )
40
+ end
41
+
42
+ if ITEM_TYPES[type] == Form::Item::Block
43
+ ITEM_TYPES[type].new(config, type, *args, block)
44
+ else
45
+ ITEM_TYPES[type].new(config, type, *args)
46
+ end
47
+ end
48
+ end
49
+
5
50
  attr_reader :name
6
51
  def initialize(config, type, name, html_attributes = {})
7
52
  @config = config
@@ -54,9 +99,12 @@ module DynamicScaffold
54
99
  end
55
100
  end
56
101
 
57
- def strong_parameter
58
- return { @name => [] } if @multiple
59
- @name
102
+ def extract_parameters(permitting)
103
+ if @multiple
104
+ permitting << { @name => [] }
105
+ else
106
+ permitting << @name
107
+ end
60
108
  end
61
109
 
62
110
  def if(&block)
@@ -30,13 +30,11 @@ module DynamicScaffold
30
30
  yield(html_attributes)
31
31
  end
32
32
 
33
- def strong_parameter
34
- params = []
33
+ def extract_parameters(permitting)
35
34
  # If you do not permit before the image body you can not use cropper value in uploader.
36
- params << "cropper_#{@name}" unless cropper.nil?
37
- params << "remove_#{@name}" if @options[:removable]
38
- params.concat(["#{@name}_cache", @name])
39
- params
35
+ permitting << "cropper_#{@name}" unless cropper.nil?
36
+ permitting << "remove_#{@name}" if @options[:removable]
37
+ permitting.concat(["#{@name}_cache", @name])
40
38
  end
41
39
  end
42
40
  end
@@ -0,0 +1,40 @@
1
+ module DynamicScaffold
2
+ module Form
3
+ module Item
4
+ class GlobalizeFields < Base
5
+ attr_reader :locales
6
+ delegate :proxy_field, :notes?, :render_notes, :render, to: :@item
7
+
8
+ def initialize(config, type, locales, options = {})
9
+ super(config, type, :translations_attributes, options)
10
+ @locales = locales
11
+ end
12
+
13
+ def for(type, *args, &block)
14
+ @item = Form::Item::Base.create(@config, type, *args, &block)
15
+ end
16
+
17
+ def strong_parameter
18
+ { translations_attributes: [:id, :locale, @item.name] }
19
+ end
20
+
21
+ def extract_parameters(permitting)
22
+ trans = permitting.find {|item| item.is_a?(Hash) && item.key?(:translations_attributes) }
23
+ if trans.nil?
24
+ permitting << { translations_attributes: [:id, :locale, @item.name] }
25
+ else
26
+ trans[:translations_attributes] << @item.name
27
+ end
28
+ end
29
+
30
+ def lang_attributes(classnames = nil)
31
+ build_html_attributes(classnames)
32
+ end
33
+
34
+ def locale_errors(locale, record)
35
+ record.errors.full_messages_for("#{@item.proxy_field.name}_#{locale}")
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,64 @@
1
+ module ActionView
2
+ module Helpers
3
+ class FormBuilder
4
+ #
5
+ # Helper that renders translations fields
6
+ # on a per-locale basis, so you can use them separately
7
+ # in the same form and still saving them all at once
8
+ # in the same request.
9
+ #
10
+ # Use it like this:
11
+ #
12
+ # <h1>Editing post</h1>
13
+ #
14
+ # <% form_for(@post) do |f| %>
15
+ # <%= f.error_messages %>
16
+ #
17
+ # <h2>English (default locale)</h2>
18
+ # <p><%= f.text_field :title %></p>
19
+ # <p><%= f.text_field :teaser %></p>
20
+ # <p><%= f.text_field :body %></p>
21
+ #
22
+ # <hr/>
23
+ #
24
+ # <h2>Spanish translation</h2>
25
+ # <% f.globalize_fields_for :es do |g| %>
26
+ # <p><%= g.text_field :title %></p>
27
+ # <p><%= g.text_field :teaser %></p>
28
+ # <p><%= g.text_field :body %></p>
29
+ # <% end %>
30
+ #
31
+ # <hr/>
32
+ #
33
+ # <h2>French translation</h2>
34
+ # <% f.globalize_fields_for :fr do |g| %>
35
+ # <p><%= g.text_field :title %></p>
36
+ # <p><%= g.text_field :teaser %></p>
37
+ # <p><%= g.text_field :body %></p>
38
+ # <% end %>
39
+ #
40
+ # <% end %>
41
+ #
42
+ def globalize_fields_for(locale, *args, &proc)
43
+ raise ArgumentError, 'Missing block' unless block_given?
44
+ @locales ||= []
45
+
46
+ first = false
47
+ unless @locales.include?(locale)
48
+ @locales << locale
49
+ first = true
50
+ end
51
+ object_name = "#{@object_name}[translations_attributes][#{@locales.index(locale) + 1}]"
52
+ object = @object.translations.find_by locale: locale.to_s
53
+
54
+ # The following tags are added only once for the first time.
55
+ if first
56
+ @template.concat @template.hidden_field_tag("#{object_name}[id]", object ? object.id : '')
57
+ @template.concat @template.hidden_field_tag("#{object_name}[locale]", locale)
58
+ end
59
+
60
+ @template.fields_for(object_name, object, *args, &proc)
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,3 +1,3 @@
1
1
  module DynamicScaffold
2
- VERSION = '0.8.5'.freeze
2
+ VERSION = '0.9.0'.freeze
3
3
  end
@@ -4,6 +4,7 @@ require 'dynamic_scaffold/routes'
4
4
  require 'dynamic_scaffold/controller_utilities'
5
5
  require 'dynamic_scaffold/controller'
6
6
  require 'dynamic_scaffold/config'
7
+ require 'dynamic_scaffold/form_builder'
7
8
 
8
9
  module DynamicScaffold
9
10
  module Error
@@ -25,6 +26,7 @@ module DynamicScaffold
25
26
  autoload :SingleOption, 'dynamic_scaffold/form/item/single_option'
26
27
  autoload :TwoOptionsWithBlock, 'dynamic_scaffold/form/item/two_options_with_block'
27
28
  autoload :TwoOptions, 'dynamic_scaffold/form/item/two_options'
29
+ autoload :GlobalizeFields, 'dynamic_scaffold/form/item/globalize_fields'
28
30
  end
29
31
  end
30
32
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dynamic_scaffold
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.5
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masamoto Miyata
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-31 00:00:00.000000000 Z
11
+ date: 2018-08-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: classnames-rails-view
@@ -233,6 +233,7 @@ files:
233
233
  - app/assets/stylesheets/dynamic_scaffold/bootstrap4.scss
234
234
  - app/assets/stylesheets/dynamic_scaffold/common.scss
235
235
  - app/assets/stylesheets/dynamic_scaffold/resplist.scss
236
+ - app/helpers/dynamic_scaffold_helper.rb
236
237
  - app/views/dynamic_scaffold/bootstrap/_edit.html.erb
237
238
  - app/views/dynamic_scaffold/bootstrap/_form.html.erb
238
239
  - app/views/dynamic_scaffold/bootstrap/_list.html.erb
@@ -261,9 +262,11 @@ files:
261
262
  - lib/dynamic_scaffold/form/item/base.rb
262
263
  - lib/dynamic_scaffold/form/item/block.rb
263
264
  - lib/dynamic_scaffold/form/item/carrier_wave_image.rb
265
+ - lib/dynamic_scaffold/form/item/globalize_fields.rb
264
266
  - lib/dynamic_scaffold/form/item/single_option.rb
265
267
  - lib/dynamic_scaffold/form/item/two_options.rb
266
268
  - lib/dynamic_scaffold/form/item/two_options_with_block.rb
269
+ - lib/dynamic_scaffold/form_builder.rb
267
270
  - lib/dynamic_scaffold/icons/fontawesome.rb
268
271
  - lib/dynamic_scaffold/list/item.rb
269
272
  - lib/dynamic_scaffold/routes.rb