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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +85 -84
  3. data/.ruby-version +1 -1
  4. data/CHANGELOG.md +10 -0
  5. data/Gemfile +21 -1
  6. data/README.md +15 -20
  7. data/introspective_grape.gemspec +41 -63
  8. data/lib/introspective_grape/api.rb +22 -12
  9. data/lib/introspective_grape/camel_snake.rb +3 -3
  10. data/lib/introspective_grape/create_helpers.rb +1 -1
  11. data/lib/introspective_grape/filters.rb +5 -3
  12. data/lib/introspective_grape/route.rb +11 -0
  13. data/lib/introspective_grape/traversal.rb +56 -56
  14. data/lib/introspective_grape/validators.rb +5 -4
  15. data/lib/introspective_grape/version.rb +1 -1
  16. data/lib/introspective_grape.rb +1 -0
  17. data/spec/dummy/Gemfile +4 -2
  18. data/spec/dummy/app/api/{api_helpers.rb → authentication_helper.rb} +2 -1
  19. data/spec/dummy/app/api/dummy/chat_api.rb +1 -1
  20. data/spec/dummy/app/api/dummy/company_api.rb +1 -1
  21. data/spec/dummy/app/api/dummy/location_api.rb +1 -1
  22. data/spec/dummy/app/api/dummy/project_api.rb +2 -2
  23. data/spec/dummy/app/api/dummy/role_api.rb +1 -1
  24. data/spec/dummy/app/api/dummy/sessions.rb +2 -2
  25. data/spec/dummy/app/api/dummy/user_api.rb +1 -1
  26. data/spec/dummy/app/api/dummy_api.rb +5 -6
  27. data/spec/dummy/app/api/error_handlers.rb +6 -6
  28. data/spec/dummy/app/api/permissions_helper.rb +1 -1
  29. data/spec/dummy/app/helpers/current.rb +3 -0
  30. data/spec/dummy/app/models/abstract_adapter.rb +11 -8
  31. data/spec/dummy/app/models/chat_message.rb +1 -1
  32. data/spec/dummy/app/models/chat_user.rb +1 -1
  33. data/spec/dummy/app/models/company.rb +3 -2
  34. data/spec/dummy/app/models/location.rb +1 -1
  35. data/spec/dummy/app/models/role.rb +1 -1
  36. data/spec/dummy/app/models/team.rb +5 -0
  37. data/spec/dummy/app/models/user/chatter.rb +2 -2
  38. data/spec/dummy/app/models/user.rb +2 -0
  39. data/spec/dummy/bin/bundle +1 -1
  40. data/spec/dummy/bin/rails +1 -1
  41. data/spec/dummy/bin/setup +20 -13
  42. data/spec/dummy/bin/update +31 -0
  43. data/spec/dummy/bin/yarn +11 -0
  44. data/spec/dummy/config/application.rb +17 -24
  45. data/spec/dummy/config/boot.rb +2 -5
  46. data/spec/dummy/config/environment.rb +1 -7
  47. data/spec/dummy/config/environments/development.rb +28 -16
  48. data/spec/dummy/config/environments/production.rb +27 -25
  49. data/spec/dummy/config/environments/test.rb +13 -10
  50. data/spec/dummy/config/initializers/application_controller_renderer.rb +8 -0
  51. data/spec/dummy/config/initializers/assets.rb +6 -3
  52. data/spec/dummy/config/initializers/content_security_policy.rb +25 -0
  53. data/spec/dummy/config/initializers/cookies_serializer.rb +2 -0
  54. data/spec/dummy/config/initializers/new_framework_defaults_5_2.rb +38 -0
  55. data/spec/dummy/config/initializers/wrap_parameters.rb +2 -2
  56. data/spec/dummy/config/locales/en.yml +10 -0
  57. data/spec/dummy/config/routes.rb +1 -1
  58. data/spec/dummy/config/storage.yml +34 -0
  59. data/spec/models/image_spec.rb +1 -5
  60. data/spec/rails_helper.rb +1 -2
  61. data/spec/requests/chat_api_spec.rb +1 -1
  62. data/spec/requests/company_api_spec.rb +1 -1
  63. data/spec/requests/location_api_spec.rb +1 -1
  64. data/spec/requests/project_api_spec.rb +5 -2
  65. data/spec/requests/role_api_spec.rb +1 -1
  66. data/spec/requests/user_api_spec.rb +2 -2
  67. data/spec/support/request_helpers.rb +4 -3
  68. metadata +23 -343
  69. data/spec/dummy/.ruby-version +0 -1
  70. data/spec/dummy/config/initializers/inflections.rb +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d29e073d96e9a6f2569eeaec65ece289f344fd5f0b6ea88a0dfb345d36d51052
4
- data.tar.gz: dac77dd6bc6812de00ec06ee5299c5cea5ff0f3539a304e6a1d1335f72e69f36
3
+ metadata.gz: 6ec4b919395ffd2b409a4a4b93f223aa10406fef2886f33cc5b8d9ec89e3822b
4
+ data.tar.gz: 7269f346109569e44df72beed6f00a5b2c62cf1f50efb657b43764a5304e8860
5
5
  SHA512:
6
- metadata.gz: 118befdc8fca693dd91610d8c0ecff86ca2e297cdb1b3817384b1fa78958a5949f1d252cc70eadf2187bee87080fb9949382e656b6765f259f4d23bba7fd2c47
7
- data.tar.gz: 21f3339a6e874bca7d94fa3efcd92812afbbc0e9b74371cafc8eb3e1644334930671ee59841a13237998272acc06954916a5b09ccd9eb760df38c8b3a28557f9
6
+ metadata.gz: 27141bf2c3082bef253ef90f838fc272600ef87e9c6767bd93acf7f2007beaa97c9e995d0a7e563ee2595945eb38e1ff93fbe3a445d6cb0182cfdcbf7b092885
7
+ data.tar.gz: 91c5267b99ce330cd04c09843822085c8c3917fb718537d516d769be75f23c3a40618442037e55800f57d6139df95ec4e12a647c3e100d7d6244a9e9c84bd893
data/.rubocop.yml CHANGED
@@ -1,84 +1,85 @@
1
- AllCops:
2
- NewCops: enable
3
- Exclude:
4
- - 'spec/**/*'
5
- - 'db/**/*'
6
- - 'Gemfile'
7
- - 'vendor/**/*' # or vendor/bundle/**/*
8
-
9
- Gemspec/OrderedDependencies:
10
- Enabled: false # I like to group them, so what?
11
-
12
- Metrics/BlockLength:
13
- Max: 30
14
-
15
- Metrics/MethodLength:
16
- Max: 30
17
-
18
- Metrics/AbcSize:
19
- Max: 20
20
-
21
- Metrics/PerceivedComplexity:
22
- Max: 12
23
-
24
- Metrics/CyclomaticComplexity:
25
- Max: 12
26
-
27
- Layout/EndOfLine:
28
- Enabled: false
29
-
30
- Layout/ExtraSpacing:
31
- Enabled: false
32
-
33
- Layout/HashAlignment:
34
- Enabled: false
35
-
36
- Layout/LineLength:
37
- Enabled: false
38
-
39
- Layout/SpaceAroundEqualsInParameterDefault:
40
- # I like to space repeated grammars out tabulated, defund these cops
41
- Enabled: false
42
-
43
- Layout/EmptyLinesAroundExceptionHandlingKeywords:
44
- Enabled: false
45
-
46
- Layout/SpaceInsideBlockBraces:
47
- Enabled: false
48
-
49
- Layout/SpaceInsideParens:
50
- Enabled: false
51
-
52
- Layout/SpaceAroundOperators:
53
- Enabled: false
54
-
55
- Lint/EmptyBlock:
56
- Enabled: false
57
-
58
- Style/BlockDelimiters:
59
- Enabled: false
60
-
61
- Style/FrozenStringLiteralComment:
62
- Enabled: false
63
-
64
- Style/Documentation:
65
- Enabled: false
66
-
67
- Style/RaiseArgs:
68
- Enabled: false
69
-
70
- Style/RedundantBegin:
71
- Enabled: false
72
-
73
- Style/RescueModifier:
74
- Enabled: false
75
-
76
- Style/OptionalBooleanParameter:
77
- Enabled: false
78
-
79
- Style/PercentLiteralDelimiters:
80
- # the cops change this preference every version of ruby, but who cares in the first place?
81
- Enabled: false
82
-
83
- Style/MultilineBlockChain:
84
- Enabled: false
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
- 2.7.3
1
+ 3.3.1
data/CHANGELOG.md CHANGED
@@ -1,4 +1,14 @@
1
1
 
2
+ 0.7.0 08/27/2025
3
+ ================
4
+
5
+ Support for Ruby > 3, Rails 7.2+.
6
+
7
+ 0.6.0 07/21/2022
8
+ ================
9
+
10
+ Support for Rails >6.
11
+
2
12
  0.5.7 03/10/2022
3
13
  ================
4
14
 
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 the introspection of your database by
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 the same.
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 also makes it easy to snakecase incoming parameters and camelize outputs, all the way through to your swagger docs.
29
-
30
- NOTE: SchemaPlus is not currently being maintained and is unavailable for Rails > 2.5, and thus so is
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 patches Grape::Swagger to camelize your API's self-documentation, while snakecasing parameters passed to your API.
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 need to disable all camel-snake transliteration set `IntrospectiveGrape.config.camelize_parameters = false` down in `config/initializers` and do not `require` or `formatter` those patches.
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 MyModelAPI < IntrospectiveGrape::API
88
+ class MyModelApi < IntrospectiveGrape::API
94
89
  filter_on :all
95
90
 
96
- restful MyModel, [:strong, :param, :fields, :and, { nested_model_attributes: [:nested,:fields, :_destroy] }]
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 MyModelAPI class for grape-entity definitions. If you prefer to define your entities elsewhere you could inherit them here instead.
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 loading errors.
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.
@@ -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
- 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
-
22
- s.files = `git ls-files`.split("\n").sort
23
- s.test_files = `git ls-files -- spec/*`.split("\n")
24
-
25
- s.required_ruby_version = '> 2.5'
26
-
27
- s.add_runtime_dependency 'rails', '~> 5.2'
28
- s.add_runtime_dependency 'schema_validations'
29
- s.add_runtime_dependency 'rack'
30
-
31
- s.add_runtime_dependency 'grape', '1.6.0'
32
- s.add_runtime_dependency 'dry-types'
33
- s.add_runtime_dependency 'grape-entity'
34
- s.add_runtime_dependency 'grape-swagger'
35
-
36
- s.add_runtime_dependency 'kaminari'
37
- s.add_runtime_dependency 'grape-kaminari'
38
-
39
- s.add_runtime_dependency 'pundit'
40
-
41
- s.add_runtime_dependency 'camel_snake_keys', '>0.0.4'
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(child)
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 ActiveRecord::Migration.check_pending! rescue return end
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 = strong_params.blank? ? model.attribute_names.map(&:to_sym) - %i(id updated_at created_at) : 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.update_attributes!( safe_params(params).permit(klass.whitelist) )
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..-1], attr)
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 OpenStruct.new(klass: self, name: name, param: "#{name}_attributes", model: model,
295
- many?: plural?(parent_model, reflection),
296
- key: "#{name.singularize}_id".to_sym,
297
- swagger_key: swagger_key, reflection: reflection)
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
- (model && PLURAL_REFLECTIONS.include?(reflection.class))
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(/Destroy/, '_destroy')
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(*args)
38
- param[:name] = param[:name].camelize(:lower).gsub(/Destroy/, '_destroy')
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.update_attributes( dsl.send(:safe_params, params).permit(whitelist) )
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: Array[String], coerce_with: ->(val) { val.split(',') }, description: 'Filter by a comma separated list of unique identifiers.'
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
- JSON of conditions for query. If you're familiar with ActiveRecord's query conventions you can build more complex filters, i.e. against included child associations, e.g.: {\"&lt;association_name&gt;_&lt;parent&gt;\":{\"field\":\"value\"}}
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.: {"&lt;association_name&gt;_&lt;parent&gt;":{"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.each do |filter, _details|
111
+ klass.custom_filters.each_key do |filter|
110
112
  records = records.send(filter, params[filter])
111
113
  end
112
114
 
@@ -0,0 +1,11 @@
1
+ class Route
2
+ attr_accessor(*%i[klass name param model many key swagger_key reflection])
3
+
4
+ def initialize(attrs = {})
5
+ attrs.each { |key, value| instance_variable_set("@#{key}", value) }
6
+ end
7
+
8
+ def many?
9
+ many ? true : false
10
+ end
11
+ end