graphql_rails 2.0.0 → 2.1.0

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
  SHA256:
3
- metadata.gz: 1d635269612ec07a541e7adebb01a9da7420f74511d8bbc4a30c60cea2eadc3f
4
- data.tar.gz: 5d8e87e2d4c22bcf679645fa0de355b5c2a1765d357e28ba00560e83279462a0
3
+ metadata.gz: bd5007444af16b72661bd4c9ad03866017b9fbbaadbd4a4bccc5c788c73f95bf
4
+ data.tar.gz: 884390854d3490c9b323f82c527b922a087a0617a1a862fb5cbcd3d18f31e955
5
5
  SHA512:
6
- metadata.gz: 4bdbac43bd69d1ace6bc7b29d6cfba07225950ff9a583f269310eed608fc5554afa934e2e34d4f2001349bdc8385fe4d94b6dc1b8844cb20f5d850276b5c9576
7
- data.tar.gz: 9bdf1be49c697610f584def6bb016b5bd60455eb813c5b4884b491c39cb7df7c29d277efe56e45e79bc24089c3cf1befa9c178471396fe6eb6ca52c2ec49bffc
6
+ metadata.gz: dcc498d22901bfecb649f44b266634ed762d119d0c4d876df04fbe5ae595173e61c3fe53078ea1803000fd5ec6faaa8686e1198aa2037ae6f09b91bf4e20b001
7
+ data.tar.gz: 58a8ae501e143744082ca85ac0dba51bdcf5883fa949b25d23fd4c5510c28b877c4f5ca9cbc7f0af5d6d19b7c742fa835fa4b6d7afc1ccaaca0b83c153e9aeb9
data/.rubocop.yml CHANGED
@@ -3,6 +3,9 @@ require: rubocop-rspec
3
3
  RSpec/NestedGroups:
4
4
  Enabled: false
5
5
 
6
+ RSpec/MultipleMemoizedHelpers:
7
+ Enabled: false
8
+
6
9
  Layout/LineLength:
7
10
  Enabled: true
8
11
  Max: 120
data/CHANGELOG.md CHANGED
@@ -9,6 +9,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  * Added/Changed/Deprecated/Removed/Fixed/Security: YOUR CHANGE HERE
11
11
 
12
+ ## [2.1.0](2022-01-12)
13
+
14
+ * Added: decorated relations now can be called using "find", "empty?" and "find_by" methods
15
+ * Fixed: allow to define graphql-ruby enum classes as strings.
16
+ * Added: add "groups" to attributes.
17
+ * Changed: `date` type is now alias for `GraphQL::Types::ISO8601Date`, also added aliases for other common graphql-graphql types.
18
+
12
19
  ## [2.0.0](2021-12-03)
13
20
 
14
21
  * Added: support for generating multiple schema dumps with `rake graphql_rails:schema:dump`.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- graphql_rails (2.0.0)
4
+ graphql_rails (2.1.0)
5
5
  activesupport (>= 4)
6
6
  graphql (~> 1.12, >= 1.12.4)
7
7
 
@@ -78,7 +78,7 @@ GEM
78
78
  erubi (1.9.0)
79
79
  globalid (0.4.2)
80
80
  activesupport (>= 4.2.0)
81
- graphql (1.12.10)
81
+ graphql (1.13.4)
82
82
  i18n (1.8.5)
83
83
  concurrent-ruby (~> 1.0)
84
84
  json (2.3.1)
@@ -31,14 +31,7 @@ Some types can be determined by attribute name, so you can skip this attribute:
31
31
  * attributes which ends with `?` has `Boolean!` type
32
32
  * all other attributes without type are considered to be `String`
33
33
 
34
- available types are:
35
-
36
- * ID: `'id'`
37
- * String: `'string'`, `'str'`, `'text'`
38
- * Boolean: `'bool'`, `'boolean'`
39
- * Float: `'float'`, `'double'`, `'decimal'`
40
-
41
- usage example:
34
+ Usage example:
42
35
 
43
36
  ```ruby
44
37
  class User
@@ -54,6 +47,34 @@ class User
54
47
  end
55
48
  ```
56
49
 
50
+ You can also use some build in aliases for types, such as:
51
+
52
+ * `'id'` is alias for `GraphQL::Types::ID`
53
+ * `'integer'`, `'int'` are aliases for `GraphQL::Types::Int`
54
+ * `'bigint'`, `'big_int'` are aliases for `GraphQL::Types::BigInt`
55
+ * 'float', 'double', 'decimal' are aliases for `GraphQL::Types::Float`
56
+ * `'bool'`, `'boolean'` are aliases for GraphQL::Types::Boolean
57
+ * String: `'string'`, `'str'`, `'text'`
58
+ * 'date' is alias for `GraphQL::Types::ISO8601Date`
59
+ * 'time', 'datetime', 'date_time' are aliases for `GraphQL::Types::ISO8601DateTime`
60
+ * 'json' is alias for `GraphQL::Types::JSON`
61
+
62
+ Usage example:
63
+
64
+ ```ruby
65
+ class User
66
+ include GraphqlRails::Model
67
+
68
+ graphql do |c|
69
+ c.attribute(:about_me).type(:text)
70
+ c.attribute(:active).type('bool!')
71
+ c.attribute(:created_at).type(:datetime!)
72
+ c.attribute(:data).type(:json!)
73
+ c.attribute(:login_dates).type('[date!]!')
74
+ end
75
+ end
76
+ ```
77
+
57
78
  #### attribute.type: using graphql-ruby objects
58
79
 
59
80
  You can also use raw graphql-ruby objects as attribute types. Here is an example:
@@ -110,6 +131,45 @@ class User
110
131
  end
111
132
  ```
112
133
 
134
+ ### attribute.groups
135
+
136
+ Groups are handy feature when you want to have multiple schemas. For example, you want to have public graphql endpoint and internal graphql endpoint where each group has some unique nodes. If attribute has `groups` set, then this attribute will be visible only in appropriate group schemas.
137
+
138
+ ```ruby
139
+ class User
140
+ include GraphqlRails::Model
141
+
142
+ graphql do |c|
143
+ # visible in all schemas (default):
144
+ c.attribute(:email)
145
+
146
+ # visible in "internal" and "beta" schemas only:
147
+ c.attribute(:admin_id).groups(%i[internal beta])
148
+
149
+ # visible in "external" schema only:
150
+ c.attribute(:nickname).groups(%i[external])
151
+ end
152
+ end
153
+ ```
154
+
155
+ ### attribute.group
156
+
157
+ Alias for Attribute#groups.
158
+
159
+ ```ruby
160
+ class User
161
+ include GraphqlRails::Model
162
+
163
+ graphql do |c|
164
+ # visible in all schemas (default):
165
+ c.attribute(:email)
166
+
167
+ # visible in "external" schema only:
168
+ c.attribute(:nickname).group(:external)
169
+ end
170
+ end
171
+ ```
172
+
113
173
  ### attribute.options
114
174
 
115
175
  Allows passing options to attribute definition. Available options:
@@ -40,7 +40,8 @@ module GraphqlRails
40
40
  {
41
41
  method: property.to_sym,
42
42
  null: optional?,
43
- camelize: camelize?
43
+ camelize: camelize?,
44
+ groups: groups
44
45
  }
45
46
  end
46
47
 
@@ -20,6 +20,18 @@ module GraphqlRails
20
20
  chainable_option :type
21
21
  end
22
22
 
23
+ def groups(new_groups = ChainableOptions::NOT_SET)
24
+ @groups ||= []
25
+ return @groups if new_groups == ChainableOptions::NOT_SET
26
+
27
+ @groups = Array(new_groups).map(&:to_s)
28
+ self
29
+ end
30
+
31
+ def group(*args)
32
+ groups(*args)
33
+ end
34
+
23
35
  def required(new_value = true) # rubocop:disable Style/OptionalBooleanParameter
24
36
  @required = new_value
25
37
  self
@@ -25,7 +25,7 @@ module GraphqlRails
25
25
  end
26
26
 
27
27
  def input_argument_options
28
- { required: required?, description: description, camelize: false }
28
+ { required: required?, description: description, camelize: false, groups: groups }
29
29
  end
30
30
 
31
31
  def paginated?
@@ -16,18 +16,27 @@ module GraphqlRails
16
16
  'int' => GraphQL::Types::Int,
17
17
  'integer' => GraphQL::Types::Int,
18
18
 
19
+ 'big_int' => GraphQL::Types::BigInt,
20
+ 'bigint' => GraphQL::Types::BigInt,
21
+
22
+ 'float' => GraphQL::Types::Float,
23
+ 'double' => GraphQL::Types::Float,
24
+ 'decimal' => GraphQL::Types::Float,
25
+
26
+ 'bool' => GraphQL::Types::Boolean,
27
+ 'boolean' => GraphQL::Types::Boolean,
28
+
19
29
  'string' => GraphQL::Types::String,
20
30
  'str' => GraphQL::Types::String,
21
31
  'text' => GraphQL::Types::String,
22
- 'time' => GraphQL::Types::String,
23
- 'date' => GraphQL::Types::String,
24
32
 
25
- 'bool' => GraphQL::Types::Boolean,
26
- 'boolean' => GraphQL::Types::Boolean,
33
+ 'date' => GraphQL::Types::ISO8601Date,
27
34
 
28
- 'float' => GraphQL::Types::Float,
29
- 'double' => GraphQL::Types::Float,
30
- 'decimal' => GraphQL::Types::Float
35
+ 'time' => GraphQL::Types::ISO8601DateTime,
36
+ 'datetime' => GraphQL::Types::ISO8601DateTime,
37
+ 'date_time' => GraphQL::Types::ISO8601DateTime,
38
+
39
+ 'json' => GraphQL::Types::JSON
31
40
  }.freeze
32
41
 
33
42
  WRAPPER_TYPES = [
@@ -43,10 +52,16 @@ module GraphqlRails
43
52
  GraphQL::InputObjectType
44
53
  ].freeze
45
54
 
55
+ PARSEABLE_RAW_GRAPHQL_TYPES = [
56
+ GraphQL::Schema::Object,
57
+ GraphQL::Schema::Scalar,
58
+ GraphQL::Schema::Enum
59
+ ].freeze
60
+
46
61
  RAW_GRAPHQL_TYPES = (WRAPPER_TYPES + GRAPHQL_BASE_TYPES).freeze
47
62
 
48
63
  def unwrapped_scalar_type
49
- TYPE_MAPPING[nullable_inner_name.downcase.downcase]
64
+ TYPE_MAPPING[nullable_inner_name.downcase]
50
65
  end
51
66
 
52
67
  def raw_graphql_type?
@@ -88,7 +103,7 @@ module GraphqlRails
88
103
  def graphql_type_object?(type_class)
89
104
  return false unless type_class.is_a?(Class)
90
105
 
91
- type_class < GraphQL::Schema::Object || type_class < GraphQL::Schema::Scalar
106
+ PARSEABLE_RAW_GRAPHQL_TYPES.any? { |parent_type| type_class < parent_type }
92
107
  end
93
108
 
94
109
  def applicable_graphql_type?(type)
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'graphql_rails/controller/request'
4
+ require 'graphql_rails/types/argument_type'
4
5
 
5
6
  module GraphqlRails
6
7
  class Controller
@@ -8,6 +9,8 @@ module GraphqlRails
8
9
  # Resolver which includes controller specific methods.
9
10
  # Used to simplify resolver build for each controller action
10
11
  class ControllerActionResolver < GraphQL::Schema::Resolver
12
+ argument_class(GraphqlRails::Types::ArgumentType)
13
+
11
14
  def self.controller(controller_class = nil)
12
15
  @controller = controller_class if controller_class
13
16
  @controller
@@ -5,7 +5,7 @@ module GraphqlRails
5
5
  # wrapps active record relation and returns decorated object instead
6
6
  class RelationDecorator
7
7
  delegate :map, :each, to: :to_a
8
- delegate :limit_value, :offset_value, :count, :size, to: :relation
8
+ delegate :limit_value, :offset_value, :count, :size, :empty?, to: :relation
9
9
 
10
10
  def self.decorates?(object)
11
11
  (defined?(ActiveRecord) && object.is_a?(ActiveRecord::Relation)) ||
@@ -24,7 +24,7 @@ module GraphqlRails
24
24
  end
25
25
  end
26
26
 
27
- %i[first second last].each do |method_name|
27
+ %i[first second last find find_by].each do |method_name|
28
28
  define_method method_name do |*args, &block|
29
29
  decoratable_object_method(method_name, *args, &block)
30
30
  end
@@ -1,11 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'graphql_rails/types/argument_type'
4
+ require 'graphql_rails/concerns/service'
5
+
3
6
  module GraphqlRails
4
7
  module Model
5
8
  # stores information about model specific config, like attributes and types
6
9
  class BuildGraphqlInputType
7
- require 'graphql_rails/concerns/service'
8
-
9
10
  include ::GraphqlRails::Service
10
11
 
11
12
  def initialize(name:, description: nil, attributes:)
@@ -20,6 +21,7 @@ module GraphqlRails
20
21
  type_attributes = attributes
21
22
 
22
23
  Class.new(GraphQL::Schema::InputObject) do
24
+ argument_class(GraphqlRails::Types::ArgumentType)
23
25
  graphql_name(type_name)
24
26
  description(type_description)
25
27
 
@@ -5,6 +5,7 @@ module GraphqlRails
5
5
  # Initializes class to define graphql type and fields.
6
6
  class FindOrBuildGraphqlTypeClass
7
7
  require 'graphql_rails/concerns/service'
8
+ require 'graphql_rails/types/object_type'
8
9
 
9
10
  include ::GraphqlRails::Service
10
11
 
@@ -32,7 +33,7 @@ module GraphqlRails
32
33
  graphql_type_name = name
33
34
  graphql_type_description = description
34
35
 
35
- graphql_type_klass = Class.new(GraphQL::Schema::Object) do
36
+ graphql_type_klass = Class.new(GraphqlRails::Types::ObjectType) do
36
37
  graphql_name(graphql_type_name)
37
38
  description(graphql_type_description)
38
39
  end
@@ -8,12 +8,13 @@ module GraphqlRails
8
8
 
9
9
  include ::GraphqlRails::Service
10
10
 
11
- def initialize(group: nil, params:, schema: nil, router: nil, **schema_options)
11
+ def initialize(params:, context: {}, schema: nil, router: nil, group: nil, **schema_options) # rubocop:disable Metrics/ParameterLists
12
12
  @group = group
13
13
  @graphql_schema = schema
14
14
  @params = params
15
- @schema_options = schema_options
16
15
  @router = router
16
+ @initial_context = context
17
+ @schema_options = schema_options
17
18
  end
18
19
 
19
20
  def call
@@ -21,13 +22,18 @@ module GraphqlRails
21
22
  params[:query],
22
23
  variables: variables,
23
24
  operation_name: params[:operationName],
25
+ context: context,
24
26
  **schema_options
25
27
  )
26
28
  end
27
29
 
28
30
  private
29
31
 
30
- attr_reader :schema_options, :params, :group
32
+ attr_reader :schema_options, :params, :group, :initial_context
33
+
34
+ def context
35
+ initial_context.merge(graphql_group: group)
36
+ end
31
37
 
32
38
  def variables
33
39
  ensure_hash(params[:variables])
@@ -18,13 +18,18 @@ module GraphqlRails
18
18
  end
19
19
 
20
20
  def call
21
- File.write(schema_path, schema.to_definition)
21
+ File.write(schema_path, schema_dump)
22
22
  end
23
23
 
24
24
  private
25
25
 
26
26
  attr_reader :router, :group
27
27
 
28
+ def schema_dump
29
+ context = { graphql_group: group }
30
+ schema.to_definition(context: context)
31
+ end
32
+
28
33
  def schema
29
34
  @schema ||= router.graphql_schema(group.presence)
30
35
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'graphql_rails/types/hidable_by_group'
4
+
5
+ module GraphqlRails
6
+ module Types
7
+ # Base argument type for all GraphqlRails inputs
8
+ class ArgumentType < GraphQL::Schema::Argument
9
+ include GraphqlRails::Types::HidableByGroup
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'graphql_rails/types/argument_type'
4
+ require 'graphql_rails/types/hidable_by_group'
5
+
6
+ module GraphqlRails
7
+ module Types
8
+ # Base field for all GraphqlRails model fields
9
+ class FieldType < GraphQL::Schema::Field
10
+ include GraphqlRails::Types::HidableByGroup
11
+ argument_class(GraphqlRails::Types::ArgumentType)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'graphql_rails/types/argument_type'
4
+
5
+ module GraphqlRails
6
+ module Types
7
+ # Add visibility option based on groups
8
+ module HidableByGroup
9
+ def initialize(*args, groups: [], **kwargs, &block)
10
+ super(*args, **kwargs, &block)
11
+
12
+ @groups = groups.map(&:to_s)
13
+ end
14
+
15
+ def visible?(context)
16
+ super && visible_in_context_group?(context)
17
+ end
18
+
19
+ private
20
+
21
+ def groups
22
+ @groups
23
+ end
24
+
25
+ def visible_in_context_group?(context)
26
+ group = context[:graphql_group] || context['graphql_group']
27
+
28
+ group.nil? || groups.empty? || groups.include?(group.to_s)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'graphql_rails/types/field_type'
4
+
5
+ module GraphqlRails
6
+ module Types
7
+ # Base graphql type class for all GraphqlRails models
8
+ class ObjectType < GraphQL::Schema::Object
9
+ field_class(GraphqlRails::Types::FieldType)
10
+ end
11
+ end
12
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GraphqlRails
4
- VERSION = '2.0.0'
4
+ VERSION = '2.1.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Povilas Jurčys
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-12-03 00:00:00.000000000 Z
11
+ date: 2022-01-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql
@@ -230,6 +230,10 @@ files:
230
230
  - lib/graphql_rails/tasks/dump_graphql_schema.rb
231
231
  - lib/graphql_rails/tasks/dump_graphql_schemas.rb
232
232
  - lib/graphql_rails/tasks/schema.rake
233
+ - lib/graphql_rails/types/argument_type.rb
234
+ - lib/graphql_rails/types/field_type.rb
235
+ - lib/graphql_rails/types/hidable_by_group.rb
236
+ - lib/graphql_rails/types/object_type.rb
233
237
  - lib/graphql_rails/version.rb
234
238
  homepage: https://github.com/samesystem/graphql_rails
235
239
  licenses: