administrate 0.18.0 → 0.20.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|