introspective_grape 0.5.7 → 0.7.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/.rubocop.yml +85 -84
- data/.ruby-version +1 -1
- data/CHANGELOG.md +10 -0
- data/Gemfile +21 -1
- data/README.md +15 -20
- data/introspective_grape.gemspec +41 -63
- data/lib/introspective_grape/api.rb +22 -12
- data/lib/introspective_grape/camel_snake.rb +3 -3
- data/lib/introspective_grape/create_helpers.rb +1 -1
- data/lib/introspective_grape/filters.rb +5 -3
- data/lib/introspective_grape/route.rb +11 -0
- data/lib/introspective_grape/traversal.rb +56 -56
- data/lib/introspective_grape/validators.rb +5 -4
- data/lib/introspective_grape/version.rb +1 -1
- data/lib/introspective_grape.rb +1 -0
- data/spec/dummy/Gemfile +4 -2
- data/spec/dummy/app/api/{api_helpers.rb → authentication_helper.rb} +2 -1
- data/spec/dummy/app/api/dummy/chat_api.rb +1 -1
- data/spec/dummy/app/api/dummy/company_api.rb +1 -1
- data/spec/dummy/app/api/dummy/location_api.rb +1 -1
- data/spec/dummy/app/api/dummy/project_api.rb +2 -2
- data/spec/dummy/app/api/dummy/role_api.rb +1 -1
- data/spec/dummy/app/api/dummy/sessions.rb +2 -2
- data/spec/dummy/app/api/dummy/user_api.rb +1 -1
- data/spec/dummy/app/api/dummy_api.rb +5 -6
- data/spec/dummy/app/api/error_handlers.rb +6 -6
- data/spec/dummy/app/api/permissions_helper.rb +1 -1
- data/spec/dummy/app/helpers/current.rb +3 -0
- data/spec/dummy/app/models/abstract_adapter.rb +11 -8
- data/spec/dummy/app/models/chat_message.rb +1 -1
- data/spec/dummy/app/models/chat_user.rb +1 -1
- data/spec/dummy/app/models/company.rb +3 -2
- data/spec/dummy/app/models/location.rb +1 -1
- data/spec/dummy/app/models/role.rb +1 -1
- data/spec/dummy/app/models/team.rb +5 -0
- data/spec/dummy/app/models/user/chatter.rb +2 -2
- data/spec/dummy/app/models/user.rb +2 -0
- data/spec/dummy/bin/bundle +1 -1
- data/spec/dummy/bin/rails +1 -1
- data/spec/dummy/bin/setup +20 -13
- data/spec/dummy/bin/update +31 -0
- data/spec/dummy/bin/yarn +11 -0
- data/spec/dummy/config/application.rb +17 -24
- data/spec/dummy/config/boot.rb +2 -5
- data/spec/dummy/config/environment.rb +1 -7
- data/spec/dummy/config/environments/development.rb +28 -16
- data/spec/dummy/config/environments/production.rb +27 -25
- data/spec/dummy/config/environments/test.rb +13 -10
- data/spec/dummy/config/initializers/application_controller_renderer.rb +8 -0
- data/spec/dummy/config/initializers/assets.rb +6 -3
- data/spec/dummy/config/initializers/content_security_policy.rb +25 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +2 -0
- data/spec/dummy/config/initializers/new_framework_defaults_5_2.rb +38 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +2 -2
- data/spec/dummy/config/locales/en.yml +10 -0
- data/spec/dummy/config/routes.rb +1 -1
- data/spec/dummy/config/storage.yml +34 -0
- data/spec/models/image_spec.rb +1 -5
- data/spec/rails_helper.rb +1 -2
- data/spec/requests/chat_api_spec.rb +1 -1
- data/spec/requests/company_api_spec.rb +1 -1
- data/spec/requests/location_api_spec.rb +1 -1
- data/spec/requests/project_api_spec.rb +5 -2
- data/spec/requests/role_api_spec.rb +1 -1
- data/spec/requests/user_api_spec.rb +2 -2
- data/spec/support/request_helpers.rb +4 -3
- metadata +23 -343
- data/spec/dummy/.ruby-version +0 -1
- data/spec/dummy/config/initializers/inflections.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6ec4b919395ffd2b409a4a4b93f223aa10406fef2886f33cc5b8d9ec89e3822b
|
4
|
+
data.tar.gz: 7269f346109569e44df72beed6f00a5b2c62cf1f50efb657b43764a5304e8860
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27141bf2c3082bef253ef90f838fc272600ef87e9c6767bd93acf7f2007beaa97c9e995d0a7e563ee2595945eb38e1ff93fbe3a445d6cb0182cfdcbf7b092885
|
7
|
+
data.tar.gz: 91c5267b99ce330cd04c09843822085c8c3917fb718537d516d769be75f23c3a40618442037e55800f57d6139df95ec4e12a647c3e100d7d6244a9e9c84bd893
|
data/.rubocop.yml
CHANGED
@@ -1,84 +1,85 @@
|
|
1
|
-
AllCops:
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
- '
|
6
|
-
- '
|
7
|
-
- '
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 3.1
|
3
|
+
NewCops: enable
|
4
|
+
Exclude:
|
5
|
+
- 'spec/**/*'
|
6
|
+
- 'db/**/*'
|
7
|
+
- 'Gemfile'
|
8
|
+
- 'vendor/**/*' # or vendor/bundle/**/*
|
9
|
+
|
10
|
+
Gemspec/OrderedDependencies:
|
11
|
+
Enabled: false # I like to group them, so what?
|
12
|
+
|
13
|
+
Metrics/BlockLength:
|
14
|
+
Max: 30
|
15
|
+
|
16
|
+
Metrics/MethodLength:
|
17
|
+
Max: 30
|
18
|
+
|
19
|
+
Metrics/AbcSize:
|
20
|
+
Max: 20
|
21
|
+
|
22
|
+
Metrics/PerceivedComplexity:
|
23
|
+
Max: 12
|
24
|
+
|
25
|
+
Metrics/CyclomaticComplexity:
|
26
|
+
Max: 12
|
27
|
+
|
28
|
+
Layout/EndOfLine:
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
Layout/ExtraSpacing:
|
32
|
+
Enabled: false
|
33
|
+
|
34
|
+
Layout/HashAlignment:
|
35
|
+
Enabled: false
|
36
|
+
|
37
|
+
Layout/LineLength:
|
38
|
+
Enabled: false
|
39
|
+
|
40
|
+
Layout/SpaceAroundEqualsInParameterDefault:
|
41
|
+
# I like to space repeated grammars out tabulated, defund these cops
|
42
|
+
Enabled: false
|
43
|
+
|
44
|
+
Layout/EmptyLinesAroundExceptionHandlingKeywords:
|
45
|
+
Enabled: false
|
46
|
+
|
47
|
+
Layout/SpaceInsideBlockBraces:
|
48
|
+
Enabled: false
|
49
|
+
|
50
|
+
Layout/SpaceInsideParens:
|
51
|
+
Enabled: false
|
52
|
+
|
53
|
+
Layout/SpaceAroundOperators:
|
54
|
+
Enabled: false
|
55
|
+
|
56
|
+
Lint/EmptyBlock:
|
57
|
+
Enabled: false
|
58
|
+
|
59
|
+
Style/BlockDelimiters:
|
60
|
+
Enabled: false
|
61
|
+
|
62
|
+
Style/FrozenStringLiteralComment:
|
63
|
+
Enabled: false
|
64
|
+
|
65
|
+
Style/Documentation:
|
66
|
+
Enabled: false
|
67
|
+
|
68
|
+
Style/RaiseArgs:
|
69
|
+
Enabled: false
|
70
|
+
|
71
|
+
Style/RedundantBegin:
|
72
|
+
Enabled: false
|
73
|
+
|
74
|
+
Style/RescueModifier:
|
75
|
+
Enabled: false
|
76
|
+
|
77
|
+
Style/OptionalBooleanParameter:
|
78
|
+
Enabled: false
|
79
|
+
|
80
|
+
Style/PercentLiteralDelimiters:
|
81
|
+
# the cops change this preference every version of ruby, but who cares in the first place?
|
82
|
+
Enabled: false
|
83
|
+
|
84
|
+
Style/MultilineBlockChain:
|
85
|
+
Enabled: false
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
3.3.1
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
gemspec
|
3
3
|
|
4
|
+
gem 'devise'
|
5
|
+
gem 'grape-entity'
|
6
|
+
gem 'grape-swagger'
|
7
|
+
gem 'validates_by_schema'
|
8
|
+
|
4
9
|
# Declare your gem's dependencies in introspective_grape.gemspec.
|
5
10
|
# Bundler will treat runtime dependencies like base dependencies, and
|
6
11
|
# development dependencies will be added by default to the :development group.
|
@@ -11,8 +16,23 @@ gemspec
|
|
11
16
|
# Git. Remember to move these dependencies to your gemspec before releasing
|
12
17
|
# your gem to rubygems.org.
|
13
18
|
|
19
|
+
|
14
20
|
group :development, :test do
|
21
|
+
# testing
|
22
|
+
gem 'brakeman'
|
23
|
+
gem 'bundler-audit'
|
15
24
|
gem 'byebug'
|
16
|
-
gem 'rb-readline'
|
17
25
|
gem 'coveralls_reborn', require: false
|
26
|
+
gem 'machinist_redux'
|
27
|
+
gem 'rb-readline'
|
28
|
+
gem 'rspec-rails', '>= 3.0'
|
29
|
+
gem 'rubocop'
|
30
|
+
gem 'simplecov'
|
31
|
+
|
32
|
+
# dummy app dependencies
|
33
|
+
gem 'activerecord-jdbcsqlite3-adapter', platforms: :jruby
|
34
|
+
gem 'devise'
|
35
|
+
gem 'kt-paperclip'
|
36
|
+
gem 'rufus-mnemo'
|
37
|
+
gem 'sqlite3', platforms: :ruby
|
18
38
|
end
|
data/README.md
CHANGED
@@ -15,21 +15,18 @@
|
|
15
15
|
|
16
16
|
IntrospectiveGrape is a rails plugin for DRYing up
|
17
17
|
[Grape APIs](https://github.com/ruby-grape/grape) by laying out simple
|
18
|
-
(or, if you like, very complex) RESTful defaults based on
|
19
|
-
[SchemaPlusValidations](https://github.com/SchemaPlus/schema_validations).
|
18
|
+
(or, if you like, very complex) RESTful defaults based on your database schema.
|
20
19
|
|
21
20
|
IntrospectiveGrape provides handling for deeply nested relations according to the models'
|
22
21
|
`accepts_nested_attributes_for` declarations, generating all the necessary
|
23
|
-
boilerplate for flexible and consistent bulk endpoints on plural associations
|
24
|
-
and building nested routes for
|
22
|
+
boilerplate for flexible and consistent bulk endpoints on plural associations
|
23
|
+
and building the deeply nested routes for acting upon individual records.
|
25
24
|
|
26
25
|
It relies on [Kaminari](https://github.com/kaminari/kaminari) for pagination and [Pundit](https://github.com/varvet/pundit) for authorization, both of which are semi-optional.
|
27
26
|
|
28
|
-
To facilitate idiomatic ruby and javascript, respectively, it
|
29
|
-
|
30
|
-
|
31
|
-
IntrospectiveGrape. Which is too bad! I don't know how anybody with a relational database gets by
|
32
|
-
without it. We're working on it when we get the chance.
|
27
|
+
To facilitate idiomatic ruby and javascript, respectively, it makes it trivial to snakecase
|
28
|
+
incoming parameters and camelize outputs, all the way through to your automatically generated
|
29
|
+
swagger documentation.
|
33
30
|
|
34
31
|
## Documentation
|
35
32
|
|
@@ -54,11 +51,9 @@ class MyAPI < Grape::API
|
|
54
51
|
end
|
55
52
|
```
|
56
53
|
|
57
|
-
This also monkey
|
58
|
-
|
59
|
-
To include this behavior in your test coverage you need to either access the API's params hash or you can format the response body to `JSON.parse(response.body).with_snake_keys` in a helper method with the `using CamelSnakeKeys` refinement.
|
54
|
+
This also monkey-patches Grape::Swagger to camelize your API's self-documentation, while snakecasing parameters passed to your API.
|
60
55
|
|
61
|
-
If you
|
56
|
+
If you prefer to disable all camel-snake transliterations set `IntrospectiveGrape.config.camelize_parameters = false` down in `config/initializers`.
|
62
57
|
|
63
58
|
## Authentication and authorization
|
64
59
|
|
@@ -70,7 +65,7 @@ IntrospectiveGrape::API.authentication_method = "whatever!"
|
|
70
65
|
|
71
66
|
Pundit authorization is invoked against index?, show?, update?, create?, and destroy? methods with the model instance in question (or a new instance in the case of index).
|
72
67
|
|
73
|
-
The joke goes that you may find you need to allow an unauthenticated user to attempt a log in, which can be handled with something like:
|
68
|
+
The joke goes that you may find you need to allow an unauthenticated user to attempt a log in, which can be handled by authorizing non-users at that endpoint with something like:
|
74
69
|
|
75
70
|
```
|
76
71
|
def authorize!
|
@@ -90,10 +85,10 @@ IntrospectiveGrape's parameterization of a model begins with the `restful` decla
|
|
90
85
|
The simplest app/api/v1/my_model_api.rb with the broadest functionality would look like:
|
91
86
|
|
92
87
|
```
|
93
|
-
class
|
88
|
+
class MyModelApi < IntrospectiveGrape::API
|
94
89
|
filter_on :all
|
95
90
|
|
96
|
-
restful MyModel, [:strong, :param, :fields, :and, { nested_model_attributes: [:nested
|
91
|
+
restful MyModel, [:strong, :param, :fields, :and, { nested_model_attributes: [:nested, :fields, :_destroy] }]
|
97
92
|
|
98
93
|
class <NestedModel>Entity < Grape::Entity
|
99
94
|
expose :id, :attribute
|
@@ -109,9 +104,9 @@ end
|
|
109
104
|
|
110
105
|
This would set up all the basic RESTFUL actions with nested routes for the associated model and its association, providing a good deal of flexibility for API consumers out of the box.
|
111
106
|
|
112
|
-
IntrospectiveGrape looks in the
|
107
|
+
IntrospectiveGrape looks in the `MyModelApi` class for grape-entity definitions. If you prefer to define your entities elsewhere you can import them here instead.
|
113
108
|
|
114
|
-
NOTE: Nested entities must be defined before their parents, inside-out, or you'll run into
|
109
|
+
NOTE: Nested entities defined in the mounted API classes must be defined before their parents, inside-out, or you'll run into load errors.
|
115
110
|
|
116
111
|
## Customizing End Points
|
117
112
|
|
@@ -146,8 +141,6 @@ class MyModelAPI < IntrospectiveGrape::API
|
|
146
141
|
end
|
147
142
|
```
|
148
143
|
|
149
|
-
Please note, again, that the nested Grape::Entity is declared before its parent.
|
150
|
-
|
151
144
|
## Skipping a Presence Validation for a Required Field
|
152
145
|
|
153
146
|
If a model has, say, a procedurally generated default for a not-null field in the database
|
@@ -179,6 +172,8 @@ You can also eager load nested associations, if necessary:
|
|
179
172
|
default_includes NestedModel, <associations for eager loading>
|
180
173
|
```
|
181
174
|
|
175
|
+
My suggestion would be to ignore this feature and rely instead on [ArLazyPreload](https://github.com/DmitryTsepelev/ar_lazy_preload).
|
176
|
+
|
182
177
|
## Pagination
|
183
178
|
|
184
179
|
The index action by default will not be paginated. Simply declaring `paginate` before the `restful` declaration will enable [Kaminari](https://github.com/amatsuda/kaminari) pagination on the index results using a default 25 results per page with an offset of 0. You can pass Kaminari's options to the paginate declaration, `per_page`, `max_per_page`, etc.
|
data/introspective_grape.gemspec
CHANGED
@@ -1,63 +1,41 @@
|
|
1
|
-
$LOAD_PATH.push File.expand_path('lib', __dir__)
|
2
|
-
|
3
|
-
# Maintain your gem's version:
|
4
|
-
require 'introspective_grape/version'
|
5
|
-
|
6
|
-
# Describe your gem and declare its dependencies:
|
7
|
-
Gem::Specification.new do |s|
|
8
|
-
s.name = 'introspective_grape'
|
9
|
-
s.version = IntrospectiveGrape::VERSION
|
10
|
-
s.authors = ['Josh Buermann']
|
11
|
-
s.email = ['buermann@gmail.com']
|
12
|
-
s.homepage = 'https://github.com/buermann/introspective_grape'
|
13
|
-
s.summary = 'Quickly configure Grape APIs around your database schema and models.'
|
14
|
-
s.description = <<-DESC
|
15
|
-
IntrospectiveGrape provides handling for deeply nested relations according to the models'
|
16
|
-
`accepts_nested_attributes_for` declarations, generating all the necessary
|
17
|
-
|
18
|
-
and building nested routes for the same.
|
19
|
-
DESC
|
20
|
-
s.license = 'MIT'
|
21
|
-
|
22
|
-
|
23
|
-
s.
|
24
|
-
|
25
|
-
s.required_ruby_version = '
|
26
|
-
|
27
|
-
s.
|
28
|
-
s.
|
29
|
-
|
30
|
-
|
31
|
-
s.
|
32
|
-
s.
|
33
|
-
s.
|
34
|
-
|
35
|
-
|
36
|
-
s.
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
if RUBY_PLATFORM == 'java'
|
44
|
-
s.add_development_dependency 'activerecord-jdbcsqlite3-adapter'
|
45
|
-
else
|
46
|
-
s.add_development_dependency 'sqlite3'
|
47
|
-
end
|
48
|
-
|
49
|
-
# testing gems
|
50
|
-
s.add_development_dependency 'rspec-rails', '>= 3.0'
|
51
|
-
s.add_development_dependency 'coveralls_reborn'
|
52
|
-
s.add_development_dependency 'simplecov'
|
53
|
-
s.add_development_dependency 'bundler-audit'
|
54
|
-
s.add_development_dependency 'brakeman'
|
55
|
-
s.add_development_dependency 'rubocop'
|
56
|
-
s.add_development_dependency 'byebug'
|
57
|
-
s.add_development_dependency 'machinist_redux'
|
58
|
-
|
59
|
-
# dummy app dependencies
|
60
|
-
s.add_development_dependency 'kt-paperclip'
|
61
|
-
s.add_development_dependency 'rufus-mnemo'
|
62
|
-
s.add_development_dependency 'devise'
|
63
|
-
end
|
1
|
+
$LOAD_PATH.push File.expand_path('lib', __dir__)
|
2
|
+
|
3
|
+
# Maintain your gem's version:
|
4
|
+
require 'introspective_grape/version'
|
5
|
+
|
6
|
+
# Describe your gem and declare its dependencies:
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = 'introspective_grape'
|
9
|
+
s.version = IntrospectiveGrape::VERSION
|
10
|
+
s.authors = ['Josh Buermann']
|
11
|
+
s.email = ['buermann@gmail.com']
|
12
|
+
s.homepage = 'https://github.com/buermann/introspective_grape'
|
13
|
+
s.summary = 'Quickly configure Grape APIs around your database schema and models.'
|
14
|
+
s.description = <<-DESC
|
15
|
+
IntrospectiveGrape provides handling for deeply nested relations according to the models'
|
16
|
+
`accepts_nested_attributes_for` declarations, generating all the necessary
|
17
|
+
boilerplate for flexible and consistent bulk endpoints on plural associations,
|
18
|
+
and building nested routes for the same.
|
19
|
+
DESC
|
20
|
+
s.license = 'MIT'
|
21
|
+
s.metadata = { 'rubygems_mfa_required' => 'true' }
|
22
|
+
|
23
|
+
s.files = `git ls-files`.split("\n").sort
|
24
|
+
|
25
|
+
s.required_ruby_version = '>= 3.1'
|
26
|
+
|
27
|
+
s.add_dependency 'rails' # , '6.1' #, '> 5.2'
|
28
|
+
s.add_dependency 'rack'
|
29
|
+
|
30
|
+
s.add_dependency 'grape' # , '1.6.0'
|
31
|
+
s.add_dependency 'dry-types'
|
32
|
+
s.add_dependency 'grape-entity'
|
33
|
+
s.add_dependency 'grape-swagger'
|
34
|
+
|
35
|
+
s.add_dependency 'kaminari'
|
36
|
+
s.add_dependency 'grape-kaminari'
|
37
|
+
|
38
|
+
s.add_dependency 'pundit'
|
39
|
+
|
40
|
+
s.add_dependency 'camel_snake_keys'
|
41
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'action_controller'
|
2
2
|
require 'kaminari'
|
3
|
-
#require 'byebug'
|
3
|
+
# require 'byebug'
|
4
4
|
require 'grape-kaminari'
|
5
5
|
require 'introspective_grape/validators'
|
6
6
|
|
@@ -57,7 +57,7 @@ module IntrospectiveGrape
|
|
57
57
|
PG2RUBY = { datetime: DateTime }.freeze
|
58
58
|
|
59
59
|
def inherited(child)
|
60
|
-
super
|
60
|
+
super
|
61
61
|
child.before do
|
62
62
|
# Ensure that a user is logged in.
|
63
63
|
send(IntrospectiveGrape::API.authentication_method(self))
|
@@ -85,12 +85,17 @@ module IntrospectiveGrape
|
|
85
85
|
#
|
86
86
|
|
87
87
|
# Defining the api will break pending migrations during db:migrate, so bail:
|
88
|
-
begin
|
88
|
+
begin
|
89
|
+
ActiveRecord::Migration.check_all_pending!
|
90
|
+
rescue StandardError => e
|
91
|
+
warn "Migrations are pending: #{e.message}"
|
92
|
+
return
|
93
|
+
end
|
89
94
|
|
90
95
|
# normalize the whitelist to symbols
|
91
96
|
strong_params.map! {|f| f.is_a?(String) ? f.to_sym : f }
|
92
97
|
# default to a flat representation of the model's attributes if left unspecified
|
93
|
-
strong_params =
|
98
|
+
strong_params = model.attribute_names.map(&:to_sym) - %i(id updated_at created_at) if strong_params.blank?
|
94
99
|
|
95
100
|
# The strong params will be the same for all routes, differing from the Grape params
|
96
101
|
# when routes are nested
|
@@ -199,7 +204,7 @@ module IntrospectiveGrape
|
|
199
204
|
dsl.put ":#{routes.last.swagger_key}" do
|
200
205
|
authorize @model, :update?
|
201
206
|
|
202
|
-
@model.
|
207
|
+
@model.update!( safe_params(params).permit(klass.whitelist) )
|
203
208
|
|
204
209
|
if IntrospectiveGrape.config.skip_object_reload
|
205
210
|
present klass.find_leaf(routes, @model, params), with: "#{klass}::#{model}Entity".constantize
|
@@ -210,7 +215,6 @@ module IntrospectiveGrape
|
|
210
215
|
end
|
211
216
|
end
|
212
217
|
|
213
|
-
# rubocop:enable Metrics/AbcSize
|
214
218
|
def define_destroy(dsl, routes, model, _api_params)
|
215
219
|
klass = routes.first.klass
|
216
220
|
name = routes.last.name.singularize
|
@@ -225,6 +229,7 @@ module IntrospectiveGrape
|
|
225
229
|
present status: (klass.find_leaf(routes, @model, params).destroy ? true : false)
|
226
230
|
end
|
227
231
|
end
|
232
|
+
# rubocop:enable Metrics/AbcSize
|
228
233
|
|
229
234
|
def convert_nested_params_hash(dsl, routes)
|
230
235
|
root = routes.first
|
@@ -245,7 +250,7 @@ module IntrospectiveGrape
|
|
245
250
|
|
246
251
|
def merge_nested_params(routes, params)
|
247
252
|
attr = params.reject {|k| [routes.first.key, :api_key].include?(k) }
|
248
|
-
build_nested_attributes(routes[1
|
253
|
+
build_nested_attributes(routes[1..], attr)
|
249
254
|
end
|
250
255
|
|
251
256
|
def define_restful_api(dsl, routes, model, api_params)
|
@@ -291,14 +296,19 @@ module IntrospectiveGrape
|
|
291
296
|
reflection = parent_model&.reflections&.fetch(reflection_name)
|
292
297
|
swagger_key = IntrospectiveGrape.config.camelize_parameters ? "#{name.singularize.camelize(:lower)}Id" : "#{name.singularize}_id"
|
293
298
|
|
294
|
-
routes.push
|
295
|
-
|
296
|
-
|
297
|
-
|
299
|
+
routes.push Route.new(
|
300
|
+
klass: self,
|
301
|
+
name: name,
|
302
|
+
param: "#{name}_attributes",
|
303
|
+
model: model,
|
304
|
+
many: plural?(parent_model, reflection),
|
305
|
+
key: :"#{name.singularize}_id",
|
306
|
+
swagger_key: swagger_key, reflection: reflection
|
307
|
+
)
|
298
308
|
end
|
299
309
|
|
300
310
|
def plural?(model, reflection)
|
301
|
-
|
311
|
+
model && PLURAL_REFLECTIONS.include?(reflection.class)
|
302
312
|
end
|
303
313
|
|
304
314
|
def build_nested_attributes(routes, hash)
|
@@ -11,7 +11,7 @@ if IntrospectiveGrape.config.camelize_parameters
|
|
11
11
|
parsed_params.each do |param|
|
12
12
|
param[:name] = param[:name]
|
13
13
|
.camelize(:lower)
|
14
|
-
.gsub(
|
14
|
+
.gsub('Destroy', '_destroy')
|
15
15
|
end
|
16
16
|
super(params, path, method, _options = {})
|
17
17
|
end
|
@@ -34,8 +34,8 @@ if IntrospectiveGrape.config.camelize_parameters
|
|
34
34
|
else
|
35
35
|
module CallWithCamelized
|
36
36
|
def call(*args)
|
37
|
-
param = super
|
38
|
-
param[:name] = param[:name].camelize(:lower).gsub(
|
37
|
+
param = super
|
38
|
+
param[:name] = param[:name].camelize(:lower).gsub('Destroy', '_destroy')
|
39
39
|
param
|
40
40
|
end
|
41
41
|
end
|
@@ -4,7 +4,7 @@ module IntrospectiveGrape
|
|
4
4
|
dsl.send(:authorize, model, :create?)
|
5
5
|
ActiveRecord::Base.transaction do
|
6
6
|
old = find_leaves(routes, model, params)
|
7
|
-
model.
|
7
|
+
model.update( dsl.send(:safe_params, params).permit(whitelist) )
|
8
8
|
new = find_leaves(routes, model, params)
|
9
9
|
old.respond_to?(:size) ? new - old : new
|
10
10
|
end
|
@@ -62,7 +62,7 @@ module IntrospectiveGrape
|
|
62
62
|
if timestamp_filter(klass, model, field)
|
63
63
|
dsl.optional field, type: klass.param_type(model, field), description: "Constrain #{field} by #{humanize_date_range(field)} date."
|
64
64
|
elsif identifier_filter?(model, field)
|
65
|
-
dsl.optional field, type:
|
65
|
+
dsl.optional field, type: [String], coerce_with: ->(val) { val.split(',') }, description: 'Filter by a comma separated list of unique identifiers.'
|
66
66
|
else
|
67
67
|
dsl.optional field, type: klass.param_type(model, field), description: "Filter on #{field} by value."
|
68
68
|
end
|
@@ -82,7 +82,9 @@ module IntrospectiveGrape
|
|
82
82
|
|
83
83
|
def filter_doc
|
84
84
|
<<-STR
|
85
|
-
|
85
|
+
JSON of conditions for query.
|
86
|
+
|
87
|
+
If you're familiar with ActiveRecord's query conventions you can build more complex filters, i.e. against included child associations, e.g.: {"<association_name>_<parent>":{"field":"value"}}
|
86
88
|
STR
|
87
89
|
end
|
88
90
|
|
@@ -106,7 +108,7 @@ module IntrospectiveGrape
|
|
106
108
|
records = apply_simple_filter(klass, model, params, records, field)
|
107
109
|
end
|
108
110
|
|
109
|
-
klass.custom_filters.
|
111
|
+
klass.custom_filters.each_key do |filter|
|
110
112
|
records = records.send(filter, params[filter])
|
111
113
|
end
|
112
114
|
|