administrate 0.18.0 → 0.20.1
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/app/assets/javascripts/administrate/components/select.js +3 -0
- data/app/assets/stylesheets/administrate/components/_field-unit.scss +7 -0
- data/app/controllers/administrate/application_controller.rb +7 -4
- data/app/controllers/concerns/administrate/punditize.rb +43 -21
- data/app/views/administrate/application/_collection.html.erb +2 -3
- data/app/views/administrate/application/_form.html.erb +19 -4
- data/app/views/administrate/application/_index_header.html.erb +1 -1
- data/app/views/administrate/application/_navigation.html.erb +1 -1
- data/app/views/administrate/application/_pagination.html.erb +1 -1
- data/app/views/administrate/application/edit.html.erb +1 -1
- data/app/views/administrate/application/new.html.erb +1 -1
- data/app/views/administrate/application/show.html.erb +19 -11
- data/app/views/fields/has_many/_show.html.erb +2 -1
- data/app/views/fields/has_one/_form.html.erb +14 -4
- data/app/views/fields/has_one/_show.html.erb +18 -12
- data/app/views/fields/select/_form.html.erb +5 -18
- data/app/views/layouts/administrate/application.html.erb +1 -1
- data/config/locales/administrate.ja.yml +5 -5
- data/docs/authorization.md +18 -8
- data/docs/customizing_controller_actions.md +14 -0
- data/docs/customizing_dashboards.md +77 -14
- data/docs/customizing_page_views.md +1 -1
- data/docs/getting_started.md +1 -1
- data/docs/guides/customising_search.md +1 -1
- data/lib/administrate/base_dashboard.rb +26 -4
- data/lib/administrate/field/associative.rb +11 -1
- data/lib/administrate/field/belongs_to.rb +5 -2
- data/lib/administrate/field/deferred.rb +1 -1
- data/lib/administrate/field/has_many.rb +20 -6
- data/lib/administrate/field/number.rb +2 -8
- data/lib/administrate/field/polymorphic.rb +2 -1
- data/lib/administrate/field/select.rb +19 -9
- data/lib/administrate/not_authorized_error.rb +3 -1
- data/lib/administrate/order.rb +49 -23
- data/lib/administrate/page/collection.rb +1 -0
- data/lib/administrate/page/form.rb +9 -8
- data/lib/administrate/page/show.rb +10 -2
- data/lib/administrate/resource_resolver.rb +2 -1
- data/lib/administrate/search.rb +1 -1
- data/lib/administrate/version.rb +1 -1
- data/lib/administrate/view_generator.rb +6 -1
- data/lib/administrate.rb +9 -4
- data/lib/generators/administrate/dashboard/dashboard_generator.rb +6 -1
- data/lib/generators/administrate/dashboard/templates/controller.rb.erb +2 -2
- data/lib/generators/administrate/install/install_generator.rb +6 -1
- data/lib/generators/administrate/routes/routes_generator.rb +11 -2
- data/lib/generators/administrate/test_record.rb +21 -0
- metadata +37 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8e5544a7c600e80f4f0059f7b4aea8903e46d926b06dea598660baa758ed67ec
|
4
|
+
data.tar.gz: b4aefefcdb03dc10c0570e8d6b1a15629c4a3cee9f5ceb46d306e2b3a57e2454
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 18ac7ba09f2f7e36d5c86d492fda86cf2f31239146bcac7dacd47eb124fc793e9c425f1646cdcdcce8a672b1666322b6178cf5a602bc358d794e315050f94d02
|
7
|
+
data.tar.gz: 183d4aafdeeef34031acf4f0fbd29401d39ad368a2b889d509d36560dfcd2b222043ddde8504fddfddcf505017467e6eec74848c422b960233b3492e9198e06d
|
@@ -2,6 +2,7 @@
|
|
2
2
|
@include administrate-clearfix;
|
3
3
|
align-items: center;
|
4
4
|
display: flex;
|
5
|
+
flex-wrap: wrap;
|
5
6
|
margin-bottom: $base-spacing;
|
6
7
|
position: relative;
|
7
8
|
width: 100%;
|
@@ -25,6 +26,12 @@
|
|
25
26
|
}
|
26
27
|
}
|
27
28
|
|
29
|
+
.field-unit__hint {
|
30
|
+
font-size: 90%;
|
31
|
+
margin-left: calc(15% + 2rem);
|
32
|
+
width: 100%;
|
33
|
+
}
|
34
|
+
|
28
35
|
.field-unit--nested {
|
29
36
|
border: $base-border;
|
30
37
|
margin-left: 7.5%;
|
@@ -40,10 +40,11 @@ module Administrate
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def create
|
43
|
-
resource =
|
43
|
+
resource = new_resource(resource_params)
|
44
44
|
authorize_resource(resource)
|
45
45
|
|
46
46
|
if resource.save
|
47
|
+
yield(resource) if block_given?
|
47
48
|
redirect_to(
|
48
49
|
after_resource_created_path(resource),
|
49
50
|
notice: translate_with_resource("create.success"),
|
@@ -201,7 +202,7 @@ module Administrate
|
|
201
202
|
|
202
203
|
def resource_params
|
203
204
|
params.require(resource_class.model_name.param_key).
|
204
|
-
permit(dashboard.permitted_attributes).
|
205
|
+
permit(dashboard.permitted_attributes(action_name)).
|
205
206
|
transform_values { |v| read_param_value(v) }
|
206
207
|
end
|
207
208
|
|
@@ -214,6 +215,8 @@ module Administrate
|
|
214
215
|
end
|
215
216
|
elsif data.is_a?(ActionController::Parameters)
|
216
217
|
data.transform_values { |v| read_param_value(v) }
|
218
|
+
elsif data.is_a?(String) && data.blank?
|
219
|
+
nil
|
217
220
|
else
|
218
221
|
data
|
219
222
|
end
|
@@ -265,8 +268,8 @@ module Administrate
|
|
265
268
|
end
|
266
269
|
helper_method :show_action?
|
267
270
|
|
268
|
-
def new_resource
|
269
|
-
resource_class.new
|
271
|
+
def new_resource(params = {})
|
272
|
+
resource_class.new(params)
|
270
273
|
end
|
271
274
|
helper_method :new_resource
|
272
275
|
|
@@ -2,37 +2,59 @@ module Administrate
|
|
2
2
|
module Punditize
|
3
3
|
if Object.const_defined?("Pundit")
|
4
4
|
extend ActiveSupport::Concern
|
5
|
-
include Pundit::Authorization
|
6
5
|
|
7
|
-
|
8
|
-
|
6
|
+
if Pundit.const_defined?(:Authorization)
|
7
|
+
include Pundit::Authorization
|
8
|
+
else
|
9
|
+
include Pundit
|
10
|
+
end
|
9
11
|
|
10
|
-
|
11
|
-
policy_scope_admin super
|
12
|
-
end
|
12
|
+
private
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
def policy_namespace
|
15
|
+
[]
|
16
|
+
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
def scoped_resource
|
19
|
+
namespaced_scope = policy_namespace + [super]
|
20
|
+
policy_scope!(pundit_user, namespaced_scope)
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
def authorize_resource(resource)
|
24
|
+
namespaced_resource = policy_namespace + [resource]
|
25
|
+
authorize namespaced_resource
|
26
|
+
end
|
24
27
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
def authorized_action?(resource, action)
|
29
|
+
namespaced_resource = policy_namespace + [resource]
|
30
|
+
policy = Pundit.policy!(pundit_user, namespaced_resource)
|
31
|
+
policy.send("#{action}?".to_sym)
|
32
|
+
end
|
33
|
+
|
34
|
+
def policy_scope!(user, scope)
|
35
|
+
policy_scope_class = Pundit::PolicyFinder.new(scope).scope!
|
36
|
+
|
37
|
+
begin
|
38
|
+
policy_scope = policy_scope_class.new(user, pundit_model(scope))
|
39
|
+
rescue ArgumentError
|
40
|
+
raise(Pundit::InvalidConstructorError,
|
41
|
+
"Invalid #<#{policy_scope_class}> constructor is called")
|
42
|
+
end
|
43
|
+
|
44
|
+
if policy_scope.respond_to? :resolve_admin
|
45
|
+
Administrate.deprecator.warn(
|
46
|
+
"Pundit policy scope `resolve_admin` method is deprecated. " +
|
47
|
+
"Please use a namespaced pundit policy instead.",
|
48
|
+
)
|
49
|
+
policy_scope.resolve_admin
|
32
50
|
else
|
33
|
-
|
51
|
+
policy_scope.resolve
|
34
52
|
end
|
35
53
|
end
|
54
|
+
|
55
|
+
def pundit_model(record)
|
56
|
+
record.is_a?(Array) ? record.last : record
|
57
|
+
end
|
36
58
|
end
|
37
59
|
end
|
38
60
|
end
|
@@ -27,15 +27,14 @@ to display a collection of resources in an HTML table.
|
|
27
27
|
cell-label--<%= collection_presenter.ordered_html_class(attr_name) %>
|
28
28
|
cell-label--<%= "#{collection_presenter.resource_name}_#{attr_name}" %>"
|
29
29
|
scope="col"
|
30
|
-
role="columnheader"
|
31
30
|
aria-sort="<%= sort_order(collection_presenter.ordered_html_class(attr_name)) %>">
|
32
31
|
<%= link_to(sanitized_order_params(page, collection_field_name).merge(
|
33
32
|
collection_presenter.order_params_for(attr_name, key: collection_field_name)
|
34
33
|
)) do %>
|
35
34
|
<%= t(
|
36
35
|
"helpers.label.#{collection_presenter.resource_name}.#{attr_name}",
|
37
|
-
default: resource_class.human_attribute_name(attr_name),
|
38
|
-
)
|
36
|
+
default: resource_class.human_attribute_name(attr_name).titleize,
|
37
|
+
) %>
|
39
38
|
<% if collection_presenter.ordered_by?(attr_name) %>
|
40
39
|
<span class="cell-label__sort-indicator cell-label__sort-indicator--<%= collection_presenter.ordered_html_class(attr_name) %>">
|
41
40
|
<svg aria-hidden="true">
|
@@ -33,10 +33,25 @@ and renders all form fields for a resource's editable attributes.
|
|
33
33
|
</div>
|
34
34
|
<% end %>
|
35
35
|
|
36
|
-
<% page.attributes(controller.action_name).each do |
|
37
|
-
<
|
38
|
-
|
39
|
-
|
36
|
+
<% page.attributes(controller.action_name).each do |title, attributes| -%>
|
37
|
+
<fieldset class="<%= "field-unit--nested" if title.present? %>">
|
38
|
+
<% if title.present? %>
|
39
|
+
<legend><%= t "helpers.label.#{f.object_name}.#{title}", default: title %></legend>
|
40
|
+
<% end %>
|
41
|
+
|
42
|
+
<% attributes.each do |attribute| %>
|
43
|
+
<div class="field-unit field-unit--<%= attribute.html_class %> field-unit--<%= requireness(attribute) %>">
|
44
|
+
<%= render_field attribute, f: f %>
|
45
|
+
|
46
|
+
<% hint_key = "administrate.field_hints.#{page.resource_name}.#{attribute.name}" %>
|
47
|
+
<% if I18n.exists?(hint_key) -%>
|
48
|
+
<div class="field-unit__hint">
|
49
|
+
<%= I18n.t(hint_key) %>
|
50
|
+
</div>
|
51
|
+
<% end -%>
|
52
|
+
</div>
|
53
|
+
<% end %>
|
54
|
+
</fieldset>
|
40
55
|
<% end -%>
|
41
56
|
|
42
57
|
<div class="form-actions">
|
@@ -7,7 +7,7 @@ for all resources in the admin dashboard,
|
|
7
7
|
as defined by the routes in the `admin/` namespace
|
8
8
|
%>
|
9
9
|
|
10
|
-
<nav class="navigation"
|
10
|
+
<nav class="navigation">
|
11
11
|
<%= link_to(t("administrate.navigation.back_to_app"), root_url, class: "button button--alt button--nav") if defined?(root_url) %>
|
12
12
|
|
13
13
|
<% Administrate::Namespace.new(namespace).resources_with_index_route.each do |resource| %>
|
@@ -1 +1 @@
|
|
1
|
-
<%= paginate resources, param_name:
|
1
|
+
<%= paginate resources, param_name: local_assigns.fetch(:param_name, "_page") %>
|
@@ -17,7 +17,7 @@ It displays a header, and renders the `_form` partial to do the heavy lifting.
|
|
17
17
|
|
18
18
|
<% content_for(:title) { t("administrate.actions.edit_resource", name: page.page_title) } %>
|
19
19
|
|
20
|
-
<header class="main-content__header"
|
20
|
+
<header class="main-content__header">
|
21
21
|
<h1 class="main-content__page-title">
|
22
22
|
<%= content_for(:title) %>
|
23
23
|
</h1>
|
@@ -18,7 +18,7 @@ as well as a link to its edit page.
|
|
18
18
|
|
19
19
|
<% content_for(:title) { t("administrate.actions.show_resource", name: page.page_title) } %>
|
20
20
|
|
21
|
-
<header class="main-content__header"
|
21
|
+
<header class="main-content__header">
|
22
22
|
<h1 class="main-content__page-title">
|
23
23
|
<%= content_for(:title) %>
|
24
24
|
</h1>
|
@@ -42,16 +42,24 @@ as well as a link to its edit page.
|
|
42
42
|
|
43
43
|
<section class="main-content__body">
|
44
44
|
<dl>
|
45
|
-
<% page.attributes.each do |
|
46
|
-
<
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
45
|
+
<% page.attributes.each do |title, attributes| %>
|
46
|
+
<fieldset class="<%= "field-unit--nested" if title.present? %>">
|
47
|
+
<% if title.present? %>
|
48
|
+
<legend><%= t "helpers.label.#{page.resource_name}.#{title}", default: title %></legend>
|
49
|
+
<% end %>
|
50
|
+
|
51
|
+
<% attributes.each do |attribute| %>
|
52
|
+
<dt class="attribute-label" id="<%= attribute.name %>">
|
53
|
+
<%= t(
|
54
|
+
"helpers.label.#{resource_name}.#{attribute.name}",
|
55
|
+
default: page.resource.class.human_attribute_name(attribute.name),
|
56
|
+
) %>
|
57
|
+
</dt>
|
58
|
+
|
59
|
+
<dd class="attribute-data attribute-data--<%=attribute.html_class%>"
|
60
|
+
><%= render_field attribute, page: page %></dd>
|
61
|
+
<% end %>
|
62
|
+
</fieldset>
|
55
63
|
<% end %>
|
56
64
|
</dl>
|
57
65
|
</section>
|
@@ -28,9 +28,10 @@ from the associated resource class's dashboard.
|
|
28
28
|
page: page,
|
29
29
|
resources: field.resources(page_number, order),
|
30
30
|
table_title: field.name,
|
31
|
+
resource_class: field.associated_class,
|
31
32
|
) %>
|
32
33
|
<% if field.more_than_limit? %>
|
33
|
-
<%=
|
34
|
+
<%= render("pagination", resources: field.resources(page_number), param_name: "#{field.name}[page]") %>
|
34
35
|
<% end %>
|
35
36
|
|
36
37
|
<% else %>
|
@@ -19,10 +19,20 @@ The form will be rendered as nested_from to parent relationship.
|
|
19
19
|
<%= f.fields_for field.attribute, field.data || field.nested_form.resource.class.new do |has_one_f| %>
|
20
20
|
<fieldset class="field-unit--nested">
|
21
21
|
<legend><%= t "helpers.label.#{f.object_name}.#{field.name}", default: field.name.titleize %></legend>
|
22
|
-
<% field.nested_form.attributes.each do |
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
<% field.nested_form.attributes.each do |title, attributes| -%>
|
23
|
+
|
24
|
+
<fieldset class="<%= "field-unit--nested" if title.present? %>">
|
25
|
+
<% if title.present? %>
|
26
|
+
<legend><%= t "helpers.label.#{f.object_name}.#{title}", default: title %></legend>
|
27
|
+
<% end %>
|
28
|
+
|
29
|
+
<% attributes.each do |attribute| %>
|
30
|
+
<div class="field-unit field-unit--<%= attribute.html_class %>">
|
31
|
+
<%= render_field attribute, f: has_one_f %>
|
32
|
+
</div>
|
33
|
+
<% end %>
|
34
|
+
</fieldset>
|
35
|
+
|
26
36
|
<% end -%>
|
27
37
|
</fieldset>
|
28
38
|
<% end %>
|
@@ -24,18 +24,24 @@ All show page attributes of has_one relationship would be rendered
|
|
24
24
|
[namespace, field.data],
|
25
25
|
) %>
|
26
26
|
</legend>
|
27
|
-
<% field.nested_show.attributes.each do |
|
28
|
-
<
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
27
|
+
<% field.nested_show.attributes.each do |title, attributes| -%>
|
28
|
+
<fieldset class="<%= "field-unit--nested" if title.present? %>">
|
29
|
+
<% if title.present? %>
|
30
|
+
<legend><%= t "helpers.label.#{namespace}.#{title}", default: title %></legend>
|
31
|
+
<% end %>
|
32
|
+
|
33
|
+
<% attributes.each do |attribute| %>
|
34
|
+
<dt class="attribute-label">
|
35
|
+
<%= t(
|
36
|
+
"helpers.label.#{field.associated_class_name.underscore}.#{attribute.name}",
|
37
|
+
default: attribute.name.titleize,
|
38
|
+
) %>
|
39
|
+
</dt>
|
40
|
+
<dd class="attribute-data attribute-data--<%= attribute.html_class %>">
|
41
|
+
<%= render_field attribute, { page: page } %>
|
42
|
+
</dd>
|
43
|
+
<% end %>
|
44
|
+
</fieldset>
|
39
45
|
<% end -%>
|
40
46
|
</fieldset>
|
41
47
|
<% end %>
|
@@ -19,27 +19,14 @@ to be displayed on a resource's edit form page.
|
|
19
19
|
<%= f.label field.attribute %>
|
20
20
|
</div>
|
21
21
|
<div class="field-unit__field">
|
22
|
-
|
23
|
-
|
22
|
+
<%=
|
23
|
+
f.select(
|
24
24
|
field.attribute,
|
25
|
-
|
25
|
+
options_for_select(
|
26
26
|
field.selectable_options,
|
27
|
-
:last,
|
28
|
-
:first,
|
29
27
|
field.data,
|
30
28
|
),
|
31
29
|
include_blank: field.include_blank_option
|
32
|
-
)
|
33
|
-
|
34
|
-
<%= f.select(
|
35
|
-
field.attribute,
|
36
|
-
options_from_collection_for_select(
|
37
|
-
field.selectable_options,
|
38
|
-
:to_s,
|
39
|
-
:to_s,
|
40
|
-
field.data,
|
41
|
-
),
|
42
|
-
include_blank: field.include_blank_option
|
43
|
-
) %>
|
44
|
-
<% end %>
|
30
|
+
)
|
31
|
+
%>
|
45
32
|
</div>
|
@@ -5,9 +5,9 @@ ja:
|
|
5
5
|
confirm: 本当によろしいですか?
|
6
6
|
destroy: 削除
|
7
7
|
edit: 編集
|
8
|
-
edit_resource:
|
9
|
-
show_resource:
|
10
|
-
new_resource:
|
8
|
+
edit_resource: "%{name}を編集"
|
9
|
+
show_resource: "%{name}を参照"
|
10
|
+
new_resource: "%{name}を作成"
|
11
11
|
back: 戻る
|
12
12
|
controller:
|
13
13
|
create:
|
@@ -22,9 +22,9 @@ ja:
|
|
22
22
|
none: データがありません
|
23
23
|
form:
|
24
24
|
error: エラー
|
25
|
-
errors: "%{pluralized_errors}のため%{resource_name}
|
25
|
+
errors: "%{pluralized_errors}のため%{resource_name}を保存できませんでした。"
|
26
26
|
navigation:
|
27
27
|
back_to_app: アプリに戻る
|
28
28
|
search:
|
29
29
|
clear: 検索をクリアする
|
30
|
-
label:
|
30
|
+
label: "%{resource}を検索"
|
data/docs/authorization.md
CHANGED
@@ -28,20 +28,30 @@ technically have access to see in the main app. For example, a user may
|
|
28
28
|
have all public records in their scope, but you want to only show *their*
|
29
29
|
records in the admin interface to reduce confusion.
|
30
30
|
|
31
|
-
In this case, you can add
|
32
|
-
|
31
|
+
In this case, you can add additional pundit `policy_namespace` in your controller
|
32
|
+
and Administrate will use the namespaced pundit policy instead.
|
33
33
|
|
34
34
|
For example:
|
35
35
|
|
36
36
|
```ruby
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
37
|
+
# app/controllers/admin/posts_controller.rb
|
38
|
+
module Admin
|
39
|
+
class PostsController < ApplicationController
|
40
|
+
include Administrate::Punditize
|
41
|
+
|
42
|
+
def policy_namespace
|
43
|
+
[:admin]
|
41
44
|
end
|
45
|
+
end
|
46
|
+
end
|
42
47
|
|
43
|
-
|
44
|
-
|
48
|
+
# app/policies/admin/post_policy.rb
|
49
|
+
module Admin
|
50
|
+
class PostPolicy < ApplicationPolicy
|
51
|
+
class Scope < Scope
|
52
|
+
def resolve
|
53
|
+
scope.where(owner: user)
|
54
|
+
end
|
45
55
|
end
|
46
56
|
end
|
47
57
|
end
|
@@ -93,3 +93,17 @@ To set custom redirects after the actions `create`, `update` and `destroy` you c
|
|
93
93
|
[namespace, requested_resource.some_other_resource]
|
94
94
|
end
|
95
95
|
```
|
96
|
+
|
97
|
+
## Creating Records
|
98
|
+
|
99
|
+
You can perform actions after creation by passing a `block` to `super` in the
|
100
|
+
`create` method. The block will only be called if the resource is successfully
|
101
|
+
created.
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
def create
|
105
|
+
super do |resource|
|
106
|
+
# do something with the newly created resource
|
107
|
+
end
|
108
|
+
end
|
109
|
+
```
|
@@ -113,8 +113,11 @@ association `belongs_to :country`, from your model.
|
|
113
113
|
|
114
114
|
**Field::HasMany**
|
115
115
|
|
116
|
-
`:
|
117
|
-
|
116
|
+
`:collection_attributes` - Set the columns to display in the show view.
|
117
|
+
Default is COLLECTION_ATTRIBUTES in dashboard.
|
118
|
+
|
119
|
+
`:limit` - The number of resources (paginated) to display in the show view. To disable pagination,
|
120
|
+
set this to `0` or `false`. Default is `5`.
|
118
121
|
|
119
122
|
`:sort_by` - What to sort the association by in the show view.
|
120
123
|
|
@@ -128,6 +131,10 @@ association `belongs_to :country`, from your model.
|
|
128
131
|
|
129
132
|
**Field::HasOne**
|
130
133
|
|
134
|
+
`:order` - Specifies the column used to order the records. It will apply both in
|
135
|
+
the table views and in the dropdown menu on the record forms.
|
136
|
+
You can set multiple columns as well with direction. E.g.: `"name, email DESC"`.
|
137
|
+
|
131
138
|
`:searchable` - Specify if the attribute should be considered when searching.
|
132
139
|
Default is `false`.
|
133
140
|
|
@@ -164,8 +171,7 @@ more results than expected. Default is `false`.
|
|
164
171
|
and works by by passing a hash that includes the formatter (`formatter`) and
|
165
172
|
the options for the formatter (`formatter_options`). Defaults to the locale's
|
166
173
|
delimiter when `formatter_options` does not include a `delimiter`. See the
|
167
|
-
example below.
|
168
|
-
`ActiveSupport::NumberHelper.number_to_delimited` is supported.
|
174
|
+
example below. All helpers from `ActiveSupport::NumberHelper` are supported.
|
169
175
|
|
170
176
|
For example, you might use the following to display U.S. currency:
|
171
177
|
|
@@ -218,25 +224,31 @@ objects to display as.
|
|
218
224
|
|
219
225
|
**Field::Select**
|
220
226
|
|
221
|
-
`:collection` -
|
222
|
-
an array or an object responding to `:call`. Defaults to `[]`.
|
227
|
+
`:collection` - The options available to select. The format is the same as for Rails's own [`options_for_select`](https://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-options_for_select).
|
223
228
|
|
224
|
-
|
225
|
-
|
226
|
-
For example:
|
229
|
+
If the given value responds to `call`, this will be called and the result used instead. The call will receive an instance of the field as argument. For example:
|
227
230
|
|
228
231
|
```ruby
|
229
|
-
|
230
|
-
collection:
|
232
|
+
confirmation: Field::Select.with_options(
|
233
|
+
collection: ->(field) {
|
234
|
+
person = field.resource
|
235
|
+
{
|
236
|
+
"no, #{person.name}" => "opt0",
|
237
|
+
"yes, #{person.name}" => "opt1",
|
238
|
+
"absolutely, #{person.name}" => "opt2",
|
239
|
+
}
|
240
|
+
},
|
231
241
|
)
|
232
|
-
|
233
242
|
```
|
234
243
|
|
244
|
+
Administrate will detect if the attribute is an `ActiveRecord::Enum` and extract the available options. Note that if a `collection` is provided it will take precedence.
|
245
|
+
|
246
|
+
If no collection is provided and no enum can be detected, the list of options will be empty.
|
247
|
+
|
235
248
|
`:searchable` - Specify if the attribute should be considered when searching.
|
236
249
|
Default is `true`.
|
237
250
|
|
238
|
-
`:include_blank` -
|
239
|
-
blank option. Default is `false`.
|
251
|
+
`:include_blank` - Similar to [the option of the same name accepted by Rails helpers](https://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html). If provided, a "blank" option will be added first to the list of options, with the value of `include_blank` as label.
|
240
252
|
|
241
253
|
**Field::String**
|
242
254
|
|
@@ -373,3 +385,54 @@ FORM_ATTRIBUTES_EDIT = [
|
|
373
385
|
```
|
374
386
|
|
375
387
|
Or for custom action with constant name `"FORM_ATTRIBUTES_#{action.upcase}"`
|
388
|
+
|
389
|
+
### Form Fields' Hints
|
390
|
+
|
391
|
+
You can show a brief text element below an input field by setting the
|
392
|
+
corresponding translation key using the path:
|
393
|
+
|
394
|
+
`administrate.field_hints.#{model_name}.#{field_name}`
|
395
|
+
|
396
|
+
For example, with a Customer dashboard with an email field you can add a
|
397
|
+
string value that will be used as text hint:
|
398
|
+
|
399
|
+
```yml
|
400
|
+
en:
|
401
|
+
administrate:
|
402
|
+
field_hints:
|
403
|
+
customer:
|
404
|
+
email: field_hint
|
405
|
+
```
|
406
|
+
|
407
|
+
## Grouped Attributes
|
408
|
+
|
409
|
+
You may have models with a large number of fields and therefore you might want to group them in a meaningul way:
|
410
|
+
|
411
|
+
```ruby
|
412
|
+
class UserDashboard < Administrate::BaseDashboard
|
413
|
+
SHOW_PAGE_ATTRIBUTES = {
|
414
|
+
"" => [:username],
|
415
|
+
"Personal Information" => [:first_name, :last_name, :email],
|
416
|
+
"Address" => [:address_line_one, :address_line_two, :address_city, :address_state, :address_country]
|
417
|
+
}
|
418
|
+
|
419
|
+
FORM_ATTRIBUTES = {
|
420
|
+
"" => [:username, :password, :password_confirmation],
|
421
|
+
"personal_information" => [:first_name, :last_name, :email],
|
422
|
+
"address" => [:address_line_one, :address_line_two, :address_city, :address_state, :address_country]
|
423
|
+
}
|
424
|
+
end
|
425
|
+
```
|
426
|
+
|
427
|
+
You can optionally translate your group labels:
|
428
|
+
|
429
|
+
```yaml
|
430
|
+
en:
|
431
|
+
helpers:
|
432
|
+
label:
|
433
|
+
user:
|
434
|
+
address: Address
|
435
|
+
personal_information: Personal Information
|
436
|
+
```
|
437
|
+
|
438
|
+
If not defined (see `SHOW_PAGE_ATTRIBUTES` above), Administrate will default to the given strings.
|
@@ -10,7 +10,7 @@ In general, you can override any of the views under Administrate's
|
|
10
10
|
[/app/views][1].
|
11
11
|
For example, say that you want to customize the template used for flash
|
12
12
|
messages. You can provide your own as
|
13
|
-
|
13
|
+
`app/views/admin/application/_flashes.html.erb`, and it will replace
|
14
14
|
Administrate's own.
|
15
15
|
|
16
16
|
Figuring out which views are available and where can be repetitive. You can
|