administrate 0.13.0 → 0.17.0
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/associative.js +5 -0
- data/app/assets/stylesheets/administrate/base/_tables.scss +3 -0
- data/app/assets/stylesheets/administrate/components/_attributes.scss +3 -2
- data/app/assets/stylesheets/administrate/components/_buttons.scss +3 -0
- data/app/assets/stylesheets/administrate/components/_field-unit.scss +4 -0
- data/app/assets/stylesheets/administrate/components/_flashes.scss +0 -8
- data/app/assets/stylesheets/administrate/components/_main-content.scss +1 -0
- data/app/assets/stylesheets/administrate/library/_variables.scss +10 -8
- data/app/controllers/administrate/application_controller.rb +47 -13
- data/app/helpers/administrate/application_helper.rb +27 -28
- data/app/views/administrate/application/_collection.html.erb +24 -26
- data/app/views/administrate/application/_collection_header_actions.html.erb +4 -0
- data/app/views/administrate/application/_collection_item_actions.html.erb +17 -0
- data/app/views/administrate/application/_flashes.html.erb +1 -0
- data/app/views/administrate/application/_form.html.erb +2 -2
- data/app/views/administrate/application/_icons.html.erb +1 -1
- data/app/views/administrate/application/_index_header.html.erb +28 -0
- data/app/views/administrate/application/_navigation.html.erb +4 -4
- data/app/views/administrate/application/index.html.erb +9 -29
- data/app/views/administrate/application/show.html.erb +1 -1
- data/app/views/fields/belongs_to/_form.html.erb +3 -3
- data/app/views/fields/belongs_to/_index.html.erb +1 -1
- data/app/views/fields/belongs_to/_show.html.erb +1 -1
- data/app/views/fields/has_one/_index.html.erb +1 -1
- data/app/views/fields/has_one/_show.html.erb +4 -4
- data/app/views/fields/number/_form.html.erb +1 -1
- data/app/views/fields/polymorphic/_show.html.erb +1 -1
- data/app/views/fields/select/_form.html.erb +23 -9
- data/app/views/fields/time/_form.html.erb +3 -2
- data/app/views/fields/time/_index.html.erb +3 -1
- data/app/views/fields/time/_show.html.erb +3 -1
- data/app/views/fields/url/_index.html.erb +1 -1
- data/app/views/fields/url/_show.html.erb +1 -1
- data/app/views/layouts/administrate/application.html.erb +1 -0
- data/config/locales/administrate.ar.yml +2 -0
- data/config/locales/administrate.bs.yml +2 -0
- data/config/locales/administrate.ca.yml +2 -0
- data/config/locales/administrate.da.yml +2 -0
- data/config/locales/administrate.de.yml +2 -0
- data/config/locales/administrate.en.yml +2 -0
- data/config/locales/administrate.es.yml +2 -0
- data/config/locales/administrate.fi.yml +30 -0
- data/config/locales/administrate.fr.yml +4 -2
- data/config/locales/administrate.id.yml +2 -0
- data/config/locales/administrate.it.yml +2 -0
- data/config/locales/administrate.ja.yml +2 -0
- data/config/locales/administrate.ko.yml +2 -0
- data/config/locales/administrate.nl.yml +7 -5
- data/config/locales/administrate.pl.yml +2 -0
- data/config/locales/administrate.pt-BR.yml +4 -2
- data/config/locales/administrate.pt.yml +4 -2
- data/config/locales/administrate.ru.yml +2 -0
- data/config/locales/{administrate.al.yml → administrate.sq.yml} +3 -1
- data/config/locales/administrate.sv.yml +2 -0
- data/config/locales/administrate.tr.yml +30 -0
- data/config/locales/administrate.uk.yml +2 -0
- data/config/locales/administrate.vi.yml +2 -0
- data/config/locales/administrate.zh-CN.yml +2 -0
- data/config/locales/administrate.zh-TW.yml +2 -0
- data/config/unicorn.rb +8 -13
- data/docs/adding_controllers_without_related_model.md +52 -0
- data/docs/customizing_controller_actions.md +32 -0
- data/docs/customizing_dashboards.md +81 -23
- data/docs/customizing_page_views.md +15 -3
- data/docs/extending_administrate.md +27 -0
- data/docs/getting_started.md +27 -5
- data/docs/guides/hiding_dashboards_from_sidebar.md +19 -0
- data/docs/guides.md +5 -0
- data/lib/administrate/base_dashboard.rb +34 -12
- data/lib/administrate/custom_dashboard.rb +15 -0
- data/lib/administrate/engine.rb +7 -0
- data/lib/administrate/field/associative.rb +49 -5
- data/lib/administrate/field/base.rb +30 -0
- data/lib/administrate/field/belongs_to.rb +13 -3
- data/lib/administrate/field/deferred.rb +22 -3
- data/lib/administrate/field/has_many.rb +15 -2
- data/lib/administrate/field/has_one.rb +28 -8
- data/lib/administrate/field/number.rb +19 -2
- data/lib/administrate/field/polymorphic.rb +2 -2
- data/lib/administrate/field/select.rb +10 -1
- data/lib/administrate/field/time.rb +11 -0
- data/lib/administrate/namespace.rb +5 -1
- data/lib/administrate/order.rb +3 -1
- data/lib/administrate/page/base.rb +1 -1
- data/lib/administrate/page/form.rb +10 -3
- data/lib/administrate/resource_resolver.rb +2 -2
- data/lib/administrate/search.rb +47 -36
- data/lib/administrate/version.rb +1 -1
- data/lib/administrate/view_generator.rb +7 -1
- data/lib/administrate.rb +19 -0
- data/lib/generators/administrate/dashboard/dashboard_generator.rb +18 -14
- data/lib/generators/administrate/dashboard/templates/controller.rb.erb +2 -2
- data/lib/generators/administrate/dashboard/templates/dashboard.rb.erb +3 -3
- data/lib/generators/administrate/install/install_generator.rb +37 -1
- data/lib/generators/administrate/install/templates/application_controller.rb.erb +1 -1
- data/lib/generators/administrate/routes/routes_generator.rb +3 -13
- data/lib/generators/administrate/views/views_generator.rb +5 -4
- metadata +25 -44
- data/app/assets/javascripts/administrate/components/has_many_form.js +0 -3
- data/docs/contributing.md +0 -1
@@ -8,9 +8,9 @@ edit the dashboard file generated by the installation generator.
|
|
8
8
|
By default, the file will look something like this:
|
9
9
|
|
10
10
|
```ruby
|
11
|
-
require "administrate/
|
11
|
+
require "administrate/base_dashboard"
|
12
12
|
|
13
|
-
class CustomerDashboard < Administrate::
|
13
|
+
class CustomerDashboard < Administrate::BaseDashboard
|
14
14
|
ATTRIBUTE_TYPES = {
|
15
15
|
id: Field::Number,
|
16
16
|
name: Field::String,
|
@@ -65,6 +65,7 @@ specify, including:
|
|
65
65
|
- `Field::Select`
|
66
66
|
- `Field::String`
|
67
67
|
- `Field::Text`
|
68
|
+
- `Field::Url`
|
68
69
|
- `Field::Password`
|
69
70
|
|
70
71
|
## Customizing Fields
|
@@ -79,21 +80,16 @@ which are specified through the `.with_options` class method:
|
|
79
80
|
`:order` - Specifies the order of the dropdown menu, can be ordered by more
|
80
81
|
than one column. e.g.: `"name, email DESC"`.
|
81
82
|
|
82
|
-
`:primary_key` - Specifies object's primary_key. Defaults to `:id`.
|
83
|
-
|
84
|
-
`:foreign_key` - Specifies the name of the foreign key directly.
|
85
|
-
Defaults to `:#{attribute}_id`.
|
86
|
-
|
87
83
|
`:scope` - Specifies a custom scope inside a callable. Useful for preloading.
|
88
84
|
Example: `.with_options(scope: -> { MyModel.includes(:rel).limit(5) })`
|
89
85
|
|
90
|
-
`:
|
91
|
-
|
86
|
+
`:include_blank` - Specifies if the select element to be rendered should include
|
87
|
+
blank option. Default is `true`.
|
92
88
|
|
93
89
|
`:searchable` - Specify if the attribute should be considered when searching.
|
94
90
|
Default is `false`.
|
95
91
|
|
96
|
-
`
|
92
|
+
`searchable_fields` - Specify which columns to use on the search, only applies
|
97
93
|
if `searchable` is `true`
|
98
94
|
|
99
95
|
For example:
|
@@ -101,13 +97,19 @@ For example:
|
|
101
97
|
```ruby
|
102
98
|
country: Field::BelongsTo.with_options(
|
103
99
|
searchable: true,
|
104
|
-
|
100
|
+
searchable_fields: ['name'],
|
105
101
|
)
|
106
102
|
```
|
107
103
|
|
108
104
|
with this, you will be able to search through the column `name` from the
|
109
105
|
association `belongs_to :country`, from your model.
|
110
106
|
|
107
|
+
`:primary_key` (deprecated) - Specifies the association's primary_key.
|
108
|
+
|
109
|
+
`:foreign_key` (deprecated) - Specifies the name of the foreign key directly.
|
110
|
+
|
111
|
+
`:class_name` (deprecated) - Specifies the name of the associated class.
|
112
|
+
|
111
113
|
**Field::HasMany**
|
112
114
|
|
113
115
|
`:limit` - Set the number of resources to display in the show view. Default is
|
@@ -117,22 +119,18 @@ association `belongs_to :country`, from your model.
|
|
117
119
|
|
118
120
|
`:direction` - What direction the sort should be in, `:asc` (default) or `:desc`.
|
119
121
|
|
120
|
-
`:primary_key` - Specifies object's primary_key.
|
122
|
+
`:primary_key` (deprecated) - Specifies object's primary_key.
|
121
123
|
|
122
|
-
`:foreign_key` - Specifies the name of the foreign key directly.
|
124
|
+
`:foreign_key` (deprecated) - Specifies the name of the foreign key directly.
|
123
125
|
|
124
|
-
`:class_name` - Specifies the name of the associated class.
|
125
|
-
Defaults to `:#{attribute}.to_s.singularize.camelcase`.
|
126
|
+
`:class_name` (deprecated) - Specifies the name of the associated class.
|
126
127
|
|
127
128
|
**Field::HasOne**
|
128
129
|
|
129
|
-
`:class_name` - Specifies the name of the associated class.
|
130
|
-
Defaults to `:#{attribute}.to_s.singularize.camelcase`.
|
131
|
-
|
132
130
|
`:searchable` - Specify if the attribute should be considered when searching.
|
133
131
|
Default is `false`.
|
134
132
|
|
135
|
-
`
|
133
|
+
`searchable_fields` - Specify which columns to use on the search, only applies if
|
136
134
|
`searchable` is `true`
|
137
135
|
|
138
136
|
For example:
|
@@ -140,13 +138,15 @@ For example:
|
|
140
138
|
```ruby
|
141
139
|
cities: Field::HasMany.with_options(
|
142
140
|
searchable: true,
|
143
|
-
|
141
|
+
searchable_fields: ['name'],
|
144
142
|
)
|
145
143
|
```
|
146
144
|
|
147
145
|
with this, you will be able to search through the column `name` from the
|
148
146
|
association `has_many :cities`, from your model.
|
149
147
|
|
148
|
+
`:class_name` (deprecated) - Specifies the name of the associated class.
|
149
|
+
|
150
150
|
**Field::Number**
|
151
151
|
|
152
152
|
`:searchable` - Specify if the attribute should be considered when searching.
|
@@ -159,6 +159,13 @@ more results than expected. Default is `false`.
|
|
159
159
|
|
160
160
|
`:suffix` - Suffixes the number with a string. Defaults to `""`.
|
161
161
|
|
162
|
+
`:format` - Specify a hash which defines a formatter. This uses ActiveSupport
|
163
|
+
and works by by passing a hash that includes the formatter (`formatter`) and
|
164
|
+
the options for the formatter (`formatter_options`). Defaults to the locale's
|
165
|
+
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.
|
168
|
+
|
162
169
|
For example, you might use the following to display U.S. currency:
|
163
170
|
|
164
171
|
```ruby
|
@@ -166,15 +173,25 @@ For example, you might use the following to display U.S. currency:
|
|
166
173
|
prefix: "$",
|
167
174
|
decimals: 2,
|
168
175
|
)
|
176
|
+
|
177
|
+
# "$5.99"
|
169
178
|
```
|
170
179
|
|
171
|
-
Or, to display a distance in kilometers:
|
180
|
+
Or, to display a distance in kilometers, using a space as the delimiter:
|
172
181
|
|
173
182
|
```ruby
|
174
|
-
|
183
|
+
distance: Field::Number.with_options(
|
175
184
|
suffix: " km",
|
176
185
|
decimals: 2,
|
186
|
+
format: {
|
187
|
+
formatter: :number_to_delimited,
|
188
|
+
formatter_options: {
|
189
|
+
delimiter: ' ',
|
190
|
+
},
|
191
|
+
},
|
177
192
|
)
|
193
|
+
|
194
|
+
# "2 000.00 km"
|
178
195
|
```
|
179
196
|
|
180
197
|
**Field::Polymorphic**
|
@@ -200,11 +217,15 @@ objects to display as.
|
|
200
217
|
|
201
218
|
**Field::Select**
|
202
219
|
|
203
|
-
`:collection` - Specify the
|
220
|
+
`:collection` - Specify the options shown on the select field. It accept either
|
221
|
+
an array or an object responding to `:call`. Defaults to `[]`.
|
204
222
|
|
205
223
|
`:searchable` - Specify if the attribute should be considered when searching.
|
206
224
|
Default is `true`.
|
207
225
|
|
226
|
+
`:include_blank` - Specifies if the select element to be rendered should include
|
227
|
+
blank option. Default is `false`.
|
228
|
+
|
208
229
|
**Field::String**
|
209
230
|
|
210
231
|
`:searchable` - Specify if the attribute should be considered when searching.
|
@@ -221,6 +242,14 @@ Default is `false`.
|
|
221
242
|
`:truncate` - Set the number of characters to display in the index view.
|
222
243
|
Defaults to `50`.
|
223
244
|
|
245
|
+
**Field::Url**
|
246
|
+
|
247
|
+
`:searchable` - Specify if the attribute should be considered when searching.
|
248
|
+
Default is `true`.
|
249
|
+
|
250
|
+
`:truncate` - Set the number of characters to display in the index view.
|
251
|
+
Defaults to `50`.
|
252
|
+
|
224
253
|
**Field::Password**
|
225
254
|
|
226
255
|
`:searchable` - Specify if the attribute should be considered when searching.
|
@@ -300,3 +329,32 @@ COLLECTION_FILTERS = {
|
|
300
329
|
inactive: ->(resources) { resources.inactive }
|
301
330
|
}
|
302
331
|
```
|
332
|
+
|
333
|
+
You can also define a filter with parameters:
|
334
|
+
|
335
|
+
```ruby
|
336
|
+
COLLECTION_FILTERS = {
|
337
|
+
state: ->(resources, attr) { resources.where(state: attr) }
|
338
|
+
}
|
339
|
+
```
|
340
|
+
|
341
|
+
You can now search your resource with 'state:open' and your
|
342
|
+
collection filter Proc will be called with with attr = open.
|
343
|
+
|
344
|
+
## Form Attributes
|
345
|
+
|
346
|
+
You can define different attributes for new/create or edit/update actions:
|
347
|
+
|
348
|
+
```ruby
|
349
|
+
FORM_ATTRIBUTES_NEW = [
|
350
|
+
:name,
|
351
|
+
:email
|
352
|
+
]
|
353
|
+
FORM_ATTRIBUTES_EDIT = [
|
354
|
+
:name,
|
355
|
+
:email,
|
356
|
+
:orders
|
357
|
+
]
|
358
|
+
```
|
359
|
+
|
360
|
+
Or for custom action with constant name `"FORM_ATTRIBUTES_#{action.upcase}"`
|
@@ -2,12 +2,24 @@
|
|
2
2
|
title: Customizing page views
|
3
3
|
---
|
4
4
|
|
5
|
-
|
6
|
-
you can
|
5
|
+
You can provide replacements for any of Administrate's templates.
|
6
|
+
This way you can change the appearance of any page or element of
|
7
|
+
the interface.
|
8
|
+
|
9
|
+
In general, you can override any of the views under Administrate's
|
10
|
+
[/app/views][1].
|
11
|
+
For example, say that you want to customize the template used for flash
|
12
|
+
messages. You can provide your own as
|
13
|
+
`/app/views/administrate/application/_flashes.html.erb`, and it will replace
|
14
|
+
Administrate's own.
|
15
|
+
|
16
|
+
Figuring out which views are available and where can be repetitive. You can
|
17
|
+
spare yourself some effort by using the built-in view generators.
|
18
|
+
|
19
|
+
[1]: https://github.com/thoughtbot/administrate/tree/master/app/views
|
7
20
|
|
8
21
|
## Customizing for all resources
|
9
22
|
|
10
|
-
The easiest way to get started is by using the built-in generators.
|
11
23
|
In order to change the appearance of views for all resource types,
|
12
24
|
call the generators with no arguments.
|
13
25
|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
---
|
2
|
+
title: Extending Administrate
|
3
|
+
---
|
4
|
+
|
5
|
+
Apart from the configuration described in these pages, it is possible to
|
6
|
+
extend Administrate's capabilities with the use of plugins. There are a
|
7
|
+
number of plugins available, many of which can be found at [RubyGems.org].
|
8
|
+
These are some popular examples:
|
9
|
+
|
10
|
+
1. [ActiveStorage support](https://github.com/Dreamersoul/administrate-field-active_storage)
|
11
|
+
2. [Enum field](https://github.com/Valiot/administrate-field-enum)
|
12
|
+
3. [Nested has-many forms](https://github.com/nickcharlton/administrate-field-nested_has_many)
|
13
|
+
4. [Belongs-to with Ajax search](https://github.com/fishbrain/administrate-field-belongs_to_search)
|
14
|
+
5. [JSONb field plugin for Administrate](https://github.com/codica2/administrate-field-jsonb/)
|
15
|
+
|
16
|
+
See many more at https://rubygems.org/gems/administrate/reverse_dependencies.
|
17
|
+
|
18
|
+
Please note that these plugins are written by third parties. We do not
|
19
|
+
have any control over them, and we cannot give any assurances as to how
|
20
|
+
well they perform their advertised functions.
|
21
|
+
|
22
|
+
You can write your own plugins too! We don't document this specifically,
|
23
|
+
but you can have a look at the existing plugins for some directions.
|
24
|
+
In general, Administrate tries to abide by Rails's conventions, so that
|
25
|
+
hopefully should help!
|
26
|
+
|
27
|
+
[RubyGems.org]: https://rubygems.org
|
data/docs/getting_started.md
CHANGED
@@ -3,16 +3,16 @@ 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
|
6
|
+
applications version 5.0 or greater. We support Ruby 2.6 and up.
|
7
7
|
|
8
|
-
|
8
|
+
First, add the following to your Gemfile:
|
9
9
|
|
10
10
|
```ruby
|
11
11
|
# Gemfile
|
12
12
|
gem "administrate"
|
13
13
|
```
|
14
14
|
|
15
|
-
Re-bundle
|
15
|
+
Re-bundle with `bundle install`, then run the installer:
|
16
16
|
|
17
17
|
```bash
|
18
18
|
$ rails generate administrate:install
|
@@ -37,7 +37,7 @@ You will also want to add a `root` route to show a dashboard when you go to `/ad
|
|
37
37
|
Rails.application.routes.draw do
|
38
38
|
namespace :admin do
|
39
39
|
# Add dashboard for your models here
|
40
|
-
resources :customers
|
40
|
+
resources :customers
|
41
41
|
resources :orders
|
42
42
|
|
43
43
|
root to: "customers#index" # <--- Root route
|
@@ -56,6 +56,28 @@ Each `Admin::FooController` can be overwritten to specify custom behavior.
|
|
56
56
|
Once you have Administrate installed,
|
57
57
|
visit <http://localhost:3000/admin> to see your new dashboard in action.
|
58
58
|
|
59
|
+
### Errors about assets?
|
60
|
+
|
61
|
+
If your apps uses Sprockets 4, you'll need to add Administrate's assets to
|
62
|
+
your `manifest.js` file. To do this, add these two lines to the file:
|
63
|
+
|
64
|
+
```
|
65
|
+
//= link administrate/application.css
|
66
|
+
//= link administrate/application.js
|
67
|
+
```
|
68
|
+
|
69
|
+
Otherwise, your app will show you this error:
|
70
|
+
|
71
|
+
```
|
72
|
+
Asset `administrate/application.css` was not declared to be precompiled in production.
|
73
|
+
Declare links to your assets in `app/assets/config/manifest.js`.
|
74
|
+
```
|
75
|
+
|
76
|
+
For more information on why this is necessary, see Richard Schneeman's article
|
77
|
+
["Self Hosted Config: Introducing the Sprockets manifest.js"][]
|
78
|
+
|
79
|
+
[schneems]: https://www.schneems.com/2017/11/22/self-hosted-config-introducing-the-sprockets-manifestjs
|
80
|
+
|
59
81
|
## Create Additional Dashboards
|
60
82
|
|
61
83
|
In order to create additional dashboards, pass in the resource name to
|
@@ -65,7 +87,7 @@ the dashboard generator. A dashboard and controller will be created.
|
|
65
87
|
$ rails generate administrate:dashboard Foo
|
66
88
|
```
|
67
89
|
|
68
|
-
|
90
|
+
Then add a route for the new dashboard.
|
69
91
|
|
70
92
|
```ruby
|
71
93
|
# config/routes.rb
|
@@ -0,0 +1,19 @@
|
|
1
|
+
---
|
2
|
+
title: Hiding Dashboards from the Sidebar
|
3
|
+
---
|
4
|
+
|
5
|
+
Resources can be removed form the sidebar by removing their index action from the routes. For example:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
# config/routes.rb
|
9
|
+
Rails.application.routes.draw do
|
10
|
+
namespace :admin do
|
11
|
+
resources :line_items, except: :index
|
12
|
+
resources :orders
|
13
|
+
resources :products
|
14
|
+
root to: "customers#index"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
```
|
18
|
+
|
19
|
+
In this case, only Orders and Products will appear in the sidebar, while Line Items can still appear as an association.
|
data/docs/guides.md
ADDED
@@ -18,6 +18,18 @@ module Administrate
|
|
18
18
|
class BaseDashboard
|
19
19
|
include Administrate
|
20
20
|
|
21
|
+
DASHBOARD_SUFFIX = "Dashboard".freeze
|
22
|
+
|
23
|
+
class << self
|
24
|
+
def model
|
25
|
+
to_s.chomp(DASHBOARD_SUFFIX).classify.constantize
|
26
|
+
end
|
27
|
+
|
28
|
+
def resource_name(opts)
|
29
|
+
model.model_name.human(opts)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
21
33
|
def attribute_types
|
22
34
|
self.class::ATTRIBUTE_TYPES
|
23
35
|
end
|
@@ -38,13 +50,24 @@ module Administrate
|
|
38
50
|
attribute_types.keys
|
39
51
|
end
|
40
52
|
|
41
|
-
def form_attributes
|
42
|
-
self.class::FORM_ATTRIBUTES
|
53
|
+
def form_attributes(action = nil)
|
54
|
+
specific_form_attributes_for(action) || self.class::FORM_ATTRIBUTES
|
55
|
+
end
|
56
|
+
|
57
|
+
def specific_form_attributes_for(action)
|
58
|
+
return unless action
|
59
|
+
|
60
|
+
cname = "FORM_ATTRIBUTES_#{action.upcase}"
|
61
|
+
|
62
|
+
self.class.const_get(cname) if self.class.const_defined?(cname)
|
43
63
|
end
|
44
64
|
|
45
65
|
def permitted_attributes
|
46
66
|
form_attributes.map do |attr|
|
47
|
-
attribute_types[attr].permitted_attribute(
|
67
|
+
attribute_types[attr].permitted_attribute(
|
68
|
+
attr,
|
69
|
+
resource_class: self.class.model,
|
70
|
+
)
|
48
71
|
end.uniq
|
49
72
|
end
|
50
73
|
|
@@ -56,6 +79,12 @@ module Administrate
|
|
56
79
|
self.class::COLLECTION_ATTRIBUTES
|
57
80
|
end
|
58
81
|
|
82
|
+
def search_attributes
|
83
|
+
attribute_types.keys.select do |attribute|
|
84
|
+
attribute_types[attribute].searchable?
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
59
88
|
def display_resource(resource)
|
60
89
|
"#{resource.class} ##{resource.id}"
|
61
90
|
end
|
@@ -74,18 +103,11 @@ module Administrate
|
|
74
103
|
"Attribute #{attr} could not be found in #{self.class}::ATTRIBUTE_TYPES"
|
75
104
|
end
|
76
105
|
|
77
|
-
def association_classes
|
78
|
-
@association_classes ||=
|
79
|
-
ObjectSpace.each_object(Class).
|
80
|
-
select { |klass| klass < Administrate::Field::Associative }
|
81
|
-
end
|
82
|
-
|
83
106
|
def attribute_includes(attributes)
|
84
107
|
attributes.map do |key|
|
85
|
-
field =
|
108
|
+
field = attribute_type_for(key)
|
86
109
|
|
87
|
-
|
88
|
-
key if association_classes.include?(field.try(:deferred_class))
|
110
|
+
key if field.associative?
|
89
111
|
end.compact
|
90
112
|
end
|
91
113
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Administrate
|
2
|
+
class CustomDashboard
|
3
|
+
include Administrate
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def resource_name(_opts)
|
7
|
+
named_resource.pluralize.titleize
|
8
|
+
end
|
9
|
+
|
10
|
+
def resource(resource_name)
|
11
|
+
define_singleton_method(:named_resource) { resource_name }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/administrate/engine.rb
CHANGED
@@ -22,6 +22,13 @@ module Administrate
|
|
22
22
|
@@javascripts = []
|
23
23
|
@@stylesheets = []
|
24
24
|
|
25
|
+
initializer "administrate.assets.precompile" do |app|
|
26
|
+
app.config.assets.precompile += [
|
27
|
+
"administrate/application.js",
|
28
|
+
"administrate/application.css",
|
29
|
+
]
|
30
|
+
end
|
31
|
+
|
25
32
|
def self.add_javascript(script)
|
26
33
|
@@javascripts << script
|
27
34
|
end
|
@@ -3,30 +3,74 @@ require_relative "base"
|
|
3
3
|
module Administrate
|
4
4
|
module Field
|
5
5
|
class Associative < Base
|
6
|
+
def self.foreign_key_for(resource_class, attr)
|
7
|
+
reflection(resource_class, attr).foreign_key
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.associated_class(resource_class, attr)
|
11
|
+
reflection(resource_class, attr).klass
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.associated_class_name(resource_class, attr)
|
15
|
+
reflection(resource_class, attr).class_name
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.reflection(resource_class, attr)
|
19
|
+
resource_class.reflect_on_association(attr)
|
20
|
+
end
|
21
|
+
|
6
22
|
def display_associated_resource
|
7
23
|
associated_dashboard.display_resource(data)
|
8
24
|
end
|
9
25
|
|
10
26
|
def associated_class
|
11
|
-
|
27
|
+
if option_given?(:class_name)
|
28
|
+
associated_class_name.constantize
|
29
|
+
else
|
30
|
+
self.class.associated_class(resource.class, attribute)
|
31
|
+
end
|
12
32
|
end
|
13
33
|
|
14
|
-
|
34
|
+
private
|
15
35
|
|
16
36
|
def associated_dashboard
|
17
37
|
"#{associated_class_name}Dashboard".constantize.new
|
18
38
|
end
|
19
39
|
|
20
40
|
def associated_class_name
|
21
|
-
|
41
|
+
if option_given?(:class_name)
|
42
|
+
deprecated_option(:class_name)
|
43
|
+
else
|
44
|
+
self.class.associated_class_name(
|
45
|
+
resource.class,
|
46
|
+
attribute,
|
47
|
+
)
|
48
|
+
end
|
22
49
|
end
|
23
50
|
|
24
51
|
def primary_key
|
25
|
-
|
52
|
+
if option_given?(:primary_key)
|
53
|
+
deprecated_option(:primary_key)
|
54
|
+
else
|
55
|
+
:id
|
56
|
+
end
|
26
57
|
end
|
27
58
|
|
28
59
|
def foreign_key
|
29
|
-
|
60
|
+
if option_given?(:foreign_key)
|
61
|
+
deprecated_option(:foreign_key)
|
62
|
+
else
|
63
|
+
self.class.foreign_key_for(resource.class, attribute)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def option_given?(name)
|
68
|
+
options.key?(name)
|
69
|
+
end
|
70
|
+
|
71
|
+
def deprecated_option(name)
|
72
|
+
Administrate.warn_of_deprecated_option(name)
|
73
|
+
options.fetch(name)
|
30
74
|
end
|
31
75
|
end
|
32
76
|
end
|
@@ -12,6 +12,10 @@ module Administrate
|
|
12
12
|
field_type.dasherize
|
13
13
|
end
|
14
14
|
|
15
|
+
def self.associative?
|
16
|
+
self < Associative
|
17
|
+
end
|
18
|
+
|
15
19
|
def self.searchable?
|
16
20
|
false
|
17
21
|
end
|
@@ -44,6 +48,32 @@ module Administrate
|
|
44
48
|
"/fields/#{self.class.field_type}/#{page}"
|
45
49
|
end
|
46
50
|
|
51
|
+
def required?
|
52
|
+
return false unless resource.class.respond_to?(:validators_on)
|
53
|
+
|
54
|
+
resource.class.validators_on(attribute).any? do |v|
|
55
|
+
next false unless v.class == ActiveRecord::Validations::PresenceValidator
|
56
|
+
|
57
|
+
options = v.options
|
58
|
+
next false if options.include?(:if)
|
59
|
+
next false if options.include?(:unless)
|
60
|
+
|
61
|
+
if on_option = options[:on]
|
62
|
+
if on_option == :create && !resource.persisted?
|
63
|
+
next true
|
64
|
+
end
|
65
|
+
|
66
|
+
if on_option == :update && resource.persisted?
|
67
|
+
next true
|
68
|
+
end
|
69
|
+
|
70
|
+
next false
|
71
|
+
end
|
72
|
+
|
73
|
+
true
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
47
77
|
attr_reader :attribute, :data, :options, :page, :resource
|
48
78
|
end
|
49
79
|
end
|
@@ -3,8 +3,14 @@ require_relative "associative"
|
|
3
3
|
module Administrate
|
4
4
|
module Field
|
5
5
|
class BelongsTo < Associative
|
6
|
-
def self.permitted_attribute(attr,
|
7
|
-
:
|
6
|
+
def self.permitted_attribute(attr, options = {})
|
7
|
+
resource_class = options[:resource_class]
|
8
|
+
if resource_class
|
9
|
+
foreign_key_for(resource_class, attr)
|
10
|
+
else
|
11
|
+
Administrate.warn_of_missing_resource_class
|
12
|
+
:"#{attr}_id"
|
13
|
+
end
|
8
14
|
end
|
9
15
|
|
10
16
|
def permitted_attribute
|
@@ -12,7 +18,7 @@ module Administrate
|
|
12
18
|
end
|
13
19
|
|
14
20
|
def associated_resource_options
|
15
|
-
|
21
|
+
candidate_resources.map do |resource|
|
16
22
|
[display_candidate_resource(resource), resource.send(primary_key)]
|
17
23
|
end
|
18
24
|
end
|
@@ -21,6 +27,10 @@ module Administrate
|
|
21
27
|
data && data.send(primary_key)
|
22
28
|
end
|
23
29
|
|
30
|
+
def include_blank_option
|
31
|
+
options.fetch(:include_blank, true)
|
32
|
+
end
|
33
|
+
|
24
34
|
private
|
25
35
|
|
26
36
|
def candidate_resources
|
@@ -21,17 +21,36 @@ module Administrate
|
|
21
21
|
options == other.options
|
22
22
|
end
|
23
23
|
|
24
|
+
def associative?
|
25
|
+
deferred_class.associative?
|
26
|
+
end
|
27
|
+
|
24
28
|
def searchable?
|
25
29
|
options.fetch(:searchable, deferred_class.searchable?)
|
26
30
|
end
|
27
31
|
|
28
32
|
def searchable_field
|
33
|
+
ActiveSupport::Deprecation.warn(
|
34
|
+
"searchable_field is deprecated, use searchable_fields instead",
|
35
|
+
)
|
29
36
|
options.fetch(:searchable_field)
|
30
37
|
end
|
31
38
|
|
32
|
-
def
|
33
|
-
options.
|
34
|
-
|
39
|
+
def searchable_fields
|
40
|
+
if options.key?(:searchable_field)
|
41
|
+
[searchable_field]
|
42
|
+
else
|
43
|
+
options.fetch(:searchable_fields)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def permitted_attribute(attr, opts = {})
|
48
|
+
if options.key?(:foreign_key)
|
49
|
+
Administrate.warn_of_deprecated_option(:foreign_key)
|
50
|
+
options.fetch(:foreign_key)
|
51
|
+
else
|
52
|
+
deferred_class.permitted_attribute(attr, options.merge(opts))
|
53
|
+
end
|
35
54
|
end
|
36
55
|
|
37
56
|
delegate :html_class, to: :deferred_class
|