administrate-base_controller 0.2.0 → 0.6.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.
@@ -1,21 +1,21 @@
1
- The MIT License (MIT)
2
-
3
- Copyright (c) 2019 Derk-Jan Karrenbeld
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in
13
- all copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- THE SOFTWARE.
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Derk-Jan Karrenbeld
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md CHANGED
@@ -24,7 +24,9 @@ Or install it yourself as:
24
24
 
25
25
  ## Usage
26
26
 
27
- When you require this gem, the base controller functionality will be added to the `administrate/application_controller`.
27
+ When you require this gem, you can `include Administrate::BaseController` in your admin `ApplicationController`.
28
+ Alternatively require `administrate/base_controller/engine` instead (e.g. in your Gemfile). The base controller
29
+ functionality will be added to the `administrate/application_controller`.
28
30
 
29
31
  You get the following _protected_ methods for free, which you may override:
30
32
 
@@ -41,6 +43,10 @@ You get the following _protected_ methods for free, which you may override:
41
43
  | `authorize_resource` | `show_action?(action_name.to_sym, resource)` | Allows you to change how resources are authorized |
42
44
  | `resource_params` | Calls `read_param(k, v)` for each instead of `transform_values` | Allows you to change how params are read |
43
45
  | `read_param` | Calls `read_param_value` if applicable | Allows you to change how a param is read based on its key |
46
+ | `render_index_json` | `json: resources.to_json` | Easily override json responses on the index route without changing the resources logic |
47
+ | `render_index_any` | `locals: resources, page, ...` | Easily override any responses on the index route without changing the resources logic |
48
+ | `render_show_json` | `json: resource.to_json` | Easily override json responses on the show route without changing the resources logic |
49
+ | `render_show_any` | `locals: resource, page, ...` | Easily override any responses on the show route without changing the resources logic |
44
50
 
45
51
  ```ruby
46
52
  module Admin
@@ -60,7 +66,7 @@ module Admin
60
66
  def current_ability
61
67
  @_current_ability ||= Ability.new(current_admin_user)
62
68
  end
63
-
69
+
64
70
  def show_action?(action, resource)
65
71
  current_ability.can?(action.to_sym, resource)
66
72
  end
@@ -73,13 +79,13 @@ Additionally you can correctly hide resources the `current_ability` can not `act
73
79
  ```ruby
74
80
  module Admin
75
81
  class ApplicationController < Administrate::ApplicationController
76
-
82
+
77
83
  # ...
78
-
84
+
79
85
  def scoped_resource
80
86
  super.accessible_by(current_ability, action_name.to_sym)
81
87
  end
82
- end
88
+ end
83
89
  end
84
90
  ```
85
91
 
@@ -91,8 +97,8 @@ This works without this gem, but this gem allows you to changed `scoped_resource
91
97
  module Admin
92
98
  class BookController < ::Admin::ApplicationController
93
99
  def find_resource(param)
94
- scoped_resource.friendly.find(param)
95
- end
100
+ scoped_resource.friendly.find(param)
101
+ end
96
102
  end
97
103
  end
98
104
  ```
@@ -107,7 +113,7 @@ module Admin
107
113
  class BookController < ::Admin::ApplicationController
108
114
  def index_scoped_resource
109
115
  super.where(author: Current.author)
110
- end
116
+ end
111
117
  end
112
118
  end
113
119
  ```
@@ -124,7 +130,7 @@ module Admin
124
130
  class BookController < ::Admin::ApplicationController
125
131
  def new_resource
126
132
  resource_class.new(author: Current.author)
127
- end
133
+ end
128
134
  end
129
135
  end
130
136
  ```
@@ -138,12 +144,12 @@ field, which contents have been serialized, you can overwrite `read_param`:
138
144
  module Admin
139
145
  class BookController < ::Admin::ApplicationController
140
146
  JSON_FIELDS = %w[options content].freeze
141
-
147
+
142
148
  def read_param(key, value)
143
149
  return Oj.load(value) if JSON_FIELDS.include?(String(key))
144
150
  super(key, value)
145
151
  end
146
- end
152
+ end
147
153
  end
148
154
  ```
149
155
 
@@ -152,21 +158,21 @@ Alternatively you can use the [`administrate-serialized_fields`](https://github.
152
158
  ## Related
153
159
 
154
160
  - [`Administrate`](https://github.com/thoughtbot/administrate): A Rails engine that helps you put together a super-flexible admin dashboard.
155
- <!-- - [`Administrate::BaseController`](https://github.com/XPBytes/administrate-base_controller): A set of application controller improvements. -->
156
161
 
157
162
  ### Concerns
158
163
 
159
- - [`Administrate::DefaultOrder`](https://github.com/XPBytes/administrate-default_order): Sets the default order for a resource in a administrate controller.
160
- - [`Administrate::SerializedFields`](https://github.com/XPBytes/administrate-serialized_fields): Automatically deserialize administrate fields on form submit.
164
+ - [`Administrate::DefaultOrder`](https://github.com/XPBytes/administrate-default_order): :1234: Sets the default order for a resource in a administrate controller.
165
+ - [`Administrate::SerializedFields`](https://github.com/XPBytes/administrate-serialized_fields): :ab: Automatically deserialize administrate fields on form submit.
161
166
 
162
167
  ### Fields
163
168
 
164
- - [`Administrate::Field::Code`](https://github.com/XPBytes/administrate-field-code): A `text` field that shows code.
165
- - [`Administrate::Field::Hyperlink`](https://github.com/XPBytes/administrate-field-hyperlink): A `string` field that is shows a hyperlink.
166
- - [`Adminisrtate::Field::JsonEditor`](https://github.com/XPBytes/administrate-field-json_editor): A `text` field that shows a [JSON editor](https://github.com/josdejong/jsoneditor).
167
- - [`Administrate::Field::ScopedBelongsTo`](https://github.com/XPBytes/administrate-field-scoped_belongs_to): A `belongs_to` field that yields itself to the scope `lambda`.
168
- - [`Administrate::Field::ScopedHasMany`](https://github.com/XPBytes/administrate-field-scoped_has_many): A `has_many` field that yields itself to the scope `lambda`.
169
- - [`Administrate::Field::TimeAgo`](https://github.com/XPBytes/administrate-field-time_ago): A `date_time` field that shows its data as `time_ago` since.
169
+ - [`Administrate::Field::Code`](https://github.com/XPBytes/administrate-field-code): :pencil: A `text` field that shows code.
170
+ - [`Administrate::Field::Hyperlink`](https://github.com/XPBytes/administrate-field-hyperlink): :pencil: A `string` field that is shows a hyperlink.
171
+ - [`Adminisrtate::Field::JsonEditor`](https://github.com/XPBytes/administrate-field-json_editor): :pencil: A `text` field that shows a [JSON editor](https://github.com/josdejong/jsoneditor).
172
+ - [`Administrate::Field::LazyBelongsTo`](https://github.com/XPBytes/administrate-field-lazy_belongs_to): :pencil: An input field that lazy loads `belongs_to` values.
173
+ - [`Administrate::Field::ScopedBelongsTo`](https://github.com/XPBytes/administrate-field-scoped_belongs_to): :pencil: A `belongs_to` field that yields itself to the scope `lambda`.
174
+ - [`Administrate::Field::ScopedHasMany`](https://github.com/XPBytes/administrate-field-scoped_has_many): :pencil: A `has_many` field that yields itself to the scope `lambda`.
175
+ - [`Administrate::Field::TimeAgo`](https://github.com/XPBytes/administrate-field-time_ago): :pencil: A `date_time` field that shows its data as `time_ago` since.
170
176
 
171
177
  ## Development
172
178
 
data/Rakefile CHANGED
@@ -1,10 +1,10 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
3
-
4
- Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
7
- t.test_files = FileList["test/**/*_test.rb"]
8
- end
9
-
10
- task :default => :test
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task :default => :test
@@ -1,42 +1,42 @@
1
- lib = File.expand_path('../lib', __FILE__)
2
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require 'administrate/base_controller/version'
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = 'administrate-base_controller'
7
- spec.version = Administrate::BaseController::VERSION
8
- spec.authors = ['Derk-Jan Karrenbeld']
9
- spec.email = ['derk-jan@xpbytes.com']
10
-
11
- spec.summary = 'Extends the ApplicationController in Administrate'
12
- spec.homepage = 'https://github.com/XPBytes/administrate-base_controller'
13
- spec.license = 'MIT'
14
-
15
- # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
16
- # to allow pushing to a single host or delete this section to allow pushing to any host.
17
- if spec.respond_to?(:metadata)
18
- # spec.metadata['allowed_push_host'] = 'TODO: Set to 'http://mygemserver.com''
19
-
20
- spec.metadata['homepage_uri'] = spec.homepage
21
- spec.metadata['source_code_uri'] = spec.homepage
22
- spec.metadata['changelog_uri'] = spec.homepage + '/CHANGELOG.md'
23
- else
24
- raise 'RubyGems 2.0 or newer is required to protect against ' \
25
- 'public gem pushes.'
26
- end
27
-
28
- # Specify which files should be added to the gem when it is released.
29
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
30
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
31
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
32
- end
33
- spec.bindir = 'exe'
34
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
35
- spec.require_paths = ['lib']
36
-
37
- spec.add_development_dependency 'administrate', '>= 0.11.0', '< 1'
38
- spec.add_development_dependency 'bundler', '~> 2.0'
39
- spec.add_development_dependency 'minitest', '~> 5.0'
40
- spec.add_development_dependency 'rake', '~> 10.0'
41
- spec.add_development_dependency 'rails'
42
- end
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'administrate/base_controller/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'administrate-base_controller'
7
+ spec.version = Administrate::BaseController::VERSION
8
+ spec.authors = ['Derk-Jan Karrenbeld']
9
+ spec.email = ['derk-jan@xpbytes.com']
10
+
11
+ spec.summary = 'Extends the ApplicationController in Administrate'
12
+ spec.homepage = 'https://github.com/XPBytes/administrate-base_controller'
13
+ spec.license = 'MIT'
14
+
15
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
16
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
17
+ if spec.respond_to?(:metadata)
18
+ # spec.metadata['allowed_push_host'] = 'TODO: Set to 'http://mygemserver.com''
19
+
20
+ spec.metadata['homepage_uri'] = spec.homepage
21
+ spec.metadata['source_code_uri'] = spec.homepage
22
+ spec.metadata['changelog_uri'] = spec.homepage + '/CHANGELOG.md'
23
+ else
24
+ raise 'RubyGems 2.0 or newer is required to protect against ' \
25
+ 'public gem pushes.'
26
+ end
27
+
28
+ # Specify which files should be added to the gem when it is released.
29
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
30
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
31
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
32
+ end
33
+ spec.bindir = 'exe'
34
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
35
+ spec.require_paths = ['lib']
36
+
37
+ spec.add_development_dependency 'administrate', '~> 0.13.0'
38
+ spec.add_development_dependency 'bundler', '~> 2.0'
39
+ spec.add_development_dependency 'minitest', '~> 5.0'
40
+ spec.add_development_dependency 'rake', '~> 13.0'
41
+ spec.add_development_dependency 'rails', '~> 6.0'
42
+ end
@@ -1,14 +1,14 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "administrate/default_order"
5
-
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
8
-
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require "irb"
14
- IRB.start(__FILE__)
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "administrate/default_order"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup CHANGED
@@ -1,8 +1,8 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -1,96 +1,141 @@
1
1
  require 'administrate/base_controller/version'
2
- require 'administrate/engine'
3
2
 
4
3
  module Administrate
5
- class Engine < Rails::Engine
6
- config.after_initialize do
7
- ::Administrate::ApplicationController.class_eval do
8
- def index
9
- resources = index_resources
10
- resources = apply_resource_includes(resources)
11
- resources = order.apply(resources)
12
- resources = resources.page(params[:page]).per(records_per_page)
13
- page = index_page
14
-
15
- render locals: {
16
- resources: resources,
17
- search_term: search_term,
18
- page: page,
19
- show_search_bar: show_search_bar?,
20
- }
21
- end
4
+ module BaseController
5
+ def index
6
+ resources = index_resources
7
+ resources = apply_collection_includes(resources)
8
+ resources = order.apply(resources)
9
+ resources = resources.page(params[:page]).per(records_per_page)
10
+
11
+ respond_to do |format|
12
+ format.json { render_index_json(resources) }
13
+ format.any { render_index_any(resources, format: format) }
14
+ end
15
+ end
22
16
 
23
- def new
24
- resource = new_resource
25
- authorize_resource(resource)
26
- render locals: { page: new_page(resource) }
27
- end
17
+ def new
18
+ resource = new_resource
19
+ authorize_resource(resource)
20
+ render locals: { page: new_page(resource) }
21
+ end
28
22
 
29
- def edit
30
- render locals: { page: edit_page(requested_resource) }
31
- end
23
+ def edit
24
+ render locals: { page: edit_page(requested_resource) }
25
+ end
32
26
 
33
- def show
34
- render locals: { page: show_page }
35
- end
27
+ def show
28
+ respond_to do |format|
29
+ format.json { render_show_json(requested_resource) }
30
+ format.any { render_show_any(requested_resource, format: format) }
31
+ end
32
+ end
36
33
 
37
- protected
34
+ protected
38
35
 
39
- def search_term
40
- @search_term ||= params[:search].to_s.strip
41
- end
36
+ def search_term
37
+ @search_term ||= params[:search].to_s.strip
38
+ end
42
39
 
43
- def index_scoped_resource
44
- scoped_resource
45
- end
40
+ ##
41
+ # The resource scope only used for +index+.
42
+ #
43
+ # By default this calls +scoped_resource+ but it's common to overwrite this in controllers that would like a scoped
44
+ # view on the index page only. This way a subset of resources is shown, based on some state such as the path or a
45
+ # cookie or the current user, but +find_resource+ still works as intended when accessing the show path.
46
+ #
47
+ def index_scoped_resource
48
+ scoped_resource
49
+ end
46
50
 
47
- def index_resources
48
- Administrate::Search.new(index_scoped_resource, dashboard_class, search_term).run
49
- end
51
+ ##
52
+ # Wraps the +index_scoped_resource+.
53
+ #
54
+ # By default this constructs the +Administrate::Search+ decorator, wraps the resources and runs it with the
55
+ # +dashboard_class+ and +search_term+. Overwrite this to turn off search.
56
+ #
57
+ def index_resources
58
+ Administrate::Search.new(index_scoped_resource, dashboard_class, search_term).run
59
+ end
50
60
 
51
- def index_page
52
- Administrate::Page::Collection.new(dashboard, order: order)
53
- end
61
+ ##
62
+ # The page used for +index+.
63
+ #
64
+ def index_page
65
+ Administrate::Page::Collection.new(dashboard, order: order)
66
+ end
54
67
 
55
- def show_page
56
- Administrate::Page::Show.new(dashboard, requested_resource)
57
- end
68
+ ##
69
+ # The page used for +show+
70
+ #
71
+ def show_page(resource = requested_resource)
72
+ Administrate::Page::Show.new(dashboard, resource)
73
+ end
58
74
 
59
- def new_page(resource)
60
- Administrate::Page::Form.new(dashboard, resource)
61
- end
75
+ ##
76
+ # The page used for +new+
77
+ #
78
+ def new_page(resource)
79
+ Administrate::Page::Form.new(dashboard, resource)
80
+ end
62
81
 
63
- def edit_page(resource)
64
- new_page(resource)
65
- end
82
+ ##
83
+ # The page used for +edit+
84
+ #
85
+ def edit_page(resource)
86
+ new_page(resource)
87
+ end
66
88
 
67
- def authorize_resource(resource)
68
- return if show_action?(action_name.to_sym, resource)
69
- raise "That's not a valid action."
70
- end
89
+ def authorize_resource(resource)
90
+ return if show_action?(action_name.to_sym, resource)
91
+ raise "That's not a valid action."
92
+ end
71
93
 
72
- def resource_params
73
- permitted = params.require(resource_class.model_name.param_key)
74
- .permit(dashboard.permitted_attributes)
75
- .to_h
94
+ def resource_params
95
+ permitted = params.require(resource_class.model_name.param_key)
96
+ .permit(dashboard.permitted_attributes)
97
+ .to_h
76
98
 
77
- permitted.each_with_object(permitted) do |(k, v), result|
78
- result[k] = read_param(k, v)
79
- end
99
+ permitted.each_with_object(permitted) do |(k, v), result|
100
+ result[k] = read_param(k, v)
101
+ end
102
+ end
103
+
104
+ def read_param(_, data)
105
+ if data.is_a?(Hash) && data[:type]
106
+ if data[:type] == Administrate::Field::Polymorphic.to_s
107
+ return GlobalID::Locator.locate(data[:value])
80
108
  end
109
+ end
81
110
 
82
- def read_param(_, data)
83
- if data.is_a?(ActionController::Parameters) && data[:type]
84
- return read_param_value(data)
85
- end
111
+ data
112
+ end
86
113
 
87
- data
88
- end
114
+ def render_index_json(resources)
115
+ render json: resources
116
+ end
89
117
 
90
- private
118
+ def render_index_any(resources, format:)
119
+ page = index_page
91
120
 
92
- attr_writer :search_term
93
- end
121
+ render locals: {
122
+ resources: resources,
123
+ search_term: search_term,
124
+ page: page,
125
+ show_search_bar: show_search_bar?,
126
+ }
127
+ end
128
+
129
+ def render_show_json(resource = requested_resource)
130
+ render json: resource
131
+ end
132
+
133
+ def render_show_any(resource = requested_resource, format:)
134
+ render locals: { page: show_page(resource) }
94
135
  end
136
+
137
+ private
138
+
139
+ attr_writer :search_term
95
140
  end
96
141
  end