administrate 0.8.1 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of administrate might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/app/assets/stylesheets/administrate/components/_cells.scss +2 -6
- data/app/assets/stylesheets/docs.scss +1 -0
- data/app/controllers/administrate/application_controller.rb +35 -3
- data/app/controllers/concerns/administrate/punditize.rb +36 -0
- data/app/helpers/administrate/application_helper.rb +9 -4
- data/app/views/administrate/application/_collection.html.erb +9 -7
- data/app/views/administrate/application/_form.html.erb +5 -2
- data/app/views/administrate/application/_navigation.html.erb +1 -1
- data/app/views/administrate/application/edit.html.erb +3 -3
- data/app/views/administrate/application/index.html.erb +5 -2
- data/app/views/administrate/application/new.html.erb +6 -1
- data/app/views/administrate/application/show.html.erb +3 -3
- data/app/views/fields/has_many/_index.html.erb +1 -1
- data/app/views/fields/polymorphic/_form.html.erb +11 -6
- data/app/views/fields/polymorphic/_show.html.erb +8 -4
- data/config/locales/administrate.ar.yml +6 -6
- data/config/locales/administrate.bs.yml +27 -0
- data/config/locales/administrate.ca.yml +28 -0
- data/config/locales/administrate.da.yml +6 -6
- data/config/locales/administrate.de.yml +8 -8
- data/config/locales/administrate.en.yml +6 -6
- data/config/locales/administrate.es.yml +6 -6
- data/config/locales/administrate.fr.yml +6 -6
- data/config/locales/administrate.it.yml +6 -6
- data/config/locales/administrate.ja.yml +6 -6
- data/config/locales/administrate.ko.yml +6 -6
- data/config/locales/administrate.nl.yml +6 -6
- data/config/locales/administrate.pl.yml +6 -6
- data/config/locales/administrate.pt-BR.yml +6 -6
- data/config/locales/administrate.pt.yml +6 -6
- data/config/locales/administrate.ru.yml +6 -6
- data/config/locales/administrate.sv.yml +6 -6
- data/config/locales/administrate.uk.yml +6 -6
- data/config/locales/administrate.vi.yml +6 -6
- data/config/locales/administrate.zh-CN.yml +6 -6
- data/config/locales/administrate.zh-TW.yml +6 -6
- data/docs/authorization.md +69 -0
- data/docs/customizing_attribute_partials.md +20 -1
- data/docs/customizing_dashboards.md +54 -0
- data/docs/getting_started.md +82 -1
- data/lib/administrate/field/associative.rb +4 -0
- data/lib/administrate/field/base.rb +1 -1
- data/lib/administrate/field/belongs_to.rb +4 -3
- data/lib/administrate/field/date_time.rb +13 -2
- data/lib/administrate/field/deferred.rb +6 -5
- data/lib/administrate/field/has_many.rb +2 -2
- data/lib/administrate/field/has_one.rb +16 -8
- data/lib/administrate/field/polymorphic.rb +41 -3
- data/lib/administrate/order.rb +38 -5
- data/lib/administrate/resource_resolver.rb +2 -2
- data/lib/administrate/search.rb +1 -1
- data/lib/administrate/version.rb +1 -1
- data/lib/generators/administrate/dashboard/USAGE +1 -1
- data/lib/generators/administrate/dashboard/dashboard_generator.rb +7 -1
- data/lib/generators/administrate/dashboard/templates/controller.rb.erb +2 -2
- data/lib/generators/administrate/install/install_generator.rb +13 -6
- data/lib/generators/administrate/install/templates/{application_controller.rb → application_controller.rb.erb} +1 -1
- data/lib/generators/administrate/routes/routes_generator.rb +5 -0
- data/lib/generators/administrate/routes/templates/routes.rb.erb +1 -1
- data/lib/generators/administrate/views/field_generator.rb +19 -5
- metadata +8 -4
@@ -5,8 +5,9 @@ zh-TW:
|
|
5
5
|
confirm: 確定?
|
6
6
|
destroy: 刪除
|
7
7
|
edit: 編輯
|
8
|
-
|
9
|
-
|
8
|
+
edit_resource: 編輯 %{name}
|
9
|
+
show_resource: 檢視 %{name}
|
10
|
+
new_resource: 新增 %{name}
|
10
11
|
back: 返回
|
11
12
|
controller:
|
12
13
|
create:
|
@@ -19,10 +20,9 @@ zh-TW:
|
|
19
20
|
has_many:
|
20
21
|
more: 顯示 %{total_count} 筆中的 %{count} 筆資料
|
21
22
|
none: 無
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
not_supported: 表單尚未支援 HasOne 關聯。
|
23
|
+
form:
|
24
|
+
error: error
|
25
|
+
errors: "%{pluralized_errors} prohibited this %{resource_name} from being saved:"
|
26
26
|
search:
|
27
27
|
clear: 清除搜索
|
28
28
|
label: 搜索 %{resource}
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# Authorization
|
2
|
+
|
3
|
+
The default configuration of Administrate is "authenticate-only" - once a
|
4
|
+
user is authenticated, that user has access to every action of every object.
|
5
|
+
|
6
|
+
You can add more fine-grained authorization by overriding methods in the
|
7
|
+
controller.
|
8
|
+
|
9
|
+
## Using Pundit
|
10
|
+
|
11
|
+
If your app already uses [Pundit](https://github.com/elabs/pundit) for
|
12
|
+
authorization, you just need to add one line to your
|
13
|
+
`Admin::ApplicationController`:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
include Administrate::Punditize
|
17
|
+
```
|
18
|
+
|
19
|
+
This will use all the policies from your main app to determine if the
|
20
|
+
current user is able to view a given record or perform a given action.
|
21
|
+
|
22
|
+
### Further limiting scope
|
23
|
+
|
24
|
+
You may want to limit the scope for a given user beyond what they
|
25
|
+
technically have access to see in the main app. For example, a user may
|
26
|
+
have all public records in their scope, but you want to only show *their*
|
27
|
+
records in the admin interface to reduce confusion.
|
28
|
+
|
29
|
+
In this case, you can add an additional `resolve_admin` to your policy's
|
30
|
+
scope and Administrate will use this instead of the `resolve` method.
|
31
|
+
|
32
|
+
For example:
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
class PostPolicy < ApplicationPolicy
|
36
|
+
class Scope < Scope
|
37
|
+
def resolve
|
38
|
+
scope.all
|
39
|
+
end
|
40
|
+
|
41
|
+
def resolve_admin
|
42
|
+
scope.where(owner: user)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
## Authorization without Pundit
|
49
|
+
|
50
|
+
If you use a different authorization library, or you want to roll your own,
|
51
|
+
you just need to override a few methods in your controllers or
|
52
|
+
`Admin::ApplicationController`. For example:
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
# Limit the scope of the given resource
|
56
|
+
def scoped_resource
|
57
|
+
super.where(user: current_user)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Raise an exception if the user is not permitted to access this resource
|
61
|
+
def authorize_resource(resource)
|
62
|
+
raise "Erg!" unless show_action?(params[:action], resource)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Hide links to actions if the user is not allowed to do them
|
66
|
+
def show_action?(action, resource)
|
67
|
+
current_user.can? action, resource
|
68
|
+
end
|
69
|
+
```
|
@@ -1,7 +1,20 @@
|
|
1
1
|
# Customizing attribute partials
|
2
2
|
|
3
3
|
Occasionally you might want to change how specific types of attributes appear
|
4
|
-
across all dashboards.
|
4
|
+
across all dashboards. You can customize the following built in field types:
|
5
|
+
|
6
|
+
- `belongs_to`
|
7
|
+
- `boolean`
|
8
|
+
- `date_time`
|
9
|
+
- `email`
|
10
|
+
- `has_many`
|
11
|
+
- `has_one`
|
12
|
+
- `number`
|
13
|
+
- `polymporphic`
|
14
|
+
- `select`
|
15
|
+
- `string`
|
16
|
+
- `text`
|
17
|
+
|
5
18
|
For example, you might want all `Number` values to round to three decimal points.
|
6
19
|
|
7
20
|
To get started, run the appropriate rails generator:
|
@@ -16,6 +29,12 @@ This will generate three files:
|
|
16
29
|
- `app/view/fields/number/_index.html.erb`
|
17
30
|
- `app/view/fields/number/_show.html.erb`
|
18
31
|
|
32
|
+
You can generate the partials for all field types by passing `all` to the generator.
|
33
|
+
|
34
|
+
```bash
|
35
|
+
rails generate administrate:views:field all
|
36
|
+
```
|
37
|
+
|
19
38
|
The generated templates will have documentation
|
20
39
|
describing which variables are in scope.
|
21
40
|
The rendering part of the partial will look like:
|
@@ -70,6 +70,16 @@ specify, including:
|
|
70
70
|
Each of the `Field` types take a different set of options,
|
71
71
|
which are specified through the `.with_options` class method:
|
72
72
|
|
73
|
+
**Field::BelongsTo**
|
74
|
+
|
75
|
+
`:order` - Specifies the order of the dropdown menu, can be ordered by more
|
76
|
+
than one column. e.g.: `"name, email DESC"`.
|
77
|
+
|
78
|
+
`:primary_key` - Specifies object's primary_key. Defaults to `:id`.
|
79
|
+
|
80
|
+
`:foreign_key` - Specifies the name of the foreign key directly.
|
81
|
+
Defaults to `:#{attribute}_id`.
|
82
|
+
|
73
83
|
**Field::HasMany**
|
74
84
|
|
75
85
|
`:limit` - Set the number of resources to display in the show view. Default is
|
@@ -79,6 +89,10 @@ which are specified through the `.with_options` class method:
|
|
79
89
|
|
80
90
|
`:direction` - What direction the sort should be in, `:asc` (default) or `:desc`.
|
81
91
|
|
92
|
+
`:primary_key` - Specifies object's primary_key. Defaults to `:id`.
|
93
|
+
|
94
|
+
`:foreign_key` - Specifies the name of the foreign key directly. Defaults to `:#{attribute}_id`
|
95
|
+
|
82
96
|
**Field::Number**
|
83
97
|
|
84
98
|
`:decimals` - Set the number of decimals to display. Defaults to `0`.
|
@@ -105,6 +119,22 @@ Or, to display a distance in kilometers:
|
|
105
119
|
)
|
106
120
|
```
|
107
121
|
|
122
|
+
**Field::Polymorphic**
|
123
|
+
|
124
|
+
`:classes` - Specify a list of classes whose objects will be used to populate select boxes for editing this polymorphic field.
|
125
|
+
Default is `[]`.
|
126
|
+
|
127
|
+
`:order` - What to sort the association by in the form select.
|
128
|
+
Default is `nil`.
|
129
|
+
|
130
|
+
**Field::DateTime**
|
131
|
+
|
132
|
+
`:format` - Specify what format, using `strftime` you would like `DateTime`
|
133
|
+
objects to display as.
|
134
|
+
|
135
|
+
`:timezone` - Specify which timezone `Date` and `DateTime` objects are based
|
136
|
+
in.
|
137
|
+
|
108
138
|
**Field::Select**
|
109
139
|
|
110
140
|
`:collection` - Specify the array or range to select from. Defaults to `[]`.
|
@@ -157,3 +187,27 @@ end
|
|
157
187
|
````
|
158
188
|
|
159
189
|
[define your own]: /adding_custom_field_types
|
190
|
+
|
191
|
+
To change the dashboard name in sidebar menu, sub-header and search string use default ActiveRecord i18n translations for models:
|
192
|
+
|
193
|
+
```yaml
|
194
|
+
en:
|
195
|
+
activerecord:
|
196
|
+
models:
|
197
|
+
customer:
|
198
|
+
one: Happy Customer
|
199
|
+
others: Happy Customers
|
200
|
+
```
|
201
|
+
|
202
|
+
## Customizing Actions
|
203
|
+
|
204
|
+
To enable or disable certain actions you could override `valid_action?` method in your dashboard controller like this:
|
205
|
+
|
206
|
+
```ruby
|
207
|
+
# disable 'edit' and 'destroy' links
|
208
|
+
def valid_action?(name, resource = resource_class)
|
209
|
+
%w[edit destroy].exclude?(name.to_s) && super
|
210
|
+
end
|
211
|
+
```
|
212
|
+
|
213
|
+
Action is one of `new`, `edit`, `show`, `destroy`.
|
data/docs/getting_started.md
CHANGED
@@ -29,6 +29,20 @@ The `Admin::ApplicationController` can be customized to add
|
|
29
29
|
authentication logic, authorization, pagination,
|
30
30
|
or other controller-level concerns.
|
31
31
|
|
32
|
+
You will also want to add a `root` route to show a dashboard when you go to `/admin`.
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
Rails.application.routes.draw do
|
36
|
+
namespace :admin do
|
37
|
+
# Add dashboard for your models here
|
38
|
+
resources :customers,
|
39
|
+
resources :orders
|
40
|
+
|
41
|
+
root to: "customers#index" # <--- Root route
|
42
|
+
end
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
32
46
|
The routes can be customized to show or hide
|
33
47
|
different models on the dashboard.
|
34
48
|
|
@@ -59,10 +73,54 @@ namespace :admin do
|
|
59
73
|
end
|
60
74
|
```
|
61
75
|
|
76
|
+
## Keep Dashboards Updated as Model Attributes Change
|
77
|
+
|
78
|
+
If you've installed Administrate and generated dashboards and _then_
|
79
|
+
subsequently added attributes to your models you'll need to manually add
|
80
|
+
these additions (or removals) to your dashboards.
|
81
|
+
|
82
|
+
Example:
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
# app/dashboards/your_model_dashboard.rb
|
86
|
+
|
87
|
+
ATTRIBUTE_TYPES = {
|
88
|
+
# ...
|
89
|
+
the_new_attribute: Field::String,
|
90
|
+
# ...
|
91
|
+
}.freeze
|
92
|
+
|
93
|
+
SHOW_PAGE_ATTRIBUTES = [
|
94
|
+
# ...
|
95
|
+
:the_new_attribute,
|
96
|
+
# ...
|
97
|
+
].freeze
|
98
|
+
|
99
|
+
FORM_ATTRIBUTES = [
|
100
|
+
# ...
|
101
|
+
:the_new_attribute,
|
102
|
+
# ...
|
103
|
+
].freeze
|
104
|
+
|
105
|
+
COLLECTION_ATTRIBUTES = [
|
106
|
+
# ...
|
107
|
+
:the_new_attribute, # if you want it on the index, also.
|
108
|
+
# ...
|
109
|
+
].freeze
|
110
|
+
```
|
111
|
+
|
112
|
+
It's recommended that you make this change at the same time as you add the
|
113
|
+
attribute to the model.
|
114
|
+
|
115
|
+
The alternative way to handle this is to re-run `rails g administrate:install` and
|
116
|
+
carefully pick through the diffs. This latter method is probably more cumbersome.
|
117
|
+
|
62
118
|
## Rails API
|
63
119
|
|
64
120
|
Since Rails 5.0, we've been able to have API only applications. Yet, sometimes
|
65
|
-
we still want to have an admin.
|
121
|
+
we still want to have an admin.
|
122
|
+
|
123
|
+
To get this working, we recommend updating this config:
|
66
124
|
|
67
125
|
```ruby
|
68
126
|
# config/application.rb
|
@@ -74,3 +132,26 @@ also don't use your `ApplicationController`. Instead, Administrate provides its
|
|
74
132
|
own. Meaning you're free to specify `ActionController::API` as your parent
|
75
133
|
controller to make sure no flash, session, or cookie middleware is used by your
|
76
134
|
API.
|
135
|
+
|
136
|
+
Alternatively, if your application needs to have `config.api_only = true`, we recommend you add the following lines to your `config/application.rb`
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
# Enable Flash, Cookies, MethodOverride for Administrate Gem
|
140
|
+
config.middleware.use ActionDispatch::Flash
|
141
|
+
config.session_store :cookie_store
|
142
|
+
config.middleware.use ActionDispatch::Cookies
|
143
|
+
config.middleware.use ActionDispatch::Session::CookieStore, config.session_options
|
144
|
+
config.middleware.use ::Rack::MethodOverride
|
145
|
+
```
|
146
|
+
|
147
|
+
You must also ensure that the all the required controller actions are available and accessible as routes since generators in API-only applications only generate some of the required actions. Here is an example:
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
# routes.rb
|
151
|
+
namespace :admin do
|
152
|
+
resources name, only: %i(index show new create edit update destroy)
|
153
|
+
end
|
154
|
+
|
155
|
+
# names_controller.rb
|
156
|
+
# Ensure each of those methods are defined
|
157
|
+
```
|
@@ -3,12 +3,12 @@ require_relative "associative"
|
|
3
3
|
module Administrate
|
4
4
|
module Field
|
5
5
|
class BelongsTo < Associative
|
6
|
-
def self.permitted_attribute(attr)
|
6
|
+
def self.permitted_attribute(attr, _options = nil)
|
7
7
|
:"#{attr}_id"
|
8
8
|
end
|
9
9
|
|
10
10
|
def permitted_attribute
|
11
|
-
|
11
|
+
foreign_key
|
12
12
|
end
|
13
13
|
|
14
14
|
def associated_resource_options
|
@@ -24,7 +24,8 @@ module Administrate
|
|
24
24
|
private
|
25
25
|
|
26
26
|
def candidate_resources
|
27
|
-
|
27
|
+
order = options.delete(:order)
|
28
|
+
order ? associated_class.order(order) : associated_class.all
|
28
29
|
end
|
29
30
|
|
30
31
|
def display_candidate_resource(resource)
|
@@ -4,11 +4,18 @@ module Administrate
|
|
4
4
|
module Field
|
5
5
|
class DateTime < Base
|
6
6
|
def date
|
7
|
-
I18n.localize(
|
7
|
+
I18n.localize(
|
8
|
+
data.in_time_zone(timezone).to_date,
|
9
|
+
format: format,
|
10
|
+
)
|
8
11
|
end
|
9
12
|
|
10
13
|
def datetime
|
11
|
-
I18n.localize(
|
14
|
+
I18n.localize(
|
15
|
+
data.in_time_zone(timezone),
|
16
|
+
format: format,
|
17
|
+
default: data,
|
18
|
+
)
|
12
19
|
end
|
13
20
|
|
14
21
|
private
|
@@ -16,6 +23,10 @@ module Administrate
|
|
16
23
|
def format
|
17
24
|
options.fetch(:format, :default)
|
18
25
|
end
|
26
|
+
|
27
|
+
def timezone
|
28
|
+
options.fetch(:timezone, "UTC")
|
29
|
+
end
|
19
30
|
end
|
20
31
|
end
|
21
32
|
end
|
@@ -25,11 +25,12 @@ module Administrate
|
|
25
25
|
options.fetch(:searchable, deferred_class.searchable?)
|
26
26
|
end
|
27
27
|
|
28
|
-
|
29
|
-
:
|
30
|
-
|
31
|
-
|
32
|
-
|
28
|
+
def permitted_attribute(attr, _options = nil)
|
29
|
+
options.fetch(:foreign_key,
|
30
|
+
deferred_class.permitted_attribute(attr, options))
|
31
|
+
end
|
32
|
+
|
33
|
+
delegate :html_class, to: :deferred_class
|
33
34
|
end
|
34
35
|
end
|
35
36
|
end
|
@@ -7,8 +7,8 @@ module Administrate
|
|
7
7
|
class HasMany < Associative
|
8
8
|
DEFAULT_LIMIT = 5
|
9
9
|
|
10
|
-
def self.permitted_attribute(
|
11
|
-
{ "#{
|
10
|
+
def self.permitted_attribute(attr, _options = nil)
|
11
|
+
{ "#{attr.to_s.singularize}_ids".to_sym => [] }
|
12
12
|
end
|
13
13
|
|
14
14
|
def associated_collection
|
@@ -3,25 +3,33 @@ require_relative "associative"
|
|
3
3
|
module Administrate
|
4
4
|
module Field
|
5
5
|
class HasOne < Associative
|
6
|
-
def
|
7
|
-
|
8
|
-
@nested_form = Administrate::Page::Form.new(
|
6
|
+
def nested_form
|
7
|
+
@nested_form ||= Administrate::Page::Form.new(
|
9
8
|
resolver.dashboard_class.new,
|
10
9
|
data || resolver.resource_class.new,
|
11
10
|
)
|
12
|
-
|
13
|
-
super
|
14
11
|
end
|
15
12
|
|
16
|
-
def self.permitted_attribute(attr)
|
13
|
+
def self.permitted_attribute(attr, options = nil)
|
14
|
+
associated_class_name =
|
15
|
+
if options
|
16
|
+
options.fetch(:class_name, attr.to_s.singularize.camelcase)
|
17
|
+
else
|
18
|
+
attr
|
19
|
+
end
|
17
20
|
related_dashboard_attributes =
|
18
|
-
Administrate::ResourceResolver.new("admin/#{
|
21
|
+
Administrate::ResourceResolver.new("admin/#{associated_class_name}").
|
19
22
|
dashboard_class.new.permitted_attributes + [:id]
|
20
23
|
|
21
24
|
{ "#{attr}_attributes": related_dashboard_attributes }
|
22
25
|
end
|
23
26
|
|
24
|
-
|
27
|
+
private
|
28
|
+
|
29
|
+
def resolver
|
30
|
+
@resolver ||=
|
31
|
+
Administrate::ResourceResolver.new("admin/#{associated_class_name}")
|
32
|
+
end
|
25
33
|
end
|
26
34
|
end
|
27
35
|
end
|