graphql_rails 0.3.3 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e2bd0f0c9f6aaa1808567914c7a1440302a8b7dc828e97937a264dc33cbdd0d5
4
- data.tar.gz: eac8327fdf61cbd8bedb9301f261448a48ebeaf0d14ce78a6fd986d5aa752eb9
3
+ metadata.gz: b1d9d24469554419e5b4b033eb06b1e8f0be82079285d31ee7dbfb1e8e19e825
4
+ data.tar.gz: 3acc8f452a19ca66421a438103e8da1ed24da263ce551eb7d082ac67458011e8
5
5
  SHA512:
6
- metadata.gz: e9df5b2875fc19b6a61259938ea99397edb51282c964f7bd511b1709c6625352e7c3d22428eac5ade6617b4a54244fb4b4ffa1574951b8368079fd7428cc5d68
7
- data.tar.gz: bb8c01ac692e2137f9f0d3ab39a1b7a562ba337145ea0f90a0dd3325a5a67caf523d9f97c0536008adce4815ad15adda1ae036d8ded6f970c16bd761bc7c9a19
6
+ metadata.gz: 47974bc6d410ff9ed1215025aa4d06362494f87e20fee0c4259a3186ffa001a38c495b9ec7a9eff2428e966dc32ed52f776129cbab413abf874bc8ecb4334bc2
7
+ data.tar.gz: aa1f164524942256b310088b0ae046f5d98b90e283f4c17f465c8d3ca64a3ca4b8cd836af78b2fe77332fe062518b00380ed68d22df57b61d6eca824f0f6caff
@@ -6,8 +6,6 @@ RSpec/NestedGroups:
6
6
  Metrics/LineLength:
7
7
  Enabled: true
8
8
  Max: 120
9
- Exclude:
10
- - db/migrate/*
11
9
 
12
10
  Metrics/BlockLength:
13
11
  Exclude:
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- graphql_rails (0.3.3)
4
+ graphql_rails (0.4.0)
5
5
  activesupport (>= 4)
6
6
  graphql (~> 1)
7
7
 
data/README.md CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  [![Build Status](https://travis-ci.org/samesystem/graphql_rails.svg?branch=master)](https://travis-ci.org/samesystem/graphql_rails)
4
4
  [![codecov](https://codecov.io/gh/samesystem/graphql_rails/branch/master/graph/badge.svg)](https://codecov.io/gh/samesystem/graphql_rails)
5
+ [![Documentation](https://readthedocs.org/projects/ansicolortags/badge/?version=latest)](https://samesystem.github.io/graphql_rails)
5
6
 
6
7
  Rails style structure for GrapQL API.
7
8
 
@@ -170,6 +171,10 @@ RSpec.describe MyGraphqlController, type: :graphql_controller do
170
171
  end
171
172
  ```
172
173
 
174
+ ## Detailed documentation
175
+
176
+ Check https://samesystem.github.io/graphql_rails for more details
177
+
173
178
 
174
179
  ## Development
175
180
 
@@ -80,7 +80,7 @@ By default return type is determined by controller name. When you want to return
80
80
 
81
81
  ```ruby
82
82
  class UsersController < GraphqlRails::Controller
83
- action(:last_order).permit(:id).returns(Order)
83
+ action(:last_order).permit(:id).returns('Order!') # Order is your model class name
84
84
 
85
85
  def last_order
86
86
  user = User.find(params[:id]).orders.last
@@ -122,6 +122,48 @@ class UsersController < GraphqlRails::Controller
122
122
  end
123
123
  ```
124
124
 
125
+ ## *after_action*
126
+
127
+ You can add `after_action` to run some filters after calling your controller action. Here is an example:
128
+
129
+ ```ruby
130
+ class UsersController < GraphqlRails::Controller
131
+ after_action :clear_cache
132
+
133
+ def create
134
+ User.create(params)
135
+ end
136
+
137
+ private
138
+
139
+ def clear_cache # will run after `UsersController#create` action
140
+ logger.log('Create action is completed')
141
+ end
142
+ end
143
+ ```
144
+
145
+ ## *around_action*
146
+
147
+ You can add `around_action` to run some filters before and after calling your controller action. Here is an example:
148
+
149
+ ```ruby
150
+ class UsersController < GraphqlRails::Controller
151
+ around_action :use_custom_locale
152
+
153
+ def create
154
+ User.create(params)
155
+ end
156
+
157
+ private
158
+
159
+ def with_custom_locale
160
+ I18n.with_locale('it') do
161
+ yield # yield is mandatory
162
+ end
163
+ end
164
+ end
165
+ ```
166
+
125
167
  ### *only* and *except* option
126
168
 
127
169
  `UsersController.before_action` accepts `only` or `except` options which allows to skip filters for some actions.
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
7
7
  spec.name = 'graphql_rails'
8
8
  spec.version = GraphqlRails::VERSION
9
9
  spec.authors = ['Povilas Jurčys']
10
- spec.email = ['bloomrain@gmail.com']
10
+ spec.email = ['po.jurcys@gmail.com']
11
11
 
12
12
  spec.summary = %q{GrapQL server and client for rails}
13
13
  spec.homepage = 'https://github.com/povilasjurcys/graphql_rails'
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'graphql'
4
- require 'graphql_rails/attribute/attribute_type_parser'
4
+ require 'graphql_rails/type_parser'
5
5
 
6
6
  module GraphqlRails
7
7
  # contains info about single graphql attribute
@@ -48,7 +48,7 @@ module GraphqlRails
48
48
  end
49
49
 
50
50
  def parse_type(type)
51
- type = AttributeTypeParser.new(type).call
51
+ type = TypeParser.new(type).call
52
52
 
53
53
  original_name['!'] ? type.to_non_null_type : type
54
54
  end
@@ -4,6 +4,7 @@ require 'active_support/hash_with_indifferent_access'
4
4
  require 'graphql_rails/controller/configuration'
5
5
  require 'graphql_rails/controller/request'
6
6
  require 'graphql_rails/controller/format_results'
7
+ require 'graphql_rails/controller/action_hooks_runner'
7
8
 
8
9
  module GraphqlRails
9
10
  # base class for all graphql_rails controllers
@@ -13,12 +14,20 @@ module GraphqlRails
13
14
  controller_configuration.add_before_action(*args)
14
15
  end
15
16
 
17
+ def around_action(*args)
18
+ controller_configuration.add_around_action(*args)
19
+ end
20
+
21
+ def after_action(*args)
22
+ controller_configuration.add_after_action(*args)
23
+ end
24
+
16
25
  def action(action_name)
17
26
  controller_configuration.action(action_name)
18
27
  end
19
28
 
20
29
  def controller_configuration
21
- @controller_configuration ||= Controller::Configuration.new(self)
30
+ @controller_configuration ||= Controller::Configuration.new
22
31
  end
23
32
  end
24
33
 
@@ -42,7 +51,7 @@ module GraphqlRails
42
51
  attr_reader :graphql_request
43
52
 
44
53
  def render(object_or_errors)
45
- errors = grapqhl_errors_from_render_params(object_or_errors)
54
+ errors = graphql_errors_from_render_params(object_or_errors)
46
55
  object = errors.empty? ? object_or_errors : nil
47
56
 
48
57
  graphql_request.errors = errors
@@ -56,16 +65,15 @@ module GraphqlRails
56
65
  private
57
66
 
58
67
  def call_with_rendering(action_name)
59
- before_actions = self.class.controller_configuration.before_actions_for(action_name)
60
- before_actions.each { |before_action| send(before_action.name) }
61
- response = public_send(action_name)
68
+ hooks_runner = ActionHooksRunner.new(action_name: action_name, controller: self)
69
+ response = hooks_runner.call { public_send(action_name) }
62
70
 
63
71
  render response if graphql_request.no_object_to_return?
64
72
  rescue StandardError => error
65
73
  render error: error
66
74
  end
67
75
 
68
- def grapqhl_errors_from_render_params(rendering_params)
76
+ def graphql_errors_from_render_params(rendering_params)
69
77
  return [] unless rendering_params.is_a?(Hash)
70
78
  return [] if rendering_params.keys.count != 1
71
79
 
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'active_support/core_ext/string/filters'
4
+ require 'graphql_rails/type_parser'
4
5
  require 'graphql_rails/attribute'
5
6
 
6
7
  module GraphqlRails
@@ -40,7 +41,7 @@ module GraphqlRails
40
41
  end
41
42
 
42
43
  def returns(new_return_type)
43
- @return_type = new_return_type
44
+ @return_type = TypeParser.new(new_return_type).call
44
45
  self
45
46
  end
46
47
 
@@ -3,7 +3,7 @@
3
3
  module GraphqlRails
4
4
  class Controller
5
5
  # stores information about controller filter
6
- class BeforeActionFilter
6
+ class ActionFilter
7
7
  attr_reader :name
8
8
 
9
9
  def initialize(name, only: [], except: [])
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphqlRails
4
+ class Controller
5
+ # runs {before/around/after}_action controller hooks
6
+ class ActionHooksRunner
7
+ def initialize(action_name:, controller:)
8
+ @action_name = action_name
9
+ @controller = controller
10
+ end
11
+
12
+ def call
13
+ run_before_action_hooks
14
+ run_around_actions { yield }.tap do
15
+ run_after_action_hooks
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :action_name, :controller
22
+
23
+ def all_around_actions
24
+ controller_configuration.around_actions_for(action_name)
25
+ end
26
+
27
+ def controller_configuration
28
+ controller.class.controller_configuration
29
+ end
30
+
31
+ def run_around_actions(around_actions = all_around_actions, &block)
32
+ pending_around_actions = around_actions.clone
33
+ around_action = pending_around_actions.shift
34
+
35
+ if around_action
36
+ controller.send(around_action.name) { run_around_actions(pending_around_actions, &block) }
37
+ else
38
+ yield
39
+ end
40
+ end
41
+
42
+ def run_before_action_hooks
43
+ before_actions = controller_configuration.before_actions_for(action_name)
44
+ before_actions.each { |filter| controller.send(filter.name) }
45
+ end
46
+
47
+ def run_after_action_hooks
48
+ after_actions = controller_configuration.after_actions_for(action_name)
49
+ after_actions.each { |filter| controller.send(filter.name) }
50
+ end
51
+ end
52
+ end
53
+ end
@@ -3,25 +3,41 @@
3
3
  require 'active_support/core_ext/string/inflections'
4
4
  require 'graphql_rails/attribute'
5
5
  require 'graphql_rails/controller/action_configuration'
6
- require 'graphql_rails/controller/before_action_filter'
6
+ require 'graphql_rails/controller/action_filter'
7
7
 
8
8
  module GraphqlRails
9
9
  class Controller
10
10
  # stores all graphql_rails contoller specific config
11
11
  class Configuration
12
- def initialize(controller)
13
- @controller = controller
12
+ def initialize
14
13
  @before_actions = {}
14
+ @around_actions = {}
15
+ @after_actions = {}
15
16
  @action_by_name = {}
16
17
  end
17
18
 
18
19
  def before_actions_for(action_name)
19
- before_actions.values.select { |action| action.applicable_for?(action_name) }
20
+ action_filters_for(action_name, before_actions)
21
+ end
22
+
23
+ def around_actions_for(action_name)
24
+ action_filters_for(action_name, around_actions)
25
+ end
26
+
27
+ def after_actions_for(action_name)
28
+ action_filters_for(action_name, after_actions)
29
+ end
30
+
31
+ def add_around_action(name, **options)
32
+ add_action(name, around_actions, **options)
20
33
  end
21
34
 
22
35
  def add_before_action(name, **options)
23
- symbolized_name = name.to_sym
24
- before_actions[symbolized_name] = BeforeActionFilter.new(symbolized_name, **options)
36
+ add_action(name, before_actions, **options)
37
+ end
38
+
39
+ def add_after_action(name, **options)
40
+ add_action(name, after_actions, **options)
25
41
  end
26
42
 
27
43
  def action(method_name)
@@ -30,7 +46,16 @@ module GraphqlRails
30
46
 
31
47
  private
32
48
 
33
- attr_reader :controller, :before_actions
49
+ attr_reader :before_actions, :around_actions, :after_actions
50
+
51
+ def action_filters_for(action_name, action_filters)
52
+ action_filters.values.select { |filter| filter.applicable_for?(action_name) }
53
+ end
54
+
55
+ def add_action(name, actions_collection, **options)
56
+ symbolized_name = name.to_sym
57
+ actions_collection[symbolized_name] = ActionFilter.new(symbolized_name, **options)
58
+ end
34
59
  end
35
60
  end
36
61
  end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'graphql'
4
+
5
+ module GraphqlRails
6
+ # converts string value in to GraphQL type
7
+ class TypeParser
8
+ class UnknownTypeError < ArgumentError; end
9
+
10
+ TYPE_MAPPING = {
11
+ 'id' => GraphQL::ID_TYPE,
12
+
13
+ 'int' => GraphQL::INT_TYPE,
14
+ 'integer' => GraphQL::INT_TYPE,
15
+
16
+ 'string' => GraphQL::STRING_TYPE,
17
+ 'str' => GraphQL::STRING_TYPE,
18
+ 'text' => GraphQL::STRING_TYPE,
19
+ 'time' => GraphQL::STRING_TYPE,
20
+ 'date' => GraphQL::STRING_TYPE,
21
+
22
+ 'bool' => GraphQL::BOOLEAN_TYPE,
23
+ 'boolean' => GraphQL::BOOLEAN_TYPE,
24
+
25
+ 'float' => GraphQL::FLOAT_TYPE,
26
+ 'double' => GraphQL::FLOAT_TYPE,
27
+ 'decimal' => GraphQL::FLOAT_TYPE
28
+ }.freeze
29
+
30
+ def initialize(unparsed_type)
31
+ @unparsed_type = unparsed_type
32
+ end
33
+
34
+ def call
35
+ return unparsed_type if raw_graphql_type?
36
+
37
+ if list?
38
+ parsed_list_type
39
+ else
40
+ parsed_inner_type
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ attr_reader :unparsed_type
47
+
48
+ def parsed_list_type
49
+ list_type = parsed_inner_type.to_list_type
50
+
51
+ if required_list_type?
52
+ list_type.to_non_null_type
53
+ else
54
+ list_type
55
+ end
56
+ end
57
+
58
+ def parsed_inner_type
59
+ if required_inner_type?
60
+ type_by_name.to_non_null_type
61
+ else
62
+ type_by_name
63
+ end
64
+ end
65
+
66
+ def required_inner_type?
67
+ !!unparsed_type[/\w!/] # rubocop:disable Style/DoubleNegation
68
+ end
69
+
70
+ def list?
71
+ unparsed_type.to_s.include?(']')
72
+ end
73
+
74
+ def required_list_type?
75
+ unparsed_type.to_s.include?(']!')
76
+ end
77
+
78
+ def raw_graphql_type?
79
+ unparsed_type.is_a?(GraphQL::BaseType) ||
80
+ unparsed_type.is_a?(GraphQL::ObjectType) ||
81
+ (defined?(GraphQL::Schema::Member) && unparsed_type.is_a?(Class) && unparsed_type < GraphQL::Schema::Member)
82
+ end
83
+
84
+ def inner_type_name
85
+ unparsed_type.to_s.downcase.tr('[]!', '')
86
+ end
87
+
88
+ def type_by_name
89
+ TYPE_MAPPING.fetch(inner_type_name) do
90
+ dynamicly_defined_type || raise(
91
+ UnknownTypeError,
92
+ "Type #{unparsed_type.inspect} is not supported. Supported scalar types are: #{TYPE_MAPPING.keys}." \
93
+ ' All the classes that includes `GraphqlRails::Model` are also supported as types.'
94
+ )
95
+ end
96
+ end
97
+
98
+ def dynamicly_defined_type
99
+ type_class = inner_type_name.capitalize.safe_constantize
100
+ return unless type_class.respond_to?(:graphql)
101
+
102
+ type_class.graphql.graphql_type
103
+ end
104
+ end
105
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GraphqlRails
4
- VERSION = '0.3.3'
4
+ VERSION = '0.4.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: 0.3.3
4
+ version: 0.4.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: 2018-09-05 00:00:00.000000000 Z
11
+ date: 2018-12-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql
@@ -82,7 +82,7 @@ dependencies:
82
82
  version: '3.0'
83
83
  description:
84
84
  email:
85
- - bloomrain@gmail.com
85
+ - po.jurcys@gmail.com
86
86
  executables: []
87
87
  extensions: []
88
88
  extra_rdoc_files: []
@@ -114,11 +114,11 @@ files:
114
114
  - graphql_rails.gemspec
115
115
  - lib/graphql_rails.rb
116
116
  - lib/graphql_rails/attribute.rb
117
- - lib/graphql_rails/attribute/attribute_type_parser.rb
118
117
  - lib/graphql_rails/controller.rb
119
118
  - lib/graphql_rails/controller/action.rb
120
119
  - lib/graphql_rails/controller/action_configuration.rb
121
- - lib/graphql_rails/controller/before_action_filter.rb
120
+ - lib/graphql_rails/controller/action_filter.rb
121
+ - lib/graphql_rails/controller/action_hooks_runner.rb
122
122
  - lib/graphql_rails/controller/configuration.rb
123
123
  - lib/graphql_rails/controller/controller_function.rb
124
124
  - lib/graphql_rails/controller/format_results.rb
@@ -136,6 +136,7 @@ files:
136
136
  - lib/graphql_rails/router/route.rb
137
137
  - lib/graphql_rails/router/schema_builder.rb
138
138
  - lib/graphql_rails/rspec_controller_helpers.rb
139
+ - lib/graphql_rails/type_parser.rb
139
140
  - lib/graphql_rails/version.rb
140
141
  homepage: https://github.com/povilasjurcys/graphql_rails
141
142
  licenses:
@@ -1,107 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'graphql'
4
-
5
- module GraphqlRails
6
- class Attribute
7
- # converts string value in to GraphQL type
8
- class AttributeTypeParser
9
- class UnknownTypeError < ArgumentError; end
10
-
11
- TYPE_MAPPING = {
12
- 'id' => GraphQL::ID_TYPE,
13
-
14
- 'int' => GraphQL::INT_TYPE,
15
- 'integer' => GraphQL::INT_TYPE,
16
-
17
- 'string' => GraphQL::STRING_TYPE,
18
- 'str' => GraphQL::STRING_TYPE,
19
- 'text' => GraphQL::STRING_TYPE,
20
- 'time' => GraphQL::STRING_TYPE,
21
- 'date' => GraphQL::STRING_TYPE,
22
-
23
- 'bool' => GraphQL::BOOLEAN_TYPE,
24
- 'boolean' => GraphQL::BOOLEAN_TYPE,
25
-
26
- 'float' => GraphQL::FLOAT_TYPE,
27
- 'double' => GraphQL::FLOAT_TYPE,
28
- 'decimal' => GraphQL::FLOAT_TYPE
29
- }.freeze
30
-
31
- def initialize(unparsed_type)
32
- @unparsed_type = unparsed_type
33
- end
34
-
35
- def call
36
- return unparsed_type if raw_graphql_type?
37
-
38
- if list?
39
- parsed_list_type
40
- else
41
- parsed_inner_type
42
- end
43
- end
44
-
45
- private
46
-
47
- attr_reader :unparsed_type
48
-
49
- def parsed_list_type
50
- list_type = parsed_inner_type.to_list_type
51
-
52
- if required_list_type?
53
- list_type.to_non_null_type
54
- else
55
- list_type
56
- end
57
- end
58
-
59
- def parsed_inner_type
60
- if required_inner_type?
61
- type_by_name.to_non_null_type
62
- else
63
- type_by_name
64
- end
65
- end
66
-
67
- def required_inner_type?
68
- !!unparsed_type[/\w!/] # rubocop:disable Style/DoubleNegation
69
- end
70
-
71
- def list?
72
- unparsed_type.to_s.include?(']')
73
- end
74
-
75
- def required_list_type?
76
- unparsed_type.to_s.include?(']!')
77
- end
78
-
79
- def raw_graphql_type?
80
- unparsed_type.is_a?(GraphQL::BaseType) ||
81
- unparsed_type.is_a?(GraphQL::ObjectType) ||
82
- (defined?(GraphQL::Schema::Member) && unparsed_type.is_a?(Class) && unparsed_type < GraphQL::Schema::Member)
83
- end
84
-
85
- def inner_type_name
86
- unparsed_type.to_s.downcase.tr('[]!', '')
87
- end
88
-
89
- def type_by_name
90
- TYPE_MAPPING.fetch(inner_type_name) do
91
- dynamicly_defined_type || raise(
92
- UnknownTypeError,
93
- "Type #{unparsed_type.inspect} is not supported. Supported scalar types are: #{TYPE_MAPPING.keys}." \
94
- ' All the classes that includes `GraphqlRails::Model` are also supported as types.'
95
- )
96
- end
97
- end
98
-
99
- def dynamicly_defined_type
100
- type_class = inner_type_name.capitalize.safe_constantize
101
- return unless type_class.respond_to?(:graphql)
102
-
103
- type_class.graphql.graphql_type
104
- end
105
- end
106
- end
107
- end