gearhead 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/README.md +27 -4
- data/lib/gearhead/actions/index.rb +2 -2
- data/lib/gearhead/engine.rb +2 -0
- data/lib/gearhead/extensions/attributes.rb +5 -0
- data/lib/gearhead/extensions/serialization.rb +10 -1
- data/lib/gearhead/gearbox.rb +5 -8
- data/{app/controllers → lib}/gearhead/gears_controller.rb +20 -26
- data/lib/gearhead/serializers/active_model_serializers/collection_serializer.rb +12 -0
- data/lib/gearhead/serializers/active_model_serializers/resource_serializer.rb +8 -2
- data/lib/gearhead/serializers/fast_jsonapi/collection_serializer.rb +11 -0
- data/lib/gearhead/serializers/fast_jsonapi/resource_serializer.rb +6 -0
- data/lib/gearhead/serializers/lookup.rb +8 -10
- data/lib/gearhead/version.rb +1 -1
- metadata +9 -9
- data/app/controllers/gearhead/application_controller.rb +0 -5
- data/config/routes.rb +0 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8da15acd51e6492411698015103ce3dc8f35e47f9c209b65624aa5d74d876141
|
|
4
|
+
data.tar.gz: 1f13b739558ced09c7b145c0e00a40557a07437b1e058ccc76074889cb242d2c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b4257c5b8dbf26a9c5b306f07ba1ca20f37fa3c6bc56ff75424067a67aaa98a1473ee6f37c28bb5908d8c73849cbe6d988d6bc82da9d3a0cd60a75001f869899
|
|
7
|
+
data.tar.gz: 15167236c5ecb3bf004650d12ace55a98548f678471cfd371688377357cdd72c656d431b37c6cde9221031e167133125e92226190aef4b52eb9e964f31ab2aa5
|
data/README.md
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
# Gearhead
|
|
1
|
+
# Gearhead
|
|
2
2
|
|
|
3
|
-
Gearhead turns your database into a RESTful API. It's like if ActiveAdmin and Grape had a baby.
|
|
3
|
+
Gearhead turns your database into a RESTful API. It's like if ActiveAdmin, InheritedResources, and Grape had a baby.
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
For internal projects I was always standing up API endpoints that were separate from my regular controllers. The boilerplate
|
|
8
|
+
got old real fast. This eliminates boilerplate and leaves enough configuration for you to make it your own.
|
|
4
9
|
|
|
5
10
|
## Installation
|
|
6
11
|
|
|
@@ -28,7 +33,7 @@ app/gears/.keep
|
|
|
28
33
|
and modifies your routes:
|
|
29
34
|
|
|
30
35
|
```ruby
|
|
31
|
-
|
|
36
|
+
Gearhead.routes(self)
|
|
32
37
|
```
|
|
33
38
|
|
|
34
39
|
## Configuration
|
|
@@ -177,10 +182,22 @@ Just define what attributes you want exposed:
|
|
|
177
182
|
|
|
178
183
|
```ruby
|
|
179
184
|
Gearhead.register Post do
|
|
180
|
-
attributes :id, :
|
|
185
|
+
attributes :id, :title
|
|
181
186
|
end
|
|
182
187
|
```
|
|
183
188
|
|
|
189
|
+
And customize one-off attributes:
|
|
190
|
+
|
|
191
|
+
```ruby
|
|
192
|
+
Gearhead.register Post do
|
|
193
|
+
attributes :id, :title
|
|
194
|
+
|
|
195
|
+
attribute :excerpt do |resource|
|
|
196
|
+
resource.content.first(100)
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
```
|
|
200
|
+
|
|
184
201
|
### Finding resources
|
|
185
202
|
|
|
186
203
|
Change your finder:
|
|
@@ -193,6 +210,12 @@ Gearhead.register Post do
|
|
|
193
210
|
end
|
|
194
211
|
```
|
|
195
212
|
|
|
213
|
+
### Querying
|
|
214
|
+
|
|
215
|
+
Uses Ransack under the hood. Just send the normal `q` in the query, like:
|
|
216
|
+
|
|
217
|
+
`GET /gearhead/posts?q[user_id]=1`
|
|
218
|
+
|
|
196
219
|
### Permitting params
|
|
197
220
|
|
|
198
221
|
Works just like the params you're used to:
|
|
@@ -21,7 +21,7 @@ module Gearhead
|
|
|
21
21
|
@collection = apply_query
|
|
22
22
|
@collection = apply_pagination
|
|
23
23
|
@collection = apply_serializer
|
|
24
|
-
@collection
|
|
24
|
+
@collection.to_json
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
private
|
|
@@ -70,7 +70,7 @@ module Gearhead
|
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
def apply_serializer
|
|
73
|
-
@gear.
|
|
73
|
+
@gear.collection_serializer.for(@collection, @gear.serializer_class, serialization_options)
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
def serialization_options
|
data/lib/gearhead/engine.rb
CHANGED
|
@@ -2,6 +2,7 @@ module Gearhead
|
|
|
2
2
|
module Extensions
|
|
3
3
|
module Attributes
|
|
4
4
|
def self.included(klass)
|
|
5
|
+
klass.define_gear_setting :custom_attributes, []
|
|
5
6
|
end
|
|
6
7
|
|
|
7
8
|
def _gear_attributes
|
|
@@ -15,6 +16,10 @@ module Gearhead
|
|
|
15
16
|
def default_attributes
|
|
16
17
|
@resource.columns_hash.keys.map(&:to_sym)
|
|
17
18
|
end
|
|
19
|
+
|
|
20
|
+
def attribute(name, &block)
|
|
21
|
+
@_gear_custom_attributes << [name, block]
|
|
22
|
+
end
|
|
18
23
|
end
|
|
19
24
|
end
|
|
20
25
|
end
|
|
@@ -2,6 +2,11 @@ module Gearhead
|
|
|
2
2
|
module Extensions
|
|
3
3
|
module Serialization
|
|
4
4
|
def self.included(klass)
|
|
5
|
+
klass.define_gear_setting :serializer_adapter, Gearhead.config.serialization.adapter
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def serializer_adapter(adapter)
|
|
9
|
+
@_gear_serializer_adapter = adapter
|
|
5
10
|
end
|
|
6
11
|
|
|
7
12
|
def serializer(klass)
|
|
@@ -9,13 +14,17 @@ module Gearhead
|
|
|
9
14
|
end
|
|
10
15
|
|
|
11
16
|
def serializer_class
|
|
12
|
-
real_serializer = Serializers::Lookup.for(:resource)
|
|
17
|
+
real_serializer = Serializers::Lookup.for(:resource, @_gear_serializer_adapter)
|
|
13
18
|
if real_serializer.respond_to?(:for)
|
|
14
19
|
real_serializer.for(self)
|
|
15
20
|
else
|
|
16
21
|
real_serializer
|
|
17
22
|
end
|
|
18
23
|
end
|
|
24
|
+
|
|
25
|
+
def collection_serializer
|
|
26
|
+
Serializers::Lookup.for(:collection, @_gear_serializer_adapter)
|
|
27
|
+
end
|
|
19
28
|
end
|
|
20
29
|
end
|
|
21
30
|
end
|
data/lib/gearhead/gearbox.rb
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
module Gearhead
|
|
2
2
|
class Gearbox
|
|
3
|
-
def initialize
|
|
4
|
-
end
|
|
3
|
+
def initialize; end
|
|
5
4
|
|
|
6
|
-
def setup
|
|
7
|
-
# nothing
|
|
8
|
-
end
|
|
5
|
+
def setup!; end
|
|
9
6
|
|
|
10
7
|
def prepare!
|
|
11
8
|
ActiveSupport::Dependencies.autoload_paths -= load_paths
|
|
@@ -54,7 +51,7 @@ module Gearhead
|
|
|
54
51
|
unload_gearhead = -> { Gearhead.gearbox.unload! }
|
|
55
52
|
|
|
56
53
|
if app.config.reload_classes_only_on_change
|
|
57
|
-
|
|
54
|
+
ActiveSupport::Reloader.to_prepare(prepend: true, &unload_gearhead)
|
|
58
55
|
else
|
|
59
56
|
ActiveSupport::Reloader.to_complete(&unload_gearhead)
|
|
60
57
|
end
|
|
@@ -72,9 +69,9 @@ module Gearhead
|
|
|
72
69
|
app.reloaders << routes_reloader
|
|
73
70
|
|
|
74
71
|
ActiveSupport::Reloader.to_prepare do
|
|
75
|
-
|
|
72
|
+
unless Gearhead.gearbox.loaded?
|
|
76
73
|
routes_reloader.execute_if_updated
|
|
77
|
-
Gearhead.
|
|
74
|
+
Gearhead.gearbox.load!
|
|
78
75
|
end
|
|
79
76
|
end
|
|
80
77
|
end
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
#
|
|
2
|
-
if defined?(ActiveModelSerializers)
|
|
3
|
-
ActiveModelSerializers.config.serializer_lookup_enabled = false
|
|
4
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
5
2
|
|
|
3
|
+
ActiveModelSerializers.config.serializer_lookup_enabled = false
|
|
6
4
|
module Gearhead
|
|
7
5
|
class GearsController < ::Gearhead.config.base_controller.constantize
|
|
8
6
|
before_action :find_gear!
|
|
9
|
-
before_action :ensure_action_enabled!, only: [
|
|
10
|
-
before_action :find_resource!, except: [
|
|
7
|
+
before_action :ensure_action_enabled!, only: %i[index create show update destroy]
|
|
8
|
+
before_action :find_resource!, except: %i[index create collection_action]
|
|
11
9
|
|
|
12
10
|
def index
|
|
13
|
-
render json: Gearhead::Actions::Index.build(@gear, request)
|
|
11
|
+
render json: Gearhead::Actions::Index.build(@gear, request)
|
|
14
12
|
end
|
|
15
13
|
|
|
16
14
|
def create
|
|
@@ -18,7 +16,7 @@ module Gearhead
|
|
|
18
16
|
if @resource.save
|
|
19
17
|
render json: @gear.serializer_class.new(@resource)
|
|
20
18
|
else
|
|
21
|
-
render json: { errors: @resource.errors }
|
|
19
|
+
render json: { errors: @resource.errors }, status: :unprocessable_entity
|
|
22
20
|
end
|
|
23
21
|
end
|
|
24
22
|
|
|
@@ -32,7 +30,7 @@ module Gearhead
|
|
|
32
30
|
if @resource.save
|
|
33
31
|
render json: @gear.serializer_class.new(@resource)
|
|
34
32
|
else
|
|
35
|
-
render json: { errors: @resource.errors }
|
|
33
|
+
render json: { errors: @resource.errors }, status: :unprocessable_entity
|
|
36
34
|
end
|
|
37
35
|
end
|
|
38
36
|
|
|
@@ -40,21 +38,21 @@ module Gearhead
|
|
|
40
38
|
if @resource.destroy
|
|
41
39
|
render json: @gear.serializer_class.new(resource)
|
|
42
40
|
else
|
|
43
|
-
render json: { errors: resource.errors }
|
|
41
|
+
render json: { errors: @resource.errors }, status: :unprocessable_entity
|
|
44
42
|
end
|
|
45
43
|
end
|
|
46
44
|
|
|
47
45
|
def member_action
|
|
48
46
|
action = @gear._gear_member_actions[params[:member_action].to_sym]
|
|
49
|
-
if action
|
|
50
|
-
|
|
47
|
+
if action&.verbs&.include?(request.request_method.to_sym.downcase)
|
|
48
|
+
render json: instance_exec(&action.block)
|
|
51
49
|
end
|
|
52
50
|
end
|
|
53
51
|
|
|
54
52
|
def collection_action
|
|
55
53
|
action = @gear._gear_collection_actions[params[:collection_action]]
|
|
56
|
-
if action
|
|
57
|
-
|
|
54
|
+
if action&.verbs&.include?(request.request_method.to_sym.downcase)
|
|
55
|
+
render json: instance_exec(&action.block)
|
|
58
56
|
end
|
|
59
57
|
end
|
|
60
58
|
|
|
@@ -64,35 +62,31 @@ module Gearhead
|
|
|
64
62
|
@gear = Gearhead.gear_for(request)
|
|
65
63
|
return @gear if @gear
|
|
66
64
|
|
|
67
|
-
if @gear.nil?
|
|
68
|
-
|
|
69
|
-
end
|
|
70
|
-
if @gear == false
|
|
71
|
-
error!("Gear already mounted somewhere else.", 500)
|
|
72
|
-
end
|
|
65
|
+
error!("Can't find or infer gear.", 404) if @gear.nil?
|
|
66
|
+
error!('Gear already mounted somewhere else.', 500) if @gear == false
|
|
73
67
|
end
|
|
74
68
|
|
|
75
69
|
# remember that request method is from rack so GET/POST/etc.
|
|
76
70
|
def check_collection_actions!
|
|
77
71
|
action = @gear._gear_collection_actions[request.request_method][params[:resource_id].to_sym]
|
|
78
|
-
if action
|
|
79
|
-
return render json: instance_exec(&action)
|
|
80
|
-
end
|
|
72
|
+
return render json: instance_exec(&action) if action
|
|
81
73
|
end
|
|
82
74
|
|
|
83
75
|
def find_resource!
|
|
84
76
|
@resource = ::Gearhead::ResourceFinder.for(@gear, params)
|
|
85
|
-
|
|
77
|
+
if @resource.nil?
|
|
78
|
+
error!("#{@gear.resource.name} not found for #{@gear._gear_param_key} #{params[:resource_id]}")
|
|
79
|
+
end
|
|
86
80
|
end
|
|
87
81
|
|
|
88
82
|
def ensure_action_enabled!
|
|
89
83
|
unless @gear.action_enabled?(action_name.to_sym)
|
|
90
|
-
error!("Action not allowed for #{@gear.resource.name}##{action_name}",
|
|
84
|
+
error!("Action not allowed for #{@gear.resource.name}##{action_name}", :method_not_allowed)
|
|
91
85
|
end
|
|
92
86
|
end
|
|
93
87
|
|
|
94
88
|
def error!(msg, code = 400)
|
|
95
|
-
render json: Serializers::Lookup.for(:invalid_request).new(request, msg, code)
|
|
89
|
+
render json: Serializers::Lookup.for(:invalid_request).new(request, msg, code)
|
|
96
90
|
end
|
|
97
91
|
end
|
|
98
92
|
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module Gearhead
|
|
2
|
+
module Serializers
|
|
3
|
+
module ActiveModelSerializers
|
|
4
|
+
class CollectionSerializer
|
|
5
|
+
def self.for(records, serializer, options = {})
|
|
6
|
+
options[:each_serializer] = serializer
|
|
7
|
+
::ActiveModelSerializers::SerializableResource.new(records, options)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -3,10 +3,16 @@ module Gearhead
|
|
|
3
3
|
module ActiveModelSerializers
|
|
4
4
|
class ResourceSerializer
|
|
5
5
|
def self.for(page)
|
|
6
|
-
if defined?(
|
|
7
|
-
klass = Class.new(
|
|
6
|
+
if defined?(ActiveModel::Serializer)
|
|
7
|
+
klass = Class.new(ActiveModel::Serializer)
|
|
8
8
|
klass.attributes *(page._gear_attributes.presence || page.default_attributes)
|
|
9
9
|
|
|
10
|
+
page._gear_custom_attributes.each do |attr, block|
|
|
11
|
+
klass.attribute attr do |klass|
|
|
12
|
+
block.call(klass.object)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
10
16
|
klass
|
|
11
17
|
end
|
|
12
18
|
end
|
|
@@ -8,6 +8,12 @@ module Gearhead
|
|
|
8
8
|
klass.set_type page.resource.model_name.singular_route_key.to_param
|
|
9
9
|
klass.attributes *(page._gear_attributes.presence || page.default_attributes)
|
|
10
10
|
|
|
11
|
+
page._gear_custom_attributes.each do |attr, block|
|
|
12
|
+
klass.attribute attr do |object|
|
|
13
|
+
block.call(object)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
11
17
|
klass
|
|
12
18
|
end
|
|
13
19
|
end
|
|
@@ -1,26 +1,24 @@
|
|
|
1
1
|
module Gearhead
|
|
2
2
|
module Serializers
|
|
3
3
|
class Lookup
|
|
4
|
-
def self.for(
|
|
5
|
-
new(
|
|
4
|
+
def self.for(type, adapter_name = ::Gearhead.config.serialization.adapter)
|
|
5
|
+
new(type, adapter_name).serializer
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
attr_reader :adapter_name
|
|
9
|
+
def initialize(type, adapter_name)
|
|
10
|
+
@type = type.to_s
|
|
11
|
+
@adapter_name = adapter_name
|
|
10
12
|
end
|
|
11
13
|
|
|
12
14
|
def serializer
|
|
13
|
-
"::Gearhead::Serializers::#{adapter}::#{@
|
|
15
|
+
"::Gearhead::Serializers::#{adapter}::#{@type.classify}Serializer".constantize
|
|
14
16
|
end
|
|
15
17
|
|
|
16
18
|
private
|
|
17
19
|
|
|
18
|
-
def adapter_name
|
|
19
|
-
::Gearhead.config.serialization.adapter
|
|
20
|
-
end
|
|
21
|
-
|
|
22
20
|
def adapter
|
|
23
|
-
adapter_name.to_s.
|
|
21
|
+
adapter_name.to_s.camelcase
|
|
24
22
|
end
|
|
25
23
|
end
|
|
26
24
|
end
|
data/lib/gearhead/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: gearhead
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Josh
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-09-
|
|
11
|
+
date: 2020-09-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -148,28 +148,28 @@ dependencies:
|
|
|
148
148
|
requirements:
|
|
149
149
|
- - "~>"
|
|
150
150
|
- !ruby/object:Gem::Version
|
|
151
|
-
version: '
|
|
151
|
+
version: '2'
|
|
152
152
|
type: :runtime
|
|
153
153
|
prerelease: false
|
|
154
154
|
version_requirements: !ruby/object:Gem::Requirement
|
|
155
155
|
requirements:
|
|
156
156
|
- - "~>"
|
|
157
157
|
- !ruby/object:Gem::Version
|
|
158
|
-
version: '
|
|
158
|
+
version: '2'
|
|
159
159
|
- !ruby/object:Gem::Dependency
|
|
160
160
|
name: pagy
|
|
161
161
|
requirement: !ruby/object:Gem::Requirement
|
|
162
162
|
requirements:
|
|
163
163
|
- - "~>"
|
|
164
164
|
- !ruby/object:Gem::Version
|
|
165
|
-
version: '
|
|
165
|
+
version: '3.5'
|
|
166
166
|
type: :runtime
|
|
167
167
|
prerelease: false
|
|
168
168
|
version_requirements: !ruby/object:Gem::Requirement
|
|
169
169
|
requirements:
|
|
170
170
|
- - "~>"
|
|
171
171
|
- !ruby/object:Gem::Version
|
|
172
|
-
version: '
|
|
172
|
+
version: '3.5'
|
|
173
173
|
- !ruby/object:Gem::Dependency
|
|
174
174
|
name: zeitwerk
|
|
175
175
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -194,9 +194,6 @@ files:
|
|
|
194
194
|
- MIT-LICENSE
|
|
195
195
|
- README.md
|
|
196
196
|
- Rakefile
|
|
197
|
-
- app/controllers/gearhead/application_controller.rb
|
|
198
|
-
- app/controllers/gearhead/gears_controller.rb
|
|
199
|
-
- config/routes.rb
|
|
200
197
|
- lib/gearhead.rb
|
|
201
198
|
- lib/gearhead/actions/create.rb
|
|
202
199
|
- lib/gearhead/actions/index.rb
|
|
@@ -218,6 +215,7 @@ files:
|
|
|
218
215
|
- lib/gearhead/gear.rb
|
|
219
216
|
- lib/gearhead/gear_lookup.rb
|
|
220
217
|
- lib/gearhead/gearbox.rb
|
|
218
|
+
- lib/gearhead/gears_controller.rb
|
|
221
219
|
- lib/gearhead/paginators/lookup.rb
|
|
222
220
|
- lib/gearhead/paginators/paginator.rb
|
|
223
221
|
- lib/gearhead/paginators/pagy_paginator.rb
|
|
@@ -226,9 +224,11 @@ files:
|
|
|
226
224
|
- lib/gearhead/registry.rb
|
|
227
225
|
- lib/gearhead/resource_finder.rb
|
|
228
226
|
- lib/gearhead/router.rb
|
|
227
|
+
- lib/gearhead/serializers/active_model_serializers/collection_serializer.rb
|
|
229
228
|
- lib/gearhead/serializers/active_model_serializers/invalid_request_serializer.rb
|
|
230
229
|
- lib/gearhead/serializers/active_model_serializers/invalid_resource_serializer.rb
|
|
231
230
|
- lib/gearhead/serializers/active_model_serializers/resource_serializer.rb
|
|
231
|
+
- lib/gearhead/serializers/fast_jsonapi/collection_serializer.rb
|
|
232
232
|
- lib/gearhead/serializers/fast_jsonapi/invalid_request_serializer.rb
|
|
233
233
|
- lib/gearhead/serializers/fast_jsonapi/invalid_resource_serializer.rb
|
|
234
234
|
- lib/gearhead/serializers/fast_jsonapi/resource_serializer.rb
|
data/config/routes.rb
DELETED