graphqr 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 876e07cf3e0eb24c8d8c71f23b23e18ae3d014bc
4
- data.tar.gz: bcd24faba39f7be1b3a07ca3629bf6f680f10c25
3
+ metadata.gz: b962a2340faac84b6f9369947841074c52c34afa
4
+ data.tar.gz: 36fdff3a030711d367bd9d585228bf6f40755053
5
5
  SHA512:
6
- metadata.gz: 51f5c95b0ba53fe528e7e275bf6e00063c4d2cbd6add26bdc16cf41b0f2f2e6f4884e776108e8e4f3a522121ad0419863e50d111f0dadd0ce577d3611c524cf8
7
- data.tar.gz: cf5ff9b77895930d9d7bc9d8aa6adb3bdd494c34c6310139055e4ebb57e3403903810a197cd6f0098855dcfad2b0c275ec715bf21ef212569c7b7beeb9290bfa
6
+ metadata.gz: 5c68aeedd464b35f796312a9be00e7a909f3d99dea883637affde7a6ff349e44483326d5d6f5a5461ba7d5a191b2813f24403eebb7840b80e3b12e7b4d1d3509
7
+ data.tar.gz: 77739403805caf9a8974f16248a1da4bf392d08044e3a682fccb38e7e29697c1cf22d78fb6fd17a43242c359f8811c0a41739b82063896ffbe5a80d2fa7f3f75
data/README.md CHANGED
@@ -31,7 +31,7 @@ Or install it yourself as:
31
31
  GraphQR uses `pagy` and `pundit` by default and activates both `Authorization` and `Pagination` modules.
32
32
  If you'd like to create a specific configuration, create `config/initializers/graphql.rb` with
33
33
 
34
- ```
34
+ ```ruby
35
35
  GraphQR.configure do |config|
36
36
  config.use_pagination = true # or false to disable
37
37
  config.use_authorization = true # or false to disable
@@ -44,12 +44,20 @@ end
44
44
  ## Modules
45
45
 
46
46
  To use the extensions correctly add
47
+ ```ruby
48
+ field_class GraphQR::Fields::BaseField
47
49
  ```
48
- field_class GraphQR::Fields::BaseField
49
- ```
50
-
51
- to your `BaseObject` class. This will add the `paginate` options to your fields and add the necessary extensions according to the modules you activated.
50
+ to your `BaseObject` class. This will add the custom options to your fields and add the necessary extensions according to the modules you activated.
52
51
 
52
+ ```ruby
53
+ module Types
54
+ class BaseObject < GraphQL::Schema::Object
55
+ ...
56
+ field_class GraphQR::Fields::BaseField
57
+ ...
58
+ end
59
+ end
60
+ ```
53
61
  ### Pagination
54
62
 
55
63
  The Pagination module consists in a easier way of dealing with pages. Instead of using `cursors` we implemented a more Rails way using `per` and `page`.
@@ -57,16 +65,33 @@ Our implementation is (for now) based on [Pagy](https://github.com/ddnexus/pagy)
57
65
 
58
66
  To use the Pagination module add
59
67
 
60
- ```
68
+ ```ruby
69
+
61
70
  extend GraphQR::Pagination
62
71
  ```
63
72
 
64
73
  to any `GraphQL::Schema::Object` you'd like, but we recommend adding it to your `BaseObject` class.
65
74
 
75
+ ```ruby
76
+ module Types
77
+ class BaseObject < GraphQL::Schema::Object
78
+ ...
79
+ extend GraphQR::Pagination
80
+ ...
81
+ end
82
+ end
83
+ ```
84
+
66
85
  #### Usage
67
86
 
68
- ```
69
- field :users, UserType.pagination_type, paginate: true
87
+ ```ruby
88
+ module Types
89
+ class QueryType < Types::BaseObject
90
+ graphql_name 'Query'
91
+
92
+ field :users, UserType.pagination_type, paginate: true
93
+ end
94
+ end
70
95
  ```
71
96
 
72
97
  A `pagination_type` adds the `per` and `page` arguments and adds a `page_info` field to the response.
@@ -86,13 +111,23 @@ users(per: 10, page: 1) {
86
111
  The Authorization module in some wrappers around a `PolicyProvider` (only Pundit for now). And allows some basic behaviors.
87
112
  Everything on this module depends on a `policy_provider` passed to the GraphQL context. You can add it like this:
88
113
 
89
- ```
90
- context = {
91
- policy_provider: GraphQR::Policies::PunditProvider.new(policy_context: pundit_user)
114
+ ```ruby
115
+ class GraphqlController < ApplicationController
116
+
117
+ def execute
118
+ context = {
119
+ your_context,
120
+ policy_provider: policy_provider
121
+ }
122
+ result = YourSchema.execute(query, variables: variables, context: context, operation_name: operation_name)
123
+ render json: result.to_json
124
+ rescue StandardError => e
125
+ raise e unless Rails.env.development?
126
+
127
+ handle_error_in_development(e)
128
+ end
92
129
  ...
93
- }
94
-
95
- Schema.execute(query, variables: variables, context: context, operation_name: operation_name)
130
+ end
96
131
  ```
97
132
 
98
133
  #### Authorized
@@ -101,11 +136,21 @@ This module adds a check on the object policy before resolving it. It always sea
101
136
  It works by extending the `authorized?` method.
102
137
 
103
138
  To add this behavior, add
104
- ```
139
+ ```ruby
105
140
  extend GraphQR::Authorized
106
141
  ```
107
142
  to any `GraphQL::Schema::Object` you'd like, but we recommend adding it to your `BaseObject` class.
108
143
 
144
+ ```ruby
145
+ module Types
146
+ class BaseObject < GraphQL::Schema::Object
147
+ ...
148
+ extend GraphQR::Authorized
149
+ ...
150
+ end
151
+ end
152
+ ```
153
+
109
154
  Example:
110
155
 
111
156
  ```
@@ -125,11 +170,21 @@ If any policy returns falsy, the object is returned as `null`.
125
170
  This module adds the PolicyProvider scope to the fields that represent an `ActiveRecord::Relation`. It works by implementing the `self.scope_items` method.
126
171
 
127
172
  To add this behavior, add
128
- ```
173
+ ```ruby
129
174
  extend GraphQR::ScopeItems
130
175
  ```
131
176
  to any `GraphQL::Schema::Object` you'd like, but we recommend adding it to your `BaseObject` class.
132
177
 
178
+ ```ruby
179
+ module Types
180
+ class BaseObject < GraphQL::Schema::Object
181
+ ...
182
+ extend GraphQR::ScopeItems
183
+ ...
184
+ end
185
+ end
186
+ ```
187
+
133
188
  Example:
134
189
 
135
190
  ```
@@ -146,14 +201,22 @@ This module is a wrapper around the PolicyProvider authorization.
146
201
  It adds the `authorize_graphql` method, similar to Pundit's `authorize`, but it returns an `GraphQL::ExecutionError` instead of a `Pundit::NotAuthorizedError`
147
202
 
148
203
  To add this behavior, add
149
- ```
150
- include GraphQR::AuthorizeGraphQL
204
+ ```ruby
205
+ include GraphQR::Policies::AuthorizeGraphQL
151
206
  ```
152
207
  where you want to use this methos, but we recommend adding it to your `Mutations` and `Resolvers` classes.
153
208
 
209
+ ```ruby
210
+ class BaseResolver < GraphQL::Schema::Resolver
211
+ ...
212
+ include GraphQR::Policies::AuthorizeGraphQL
213
+ ...
214
+ end
215
+ ```
216
+
154
217
  Example:
155
218
 
156
- ```
219
+ ```ruby
157
220
  authorize_graphql User, :index?
158
221
  ```
159
222
 
@@ -167,14 +230,22 @@ This modules is based on the [has_scope](https://github.com/plataformatec/has_sc
167
230
  It provides an `apply_scopes` method that can search for model scopes and use them on a collection
168
231
 
169
232
  To add this method, add
170
- ```
233
+ ```ruby
171
234
  include GraphQR::ApplyScopes
172
235
  ```
173
236
  where you'd like to use it, but we recommend adding it to your `Resolvers`.
174
237
 
238
+ ```ruby
239
+ class BaseResolver < GraphQL::Schema::Resolver
240
+ ...
241
+ include GraphQR::ApplyScopes
242
+ ...
243
+ end
244
+ ```
245
+
175
246
  Example:
176
247
 
177
- ```
248
+ ```ruby
178
249
  apply_scopes(User, { order_by_name: true, with_id: [1,2,3] })
179
250
  ```
180
251
 
@@ -184,11 +255,21 @@ This module adds the `query_field` helper.
184
255
  It adds an easy way of creating simple fields with resolvers.
185
256
 
186
257
  To add this method, add
187
- ```
258
+ ```ruby
188
259
  extend GraphQR::QueryField
189
260
  ```
190
261
  to your `BaseObject`.
191
262
 
263
+ ```ruby
264
+ module Types
265
+ class BaseObject < GraphQL::Schema::Object
266
+ ...
267
+ extend GraphQR::QueryField
268
+ ...
269
+ end
270
+ end
271
+ ```
272
+
192
273
  Read more about its use in the [documentation](https://qulturerocks.github.io/graphqr/GraphQR/QueryField.html)
193
274
 
194
275
 
@@ -57,6 +57,9 @@ require 'graphqr/apply_scopes'
57
57
  require 'graphqr/authorized'
58
58
  require 'graphqr/pagination'
59
59
  require 'graphqr/permitted_fields_extension'
60
+ require 'graphqr/base_resolver'
61
+ require 'graphqr/base_resolvers'
60
62
  require 'graphqr/query_field'
63
+ require 'graphqr/relation_fields'
61
64
  require 'graphqr/scope_items'
62
65
  require 'graphqr/version'
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQR
4
+ ##
5
+ # @TODO doc
6
+ class BaseResolver < GraphQL::Schema::Resolver
7
+ ##
8
+ # @TODO doc
9
+ include GraphQR::ApplyScopes
10
+ include GraphQR::Policies::AuthorizeGraphQL
11
+ end
12
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQR
4
+ ##
5
+ # @TODO doc
6
+ module BaseResolvers
7
+ ##
8
+ # @TODO doc
9
+ def base_collection_resolver(type_class, scope_class)
10
+ Class.new(GraphQR::BaseResolver) do
11
+ type type_class.pagination_type, null: false
12
+
13
+ argument :filter, scope_class, required: false if scope_class.present?
14
+
15
+ def resolve(filter: {})
16
+ authorize_graphql unscoped_collection, :index?
17
+
18
+ collection = apply_scopes(unscoped_collection, filter)
19
+ context[:policy_provider].authorized_records(records: collection)
20
+ end
21
+
22
+ def unscoped_collection
23
+ raise NotImplementedError
24
+ end
25
+ end
26
+ end
27
+
28
+ def base_resource_resolver(type_class)
29
+ Class.new(GraphQR::BaseResolver) do
30
+ type type_class, null: false
31
+
32
+ def resolve
33
+ context[:policy_provider].allowed?(action: :show?, record: record)
34
+
35
+ record
36
+ end
37
+
38
+ def record
39
+ raise NotImplementedError
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -6,9 +6,9 @@ module GraphQR
6
6
  # A helper to create simple queries faster and easier
7
7
  #
8
8
  # To use this extension, add `extend Graphql::QueryField` on your `QueryType`
9
+ #
9
10
  module QueryField
10
- # rubocop:disable Metrics/ParameterLists
11
-
11
+ include BaseResolvers
12
12
  ##
13
13
  # The `query_field` method is a helper to create fields and resolver without effort.
14
14
  #
@@ -41,13 +41,15 @@ module GraphQR
41
41
  #
42
42
  # Single fields have the required `id` argument to find the exact record searched.
43
43
  # Its resolver will look for the `show?` method on the model Policy.
44
+ #
45
+ # rubocop:disable Metrics/ParameterLists
44
46
  def query_field(field_name, active_record_class, type_class:, scope_class: nil, **kwargs, &block)
45
47
  is_collection = active_record_class.is_a? Array
46
48
  if is_collection
47
49
  active_record_class = active_record_class.first
48
- resolver = collection(active_record_class, type_class, scope_class)
50
+ resolver = collection_resolver(active_record_class, type_class, scope_class)
49
51
  else
50
- resolver = resource(active_record_class, type_class)
52
+ resolver = resource_resolver(active_record_class, type_class)
51
53
  end
52
54
 
53
55
  field(field_name, paginate: is_collection, resolver: resolver, **kwargs, &block)
@@ -56,39 +58,26 @@ module GraphQR
56
58
 
57
59
  private
58
60
 
59
- def collection(active_record_class, type_class, scope_class)
60
- Class.new(::BaseResolver) do
61
- class_attribute :active_record_class
62
- self.active_record_class = active_record_class
63
-
64
- type type_class.pagination_type, null: false
65
-
66
- argument :filter, scope_class, required: false
67
-
68
- def resolve(filter: {})
69
- authorize_graphql active_record_class, :index?
70
-
71
- collection = apply_scopes(active_record_class, filter)
72
- context[:policy_provider].authorized_records(records: collection)
73
- end
74
- end
61
+ def collection_resolver(active_record_class, type_class, scope_class)
62
+ resolver = base_collection_resolver(type_class, scope_class)
63
+ resolver.define_method(:unscoped_collection) { @unscoped_collection ||= active_record_class }
64
+ resolver
75
65
  end
76
66
 
77
- def resource(active_record_class, type_class)
78
- Class.new(::BaseResolver) do
67
+ def resource_resolver(active_record_class, type_class)
68
+ Class.new(base_resource_resolver(type_class)) do
79
69
  class_attribute :active_record_class
80
70
  self.active_record_class = active_record_class
81
71
 
82
- type type_class, null: false
83
-
84
72
  argument :id, 'ID', required: true
85
73
 
86
74
  def resolve(id:)
87
- record = self.class.active_record_class.find(id)
88
-
89
- context[:policy_provider].allowed?(action: :show?, record: record)
75
+ @id = id
76
+ super()
77
+ end
90
78
 
91
- record
79
+ def record
80
+ @record ||= active_record_class.find(@id)
92
81
  end
93
82
  end
94
83
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQR
4
+ ##
5
+ # @TODO doc
6
+ module RelationFields
7
+ ##
8
+ # @TODO doc
9
+ # rubocop:disable Naming/PredicateName
10
+ include GraphQR::BaseResolvers
11
+
12
+ def has_many(field_name, type_class, scope_class: nil, **kwargs, &block)
13
+ type_class = type_class.first
14
+
15
+ resolver = has_many_resolver(field_name, type_class, scope_class)
16
+
17
+ field(field_name, paginate: true, resolver: resolver, **kwargs, &block)
18
+ end
19
+
20
+ def has_one(field_name, type_class, **kwargs, &block)
21
+ resolver = has_one_resolver(field_name, type_class)
22
+
23
+ field(field_name, resolver: resolver, **kwargs, &block)
24
+ end
25
+
26
+ private
27
+
28
+ def has_many_resolver(collection_name, type_class, scope_class)
29
+ resolver = base_collection_resolver(type_class, scope_class)
30
+ resolver.define_method(:unscoped_collection) { @unscoped_collection ||= object.send(collection_name) }
31
+ resolver
32
+ end
33
+
34
+ def has_one_resolver(resource_name, type_class)
35
+ resolver = base_resource_resolver(type_class)
36
+ resolver.define_method(:record) { @record ||= object.send(resource_name) }
37
+ resolver
38
+ end
39
+ # rubocop:enable Naming/PredicateName
40
+ end
41
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GraphQR
4
- VERSION = '0.0.5'
4
+ VERSION = '0.0.6'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphqr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Manuel Puyol
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2019-05-29 00:00:00.000000000 Z
13
+ date: 2019-07-18 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: graphql
@@ -144,6 +144,8 @@ files:
144
144
  - lib/graphqr.rb
145
145
  - lib/graphqr/apply_scopes.rb
146
146
  - lib/graphqr/authorized.rb
147
+ - lib/graphqr/base_resolver.rb
148
+ - lib/graphqr/base_resolvers.rb
147
149
  - lib/graphqr/configuration.rb
148
150
  - lib/graphqr/fields/base_field.rb
149
151
  - lib/graphqr/hooks.rb
@@ -155,6 +157,7 @@ files:
155
157
  - lib/graphqr/policies/authorize_graphql.rb
156
158
  - lib/graphqr/policies/pundit_provider.rb
157
159
  - lib/graphqr/query_field.rb
160
+ - lib/graphqr/relation_fields.rb
158
161
  - lib/graphqr/scope_items.rb
159
162
  - lib/graphqr/version.rb
160
163
  - spec/graphqr_spec.rb