graphql_rails 0.3.3 → 0.4.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: 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