administrate 0.17.0 → 0.20.0

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.
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