administrate 0.14.0 → 0.15.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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/administrate/components/associative.js +1 -0
  3. data/app/assets/stylesheets/administrate/components/_attributes.scss +3 -2
  4. data/app/assets/stylesheets/administrate/components/_field-unit.scss +4 -0
  5. data/app/assets/stylesheets/administrate/components/_main-content.scss +1 -0
  6. data/app/controllers/administrate/application_controller.rb +11 -11
  7. data/app/helpers/administrate/application_helper.rb +10 -23
  8. data/app/views/administrate/application/_collection.html.erb +1 -1
  9. data/app/views/administrate/application/_form.html.erb +1 -1
  10. data/app/views/administrate/application/index.html.erb +2 -2
  11. data/app/views/administrate/application/show.html.erb +1 -1
  12. data/app/views/fields/belongs_to/_form.html.erb +3 -3
  13. data/app/views/fields/has_one/_index.html.erb +1 -1
  14. data/app/views/fields/has_one/_show.html.erb +4 -4
  15. data/app/views/fields/number/_form.html.erb +1 -1
  16. data/app/views/fields/polymorphic/_show.html.erb +1 -1
  17. data/app/views/fields/select/_form.html.erb +2 -2
  18. data/app/views/fields/time/_index.html.erb +3 -1
  19. data/app/views/fields/time/_show.html.erb +3 -1
  20. data/app/views/layouts/administrate/application.html.erb +1 -0
  21. data/config/locales/administrate.fi.yml +30 -0
  22. data/config/locales/administrate.fr.yml +2 -2
  23. data/config/locales/administrate.nl.yml +4 -4
  24. data/config/locales/administrate.pt-BR.yml +2 -2
  25. data/config/locales/administrate.pt.yml +3 -3
  26. data/config/locales/administrate.tr.yml +30 -0
  27. data/config/unicorn.rb +8 -13
  28. data/docs/adding_controllers_without_related_model.md +18 -0
  29. data/docs/customizing_dashboards.md +32 -16
  30. data/docs/extending_administrate.md +27 -0
  31. data/docs/getting_started.md +27 -5
  32. data/docs/guides.md +5 -0
  33. data/docs/guides/hiding_dashboards_from_sidebar.md +19 -0
  34. data/lib/administrate.rb +19 -0
  35. data/lib/administrate/base_dashboard.rb +5 -2
  36. data/lib/administrate/engine.rb +7 -0
  37. data/lib/administrate/field/associative.rb +48 -4
  38. data/lib/administrate/field/base.rb +26 -0
  39. data/lib/administrate/field/belongs_to.rb +13 -3
  40. data/lib/administrate/field/deferred.rb +7 -3
  41. data/lib/administrate/field/has_many.rb +15 -2
  42. data/lib/administrate/field/has_one.rb +28 -8
  43. data/lib/administrate/field/number.rb +19 -2
  44. data/lib/administrate/field/polymorphic.rb +1 -1
  45. data/lib/administrate/order.rb +3 -1
  46. data/lib/administrate/resource_resolver.rb +1 -1
  47. data/lib/administrate/search.rb +11 -8
  48. data/lib/administrate/version.rb +1 -1
  49. data/lib/administrate/view_generator.rb +7 -1
  50. data/lib/generators/administrate/dashboard/dashboard_generator.rb +3 -10
  51. data/lib/generators/administrate/dashboard/templates/dashboard.rb.erb +3 -3
  52. data/lib/generators/administrate/install/install_generator.rb +37 -1
  53. data/lib/generators/administrate/routes/routes_generator.rb +3 -13
  54. data/lib/generators/administrate/views/views_generator.rb +5 -4
  55. metadata +15 -25
  56. data/docs/contributing.md +0 -1
@@ -22,8 +22,8 @@ pt-BR:
22
22
  more: "Exibindo %{count} de %{total_count}"
23
23
  none: Nenhum
24
24
  form:
25
- error: error
26
- errors: "%{pluralized_errors} prohibited this %{resource_name} from being saved:"
25
+ error: erro
26
+ errors: "%{pluralized_errors} impediram %{resource_name} de ser gravado:"
27
27
  navigation:
28
28
  back_to_app: Voltar ao aplicativo
29
29
  search:
@@ -22,10 +22,10 @@ pt:
22
22
  more: "Mostrando %{count} de %{total_count}"
23
23
  none: Nenhum
24
24
  form:
25
- error: error
26
- errors: "%{pluralized_errors} prohibited this %{resource_name} from being saved:"
25
+ error: erro
26
+ errors: "%{pluralized_errors} impediram %{resource_name} de ser gravado:"
27
27
  navigation:
28
- back_to_app: Voltar ao aplicativo
28
+ back_to_app: Voltar à aplicação
29
29
  search:
30
30
  clear: Limpar pesquisa
31
31
  label: Pesquisa %{resource}
@@ -0,0 +1,30 @@
1
+ ---
2
+ tr:
3
+ administrate:
4
+ actions:
5
+ confirm: Emin misiniz?
6
+ destroy: Sil
7
+ edit: Düzenle
8
+ edit_resource: "%{name} Kaydını Düzenle"
9
+ show_resource: "%{name} Kaydını Göster"
10
+ new_resource: Yeni %{name}
11
+ back: Geri
12
+ controller:
13
+ create:
14
+ success: "%{resource} kaydı başarıyla yaratıldı."
15
+ destroy:
16
+ success: "%{resource} kaydı başarıyla silindi."
17
+ update:
18
+ success: "%{resource} kaydı başarıyla düzenlendi."
19
+ fields:
20
+ has_many:
21
+ more: Toplam %{total_count} kayıttan %{count} adedi gösteriliyor
22
+ none: Yok
23
+ form:
24
+ error: Hata
25
+ errors: "%{resource_name} kaydedilemedi: %{pluralized_errors}"
26
+ navigation:
27
+ back_to_app: Uygulamaya geri dön
28
+ search:
29
+ clear: Temizle
30
+ label: "%{resource} içerisinde ara"
data/config/unicorn.rb CHANGED
@@ -1,30 +1,25 @@
1
1
  # https://devcenter.heroku.com/articles/rails-unicorn
2
2
 
3
- worker_processes (ENV["UNICORN_WORKERS"] || 3).to_i
4
- timeout (ENV["UNICORN_TIMEOUT"] || 15).to_i
3
+ worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
4
+ timeout 15
5
5
  preload_app true
6
6
 
7
7
  before_fork do |_server, _worker|
8
8
  Signal.trap "TERM" do
9
- puts "Unicorn master intercepting TERM, sending myself QUIT instead"
9
+ puts "Unicorn master intercepting TERM and sending myself QUIT instead"
10
10
  Process.kill "QUIT", Process.pid
11
11
  end
12
12
 
13
- if defined? ActiveRecord::Base
13
+ defined?(ActiveRecord::Base) &&
14
14
  ActiveRecord::Base.connection.disconnect!
15
- end
16
15
  end
17
16
 
18
17
  after_fork do |_server, _worker|
19
18
  Signal.trap "TERM" do
20
- puts "Unicorn worker intercepting TERM, waiting for master to send QUIT"
19
+ puts "Unicorn worker intercepting TERM and doing nothing. " \
20
+ "Wait for master to send QUIT"
21
21
  end
22
22
 
23
- if defined? ActiveRecord::Base
24
- config = ActiveRecord::Base.configurations[Rails.env] ||
25
- Rails.application.config.database_configuration[Rails.env]
26
- config["reaping_frequency"] = (ENV["DB_REAPING_FREQUENCY"] || 10).to_i
27
- config["pool"] = (ENV["DB_POOL"] || 2).to_i
28
- ActiveRecord::Base.establish_connection(config)
29
- end
23
+ defined?(ActiveRecord::Base) &&
24
+ ActiveRecord::Base.establish_connection
30
25
  end
@@ -1,3 +1,7 @@
1
+ ---
2
+ title: Adding Controllers without a related Model
3
+ ---
4
+
1
5
  # Adding Controllers without a related Model
2
6
 
3
7
  Sometimes you may want to add a custom controller that has no resource
@@ -27,6 +31,20 @@ class StatDashboard < Administrate::CustomDashboard
27
31
  end
28
32
  ```
29
33
 
34
+ ```ruby
35
+ # app/controllers/admin/stats_controller.rb
36
+ module Admin
37
+ class StatsController < Admin::ApplicationController
38
+ def index
39
+ @stats = {
40
+ customer_count: Customer.count,
41
+ order_count: Order.count,
42
+ }
43
+ end
44
+ end
45
+ end
46
+ ```
47
+
30
48
  ```ruby
31
49
  # config/routes.rb
32
50
  namespace :admin do
@@ -79,16 +79,11 @@ which are specified through the `.with_options` class method:
79
79
  `:order` - Specifies the order of the dropdown menu, can be ordered by more
80
80
  than one column. e.g.: `"name, email DESC"`.
81
81
 
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
82
  `:scope` - Specifies a custom scope inside a callable. Useful for preloading.
88
83
  Example: `.with_options(scope: -> { MyModel.includes(:rel).limit(5) })`
89
84
 
90
- `:class_name` - Specifies the name of the associated class.
91
- Defaults to `:#{attribute}.to_s.singularize.camelcase`.
85
+ `:include_blank` - Specifies if the select element to be rendered should include
86
+ blank option. Default is `true`.
92
87
 
93
88
  `:searchable` - Specify if the attribute should be considered when searching.
94
89
  Default is `false`.
@@ -108,6 +103,12 @@ For example:
108
103
  with this, you will be able to search through the column `name` from the
109
104
  association `belongs_to :country`, from your model.
110
105
 
106
+ `:primary_key` (deprecated) - Specifies the association's primary_key.
107
+
108
+ `:foreign_key` (deprecated) - Specifies the name of the foreign key directly.
109
+
110
+ `:class_name` (deprecated) - Specifies the name of the associated class.
111
+
111
112
  **Field::HasMany**
112
113
 
113
114
  `:limit` - Set the number of resources to display in the show view. Default is
@@ -117,18 +118,14 @@ association `belongs_to :country`, from your model.
117
118
 
118
119
  `:direction` - What direction the sort should be in, `:asc` (default) or `:desc`.
119
120
 
120
- `:primary_key` - Specifies object's primary_key. Defaults to `:id`.
121
+ `:primary_key` (deprecated) - Specifies object's primary_key.
121
122
 
122
- `:foreign_key` - Specifies the name of the foreign key directly. Defaults to `:#{attribute}_id`
123
+ `:foreign_key` (deprecated) - Specifies the name of the foreign key directly.
123
124
 
124
- `:class_name` - Specifies the name of the associated class.
125
- Defaults to `:#{attribute}.to_s.singularize.camelcase`.
125
+ `:class_name` (deprecated) - Specifies the name of the associated class.
126
126
 
127
127
  **Field::HasOne**
128
128
 
129
- `:class_name` - Specifies the name of the associated class.
130
- Defaults to `:#{attribute}.to_s.singularize.camelcase`.
131
-
132
129
  `:searchable` - Specify if the attribute should be considered when searching.
133
130
  Default is `false`.
134
131
 
@@ -147,6 +144,8 @@ For example:
147
144
  with this, you will be able to search through the column `name` from the
148
145
  association `has_many :cities`, from your model.
149
146
 
147
+ `:class_name` (deprecated) - Specifies the name of the associated class.
148
+
150
149
  **Field::Number**
151
150
 
152
151
  `:searchable` - Specify if the attribute should be considered when searching.
@@ -159,6 +158,13 @@ more results than expected. Default is `false`.
159
158
 
160
159
  `:suffix` - Suffixes the number with a string. Defaults to `""`.
161
160
 
161
+ `:format` - Specify a hash which defines a formatter. This uses ActiveSupport
162
+ and works by by passing a hash that includes the formatter (`formatter`) and
163
+ the options for the formatter (`formatter_options`). Defaults to the locale's
164
+ delimiter when `formatter_options` does not include a `delimiter`. See the
165
+ example below. Note that currently only
166
+ `ActiveSupport::NumberHelper.number_to_delimited` is supported.
167
+
162
168
  For example, you might use the following to display U.S. currency:
163
169
 
164
170
  ```ruby
@@ -166,15 +172,25 @@ For example, you might use the following to display U.S. currency:
166
172
  prefix: "$",
167
173
  decimals: 2,
168
174
  )
175
+
176
+ # "$5.99"
169
177
  ```
170
178
 
171
- Or, to display a distance in kilometers:
179
+ Or, to display a distance in kilometers, using a space as the delimiter:
172
180
 
173
181
  ```ruby
174
- unit_price: Field::Number.with_options(
182
+ distance: Field::Number.with_options(
175
183
  suffix: " km",
176
184
  decimals: 2,
185
+ format: {
186
+ formatter: :number_to_delimited,
187
+ formatter_options: {
188
+ delimiter: ' ',
189
+ },
190
+ },
177
191
  )
192
+
193
+ # "2 000.00 km"
178
194
  ```
179
195
 
180
196
  **Field::Polymorphic**
@@ -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
+ At the time of writing, these appear to be the most popular ones:
9
+
10
+ 1. [ActiveStorage support](https://github.com/Dreamersoul/administrate-field-active_storage)
11
+ 2. [Password field](https://github.com/valiot/administrate-field-password)
12
+ 3. [Enum field](https://github.com/Valiot/administrate-field-enum)
13
+ 4. [Nested has-many forms](https://github.com/nickcharlton/administrate-field-nested_has_many)
14
+ 5. [Belongs-to with Ajax search](https://github.com/fishbrain/administrate-field-belongs_to_search)
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
@@ -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 4.2 or greater.
6
+ applications version 5.0 or greater. We support Ruby 2.4 and up.
7
7
 
8
- Add the following to your Gemfile:
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, then run the installer:
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
- Add a route for the new dashboard.
90
+ Then add a route for the new dashboard.
69
91
 
70
92
  ```ruby
71
93
  # config/routes.rb
data/docs/guides.md ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ title: Guides
3
+ ---
4
+
5
+ * [Hiding Dashboards from the Sidebar](./guides/hiding_dashboards_from_sidebar)
@@ -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/lib/administrate.rb CHANGED
@@ -1,4 +1,23 @@
1
1
  require "administrate/engine"
2
2
 
3
3
  module Administrate
4
+ def self.warn_of_missing_resource_class
5
+ ActiveSupport::Deprecation.warn(
6
+ "Calling Field::Base.permitted_attribute without the option " +
7
+ ":resource_class is deprecated. If you are seeing this " +
8
+ "message, you are probably using a custom field type that" +
9
+ "does this. Please make sure to update it to a version that " +
10
+ "does not use a deprecated API",
11
+ )
12
+ end
13
+
14
+ def self.warn_of_deprecated_option(name)
15
+ ActiveSupport::Deprecation.warn(
16
+ "The option :#{name} is deprecated. " +
17
+ "Administrate should detect it automatically. " +
18
+ "Please file an issue at " +
19
+ "https://github.com/thoughtbot/administrate/issues " +
20
+ "if you think otherwise.",
21
+ )
22
+ end
4
23
  end
@@ -56,7 +56,10 @@ module Administrate
56
56
 
57
57
  def permitted_attributes
58
58
  form_attributes.map do |attr|
59
- attribute_types[attr].permitted_attribute(attr)
59
+ attribute_types[attr].permitted_attribute(
60
+ attr,
61
+ resource_class: self.class.model,
62
+ )
60
63
  end.uniq
61
64
  end
62
65
 
@@ -88,7 +91,7 @@ module Administrate
88
91
 
89
92
  def attribute_includes(attributes)
90
93
  attributes.map do |key|
91
- field = self.class::ATTRIBUTE_TYPES[key]
94
+ field = attribute_type_for(key)
92
95
 
93
96
  key if field.associative?
94
97
  end.compact
@@ -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,12 +3,32 @@ 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
- associated_class_name.constantize
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
@@ -18,15 +38,39 @@ module Administrate
18
38
  end
19
39
 
20
40
  def associated_class_name
21
- options.fetch(:class_name, attribute.to_s.singularize.camelcase)
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
- options.fetch(:primary_key, :id)
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
- options.fetch(:foreign_key, :"#{attribute}_id")
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