administrate 0.17.0 → 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +0 -2
  3. data/app/assets/javascripts/administrate/application.js +0 -2
  4. data/app/assets/javascripts/administrate/components/select.js +3 -0
  5. data/app/assets/stylesheets/administrate/application.scss +0 -1
  6. data/app/assets/stylesheets/administrate/base/_forms.scss +1 -1
  7. data/app/assets/stylesheets/administrate/components/_buttons.scss +9 -0
  8. data/app/assets/stylesheets/administrate/components/_field-unit.scss +7 -0
  9. data/app/assets/stylesheets/administrate/components/_flashes.scss +2 -2
  10. data/app/assets/stylesheets/administrate/library/_variables.scss +1 -1
  11. data/app/controllers/administrate/application_controller.rb +85 -17
  12. data/app/controllers/concerns/administrate/punditize.rb +44 -20
  13. data/app/helpers/administrate/application_helper.rb +24 -6
  14. data/app/views/administrate/application/_collection.html.erb +5 -6
  15. data/app/views/administrate/application/_collection_header_actions.html.erb +2 -2
  16. data/app/views/administrate/application/_collection_item_actions.html.erb +4 -4
  17. data/app/views/administrate/application/_form.html.erb +19 -4
  18. data/app/views/administrate/application/_index_header.html.erb +2 -2
  19. data/app/views/administrate/application/_navigation.html.erb +2 -2
  20. data/app/views/administrate/application/_pagination.html.erb +1 -0
  21. data/app/views/administrate/application/edit.html.erb +2 -2
  22. data/app/views/administrate/application/index.html.erb +1 -1
  23. data/app/views/administrate/application/new.html.erb +1 -1
  24. data/app/views/administrate/application/show.html.erb +28 -12
  25. data/app/views/fields/belongs_to/_index.html.erb +1 -1
  26. data/app/views/fields/belongs_to/_show.html.erb +1 -1
  27. data/app/views/fields/date/_form.html.erb +1 -3
  28. data/app/views/fields/date_time/_form.html.erb +1 -3
  29. data/app/views/fields/has_many/_index.html.erb +1 -1
  30. data/app/views/fields/has_many/_show.html.erb +2 -1
  31. data/app/views/fields/has_one/_form.html.erb +15 -5
  32. data/app/views/fields/has_one/_index.html.erb +2 -1
  33. data/app/views/fields/has_one/_show.html.erb +20 -13
  34. data/app/views/fields/polymorphic/_index.html.erb +2 -1
  35. data/app/views/fields/polymorphic/_show.html.erb +1 -1
  36. data/app/views/fields/select/_form.html.erb +5 -18
  37. data/app/views/fields/time/_form.html.erb +2 -3
  38. data/app/views/fields/url/_index.html.erb +1 -1
  39. data/app/views/fields/url/_show.html.erb +1 -1
  40. data/app/views/layouts/administrate/application.html.erb +1 -1
  41. data/config/locales/administrate.de.yml +2 -2
  42. data/config/locales/administrate.ja.yml +5 -5
  43. data/config/locales/administrate.sl.yml +30 -0
  44. data/docs/adding_controllers_without_related_model.md +2 -2
  45. data/docs/authorization.md +43 -20
  46. data/docs/customizing_controller_actions.md +25 -6
  47. data/docs/customizing_dashboards.md +88 -10
  48. data/docs/getting_started.md +1 -1
  49. data/docs/guides/customising_search.md +149 -0
  50. data/docs/guides/hiding_dashboards_from_sidebar.md +4 -2
  51. data/docs/guides/scoping_has_many_relations.md +27 -0
  52. data/docs/guides.md +3 -1
  53. data/lib/administrate/base_dashboard.rb +39 -3
  54. data/lib/administrate/engine.rb +2 -2
  55. data/lib/administrate/field/associative.rb +18 -8
  56. data/lib/administrate/field/base.rb +4 -0
  57. data/lib/administrate/field/belongs_to.rb +9 -2
  58. data/lib/administrate/field/deferred.rb +5 -1
  59. data/lib/administrate/field/has_many.rb +20 -6
  60. data/lib/administrate/field/has_one.rb +4 -0
  61. data/lib/administrate/field/number.rb +2 -8
  62. data/lib/administrate/field/polymorphic.rb +2 -1
  63. data/lib/administrate/field/select.rb +19 -9
  64. data/lib/administrate/field/url.rb +4 -0
  65. data/lib/administrate/not_authorized_error.rb +20 -0
  66. data/lib/administrate/order.rb +73 -17
  67. data/lib/administrate/page/base.rb +4 -0
  68. data/lib/administrate/page/collection.rb +1 -0
  69. data/lib/administrate/page/form.rb +9 -8
  70. data/lib/administrate/page/show.rb +10 -2
  71. data/lib/administrate/resource_resolver.rb +2 -1
  72. data/lib/administrate/search.rb +1 -1
  73. data/lib/administrate/version.rb +1 -1
  74. data/lib/administrate/view_generator.rb +6 -1
  75. data/lib/administrate.rb +24 -2
  76. data/lib/generators/administrate/dashboard/dashboard_generator.rb +20 -2
  77. data/lib/generators/administrate/dashboard/templates/controller.rb.erb +2 -2
  78. data/lib/generators/administrate/install/install_generator.rb +6 -1
  79. data/lib/generators/administrate/routes/routes_generator.rb +11 -2
  80. data/lib/generators/administrate/test_record.rb +21 -0
  81. metadata +39 -46
  82. data/app/assets/javascripts/administrate/components/date_time_picker.js +0 -14
  83. data/config/i18n-tasks.yml +0 -18
  84. data/config/routes.rb +0 -2
  85. data/config/unicorn.rb +0 -25
@@ -16,7 +16,7 @@ By default, the relationship is rendered as a link to the associated object.
16
16
  %>
17
17
 
18
18
  <% if field.data %>
19
- <% if valid_action?(:show, field.associated_class) && show_action?(:show, field.associated_class) %>
19
+ <% if accessible_action?(field.data, :show) %>
20
20
  <%= link_to(
21
21
  field.display_associated_resource,
22
22
  [namespace, field.data],
@@ -2,7 +2,6 @@
2
2
  # Date Form Partial
3
3
 
4
4
  This partial renders an input element for a date attribute.
5
- By default, the input is a text field that is augmented with [DateTimePicker].
6
5
 
7
6
  ## Local variables:
8
7
 
@@ -13,12 +12,11 @@ By default, the input is a text field that is augmented with [DateTimePicker].
13
12
  A wrapper around the Date value pulled from the database.
14
13
 
15
14
  [1]: http://www.rubydoc.info/gems/administrate/Administrate/Field/Date
16
- [DateTimePicker]: https://github.com/Eonasdan/bootstrap-datetimepicker
17
15
  %>
18
16
 
19
17
  <div class="field-unit__label">
20
18
  <%= f.label field.attribute %>
21
19
  </div>
22
20
  <div class="field-unit__field">
23
- <%= f.text_field field.attribute, data: { type: 'date' } %>
21
+ <%= f.date_field field.attribute %>
24
22
  </div>
@@ -2,7 +2,6 @@
2
2
  # DateTime Form Partial
3
3
 
4
4
  This partial renders an input element for a datetime attribute.
5
- By default, the input is a text field that is augmented with [DateTimePicker].
6
5
 
7
6
  ## Local variables:
8
7
 
@@ -13,12 +12,11 @@ By default, the input is a text field that is augmented with [DateTimePicker].
13
12
  A wrapper around the DateTime value pulled from the database.
14
13
 
15
14
  [1]: http://www.rubydoc.info/gems/administrate/Administrate/Field/DateTime
16
- [DateTimePicker]: https://github.com/Eonasdan/bootstrap-datetimepicker
17
15
  %>
18
16
 
19
17
  <div class="field-unit__label">
20
18
  <%= f.label field.attribute %>
21
19
  </div>
22
20
  <div class="field-unit__field">
23
- <%= f.text_field field.attribute, data: { type: 'datetime' } %>
21
+ <%= f.datetime_local_field field.attribute, step: 1 %>
24
22
  </div>
@@ -16,4 +16,4 @@ as a count of how many objects are associated through the relationship.
16
16
  [1]: http://www.rubydoc.info/gems/administrate/Administrate/Field/HasMany
17
17
  %>
18
18
 
19
- <%= pluralize(field.data.size, field.attribute.to_s.humanize.downcase.singularize) %>
19
+ <%= pluralize(field.data.size, t("activerecord.models.#{field.attribute.to_s.singularize}", default: field.attribute.to_s.humanize.downcase.singularize, count: field.data.size)) %>
@@ -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
- <%= paginate field.resources(page_number), param_name: "#{field.name}[page]" %>
34
+ <%= render("pagination", resources: field.resources(page_number), param_name: "#{field.name}[page]") %>
34
35
  <% end %>
35
36
 
36
37
  <% else %>
@@ -18,11 +18,21 @@ The form will be rendered as nested_from to parent relationship.
18
18
 
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
- <legend><%= t "helpers.label.#{f.object_name}.#{field.nested_form.resource_name}", default: field.nested_form.resource_name.titleize %></legend>
22
- <% field.nested_form.attributes.each do |attribute| -%>
23
- <div class="field-unit field-unit--<%= attribute.html_class %>">
24
- <%= render_field attribute, f: has_one_f %>
25
- </div>
21
+ <legend><%= t "helpers.label.#{f.object_name}.#{field.name}", default: field.name.titleize %></legend>
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 %>
@@ -16,7 +16,8 @@ By default, the relationship is rendered as a link to the associated object.
16
16
  %>
17
17
 
18
18
  <% if field.linkable? %>
19
- <%= link_to(
19
+ <%= link_to_if(
20
+ accessible_action?(field.data, :show),
20
21
  field.display_associated_resource,
21
22
  [namespace, field.data],
22
23
  ) %>
@@ -18,23 +18,30 @@ All show page attributes of has_one relationship would be rendered
18
18
  <% if field.linkable? %>
19
19
  <fieldset class="attribute--nested">
20
20
  <legend>
21
- <%= link_to(
21
+ <%= link_to_if(
22
+ accessible_action?(field.data, :show),
22
23
  field.display_associated_resource,
23
24
  [namespace, field.data],
24
25
  ) %>
25
26
  </legend>
26
- <% field.nested_show.attributes.each do |attribute| -%>
27
- <div>
28
- <dt class="attribute-label">
29
- <%= t(
30
- "helpers.label.#{resource_name}.#{attribute.name}",
31
- default: attribute.name.titleize,
32
- ) %>
33
- </dt>
34
- <dd class="attribute-data attribute-data--<%= attribute.html_class %>">
35
- <%= render_field attribute, { page: page } %>
36
- </dd>
37
- </div>
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>
38
45
  <% end -%>
39
46
  </fieldset>
40
47
  <% end %>
@@ -17,7 +17,8 @@ By default, the relationship is rendered as a link to the associated object.
17
17
  %>
18
18
 
19
19
  <% if field.data %>
20
- <%= link_to(
20
+ <%= link_to_if(
21
+ accessible_action?(field.data, :show),
21
22
  field.display_associated_resource,
22
23
  [namespace, field.data]
23
24
  ) %>
@@ -17,7 +17,7 @@ By default, the relationship is rendered as a link to the associated object.
17
17
  %>
18
18
 
19
19
  <% if field.data %>
20
- <% if valid_action?(:show, field.data.class) %>
20
+ <% if accessible_action?(field.data, :show) %>
21
21
  <%= link_to(
22
22
  field.display_associated_resource,
23
23
  [namespace, field.data],
@@ -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
- <% if field.selectable_options.first&.is_a?(Array) %>
23
- <%= f.select(
22
+ <%=
23
+ f.select(
24
24
  field.attribute,
25
- options_from_collection_for_select(
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
- <% else %>
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>
@@ -2,7 +2,6 @@
2
2
  # Time Form Partial
3
3
 
4
4
  This partial renders an input element for time attributes.
5
- By default, the input is a text field that is augmented with [DateTimePicker].
6
5
 
7
6
  ## Local variables:
8
7
 
@@ -12,12 +11,12 @@ By default, the input is a text field that is augmented with [DateTimePicker].
12
11
  An instance of [Administrate::Field::Time][1].
13
12
  A wrapper around the tmie attributes pulled from the model.
14
13
 
15
- [DateTimePicker]: https://github.com/Eonasdan/bootstrap-datetimepicker
14
+ [1]: http://www.rubydoc.info/gems/administrate/Administrate/Field/Time
16
15
  %>
17
16
 
18
17
  <div class="field-unit__label">
19
18
  <%= f.label field.attribute %>
20
19
  </div>
21
20
  <div class="field-unit__field">
22
- <%= f.text_field field.attribute, data: { type: 'time' }, value: field.data&.strftime("%H:%M:%S") %>
21
+ <%= f.time_field field.attribute, step: 1 %>
23
22
  </div>
@@ -15,6 +15,6 @@ By default, the value is rendered as an `a` element.
15
15
  [1]: http://www.rubydoc.info/gems/administrate/Administrate/Field/Url
16
16
  %>
17
17
 
18
- <%= content_tag :a, href: field.data do %>
18
+ <%= content_tag :a, href: field.data, **field.html_options do %>
19
19
  <%= field.data %>
20
20
  <% end %>
@@ -15,6 +15,6 @@ By default, the value is rendered as an `a` element.
15
15
  [1]: http://www.rubydoc.info/gems/administrate/Administrate/Field/Url
16
16
  %>
17
17
 
18
- <%= content_tag :a, href: field.data do %>
18
+ <%= content_tag :a, href: field.data, **field.html_options do %>
19
19
  <%= field.data %>
20
20
  <% end %>
@@ -31,7 +31,7 @@ By default, it renders:
31
31
  <div class="app-container">
32
32
  <%= render "navigation" -%>
33
33
 
34
- <main class="main-content" role="main">
34
+ <main class="main-content">
35
35
  <%= render "flashes" -%>
36
36
  <%= yield %>
37
37
  </main>
@@ -21,8 +21,8 @@ de:
21
21
  more: "%{count} von %{total_count}"
22
22
  none: Keine
23
23
  form:
24
- error: error
25
- errors: "%{pluralized_errors} haben das Speichern dieses %{resource_name} verhindert:"
24
+ error: Fehler
25
+ errors: "%{resource_name} konnte nicht gespeichert werden, es gab %{pluralized_errors}."
26
26
  navigation:
27
27
  back_to_app: Zurück zur App
28
28
  search:
@@ -5,9 +5,9 @@ ja:
5
5
  confirm: 本当によろしいですか?
6
6
  destroy: 削除
7
7
  edit: 編集
8
- edit_resource: 編集 %{name}
9
- show_resource: 参照 %{name}
10
- new_resource: 新規 %{name}
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: サーチ %{resource}
30
+ label: "%{resource}を検索"
@@ -0,0 +1,30 @@
1
+ ---
2
+ sl:
3
+ administrate:
4
+ actions:
5
+ confirm: Ali ste preričani?
6
+ destroy: Izbriši
7
+ edit: Uredi
8
+ edit_resource: Uredi %{name}
9
+ show_resource: Prikaži %{name}
10
+ new_resource: Dodaj %{name}
11
+ back: Nazaj
12
+ controller:
13
+ create:
14
+ success: "%{resource} je dodan."
15
+ destroy:
16
+ success: "%{resource} je izbrisan."
17
+ update:
18
+ success: "%{resource} je posodobljen."
19
+ fields:
20
+ has_many:
21
+ more: Prikazanih %{count} od %{total_count}
22
+ none: Nobene
23
+ form:
24
+ error: napaka
25
+ errors: "%{resource_name} ni mogoče shraniti zaradi:"
26
+ navigation:
27
+ back_to_app: Nazaj v aplikacijo
28
+ search:
29
+ clear: Počisti iskanje
30
+ label: Išči %{resource}
@@ -14,9 +14,9 @@ routes are displayed in the sidebar and then add a custom dashboard:
14
14
  <div style="padding: 20px">
15
15
  <h1>Stats</h1>
16
16
  <br>
17
- <p><b>Total Customers:</b> <%= @stats[:customer_count] %></h1>
17
+ <p><b>Total Customers:</b> <%= @stats[:customer_count] %></p>
18
18
  <br>
19
- <p><b>Total Orders:</b> <%= @stats[:order_count] %></h1>
19
+ <p><b>Total Orders:</b> <%= @stats[:order_count] %></p>
20
20
  </div>
21
21
  ```
22
22
 
@@ -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 an additional `resolve_admin` to your policy's
32
- scope and Administrate will use this instead of the `resolve` method.
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
- class PostPolicy < ApplicationPolicy
38
- class Scope < Scope
39
- def resolve
40
- scope.all
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
- def resolve_admin
44
- scope.where(owner: user)
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
@@ -49,23 +59,36 @@ end
49
59
 
50
60
  ## Authorization without Pundit
51
61
 
52
- If you use a different authorization library, or you want to roll your own,
53
- you just need to override a few methods in your controllers or
54
- `Admin::ApplicationController`. For example:
62
+ Pundit is not necessary to implement authorization within Administrate. It is
63
+ simply a common solution that many in the community use, and for this reason
64
+ Administrate provides a plugin to work with it. However you can use a different
65
+ solution or roll out your own.
66
+
67
+ To integrate a different authorization solution, you will need to
68
+ implement some methods in `Admin::ApplicationController`
69
+ or its subclasses.
70
+
71
+ These are the methods to override, with examples:
55
72
 
56
73
  ```ruby
57
- # Limit the scope of the given resource
74
+ # Used in listings, such as the `index` actions. It
75
+ # restricts the scope of records that a user can access.
76
+ # Returns an ActiveRecord scope.
58
77
  def scoped_resource
59
78
  super.where(user: current_user)
60
79
  end
61
80
 
62
- # Raise an exception if the user is not permitted to access this resource
63
- def authorize_resource(resource)
64
- raise "Erg!" unless show_action?(params[:action], resource)
65
- end
66
-
67
- # Hide links to actions if the user is not allowed to do them
68
- def show_action?(action, resource)
69
- current_user.can? action, resource
81
+ # Return true if the current user can access the given
82
+ # resource, false otherwise.
83
+ def authorized_action?(resource, action)
84
+ current_user.can?(resource, action)
70
85
  end
71
86
  ```
87
+
88
+ Additionally, the method `authorize_resource(resource)`
89
+ should throw an exception if the current user is not
90
+ allowed to access the given resource. Normally
91
+ you wouldn't need to override it, as the default
92
+ implementation uses `authorized_action?` to produce the
93
+ correct behaviour. However you may still want to override it
94
+ if you want to raise a custom error type.
@@ -46,17 +46,22 @@ end
46
46
 
47
47
  ## Customizing Actions
48
48
 
49
- To enable or disable certain actions you could override `valid_action?` method in your dashboard controller like this:
49
+ To disable certain actions globally, you can disable their
50
+ routes in `config/routes.rb`, using the usual Rails
51
+ facilities for this. For example:
50
52
 
51
53
  ```ruby
52
- # disable 'edit' and 'destroy' links
53
- def valid_action?(name, resource = resource_class)
54
- %w[edit destroy].exclude?(name.to_s) && super
54
+ Rails.application.routes.draw do
55
+ # ...
56
+ namespace :admin do
57
+ # ...
58
+
59
+ # Payments can only be listed or displayed
60
+ resources :payments, only: [:index, :show]
61
+ end
55
62
  end
56
63
  ```
57
64
 
58
- Action is one of `new`, `edit`, `show`, `destroy`.
59
-
60
65
  ## Customizing Default Sorting
61
66
 
62
67
  To set the default sorting on the index action you could override `default_sorting_attribute` or `default_sorting_direction` in your dashboard controller like this:
@@ -88,3 +93,17 @@ To set custom redirects after the actions `create`, `update` and `destroy` you c
88
93
  [namespace, requested_resource.some_other_resource]
89
94
  end
90
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
+ ```
@@ -77,8 +77,9 @@ which are specified through the `.with_options` class method:
77
77
 
78
78
  **Field::BelongsTo**
79
79
 
80
- `:order` - Specifies the order of the dropdown menu, can be ordered by more
81
- than one column. e.g.: `"name, email DESC"`.
80
+ `:order` - Specifies the column used to order the records. It will apply both in
81
+ the table views and in the dropdown menu on the record forms.
82
+ You can set multiple columns as well with direction. E.g.: `"name, email DESC"`.
82
83
 
83
84
  `:scope` - Specifies a custom scope inside a callable. Useful for preloading.
84
85
  Example: `.with_options(scope: -> { MyModel.includes(:rel).limit(5) })`
@@ -112,8 +113,11 @@ association `belongs_to :country`, from your model.
112
113
 
113
114
  **Field::HasMany**
114
115
 
115
- `:limit` - Set the number of resources to display in the show view. Default is
116
- `5`.
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`.
117
121
 
118
122
  `:sort_by` - What to sort the association by in the show view.
119
123
 
@@ -127,6 +131,10 @@ association `belongs_to :country`, from your model.
127
131
 
128
132
  **Field::HasOne**
129
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
+
130
138
  `:searchable` - Specify if the attribute should be considered when searching.
131
139
  Default is `false`.
132
140
 
@@ -163,8 +171,7 @@ more results than expected. Default is `false`.
163
171
  and works by by passing a hash that includes the formatter (`formatter`) and
164
172
  the options for the formatter (`formatter_options`). Defaults to the locale's
165
173
  delimiter when `formatter_options` does not include a `delimiter`. See the
166
- example below. Note that currently only
167
- `ActiveSupport::NumberHelper.number_to_delimited` is supported.
174
+ example below. All helpers from `ActiveSupport::NumberHelper` are supported.
168
175
 
169
176
  For example, you might use the following to display U.S. currency:
170
177
 
@@ -217,14 +224,31 @@ objects to display as.
217
224
 
218
225
  **Field::Select**
219
226
 
220
- `:collection` - Specify the options shown on the select field. It accept either
221
- 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).
228
+
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:
230
+
231
+ ```ruby
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
+ },
241
+ )
242
+ ```
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.
222
247
 
223
248
  `:searchable` - Specify if the attribute should be considered when searching.
224
249
  Default is `true`.
225
250
 
226
- `:include_blank` - Specifies if the select element to be rendered should include
227
- 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.
228
252
 
229
253
  **Field::String**
230
254
 
@@ -250,6 +274,9 @@ Default is `true`.
250
274
  `:truncate` - Set the number of characters to display in the index view.
251
275
  Defaults to `50`.
252
276
 
277
+ `:html_options` - Specify anchor tag attributes (e.g., `target="_blank"`).
278
+ Defaults is `{}`.
279
+
253
280
  **Field::Password**
254
281
 
255
282
  `:searchable` - Specify if the attribute should be considered when searching.
@@ -358,3 +385,54 @@ FORM_ATTRIBUTES_EDIT = [
358
385
  ```
359
386
 
360
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.
@@ -3,7 +3,7 @@ title: Getting Started
3
3
  ---
4
4
 
5
5
  Administrate is released as a Ruby gem, and can be installed on Rails
6
- applications version 5.0 or greater. We support Ruby 2.6 and up.
6
+ applications version 6.0 or greater. We support Ruby 3.0 and up.
7
7
 
8
8
  First, add the following to your Gemfile:
9
9