graphql-rails-resolver 0.1.2 → 0.1.3

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
  SHA1:
3
- metadata.gz: eac8d006df6f747647df533f2606819a2b6e304a
4
- data.tar.gz: c2d7486872ecc83c143fd1654f369ab8fc58045e
3
+ metadata.gz: daaae82f72286352c8b15b9c04ebe0f29cdb5c7d
4
+ data.tar.gz: 8d6d288781cbe6643e005a7d618f174f96324833
5
5
  SHA512:
6
- metadata.gz: de1cd692a89ecf230ede5977aecf4e36a6ad5be227354643228d139c620f6e281547a8d259560a80e6016c3a3cbb6db8b3bf0bd691963d3ae71cb997eff14d91
7
- data.tar.gz: a5de48a5fb24727abd8f92f39fb3946f9e913aa8ca2116d6ecff9bc107e3110f1568f4d07398d550f5a7fa5e211e9ebb7d4c829ccb2ba4068b2dc0a667753f4f
6
+ metadata.gz: a1d3162e913409721fb111794ec0cc2d325957852d126513123945683d97ab220fc16475ae391feea818014d02604f9e91a35fda4c8b12025f01e9c99adc4e78
7
+ data.tar.gz: 2388a47c80fcfd9440322c14355587d6dd546866b95b9ff3402e3761c47faf459a517086c56470c3a850353f116736154bd75e22ce325cdff59f009021c9f152
data/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ # GraphQL::Rails::Resolver
2
+ ## CHANGELOG
3
+
4
+ ### Version 0.1.3
5
+ Added `resolve_scope` for resolving model scopes.
6
+ Fixed `resolve_where` not being called and reworked class inheritance.
7
+
8
+
9
+ ### Version 0.1.2
10
+ Initial release. Took a couple tries to figure out how to import to a new namespace on an existing gem.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2016 Cole Turner
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -1,11 +1,11 @@
1
- # ActiveResolver (graphql-rails-resolver)
2
- A utility for ease graphql-ruby integration into a Rails project. ActiveResolver offers a declarative approach to resolving Field arguments in a Rails environment.
1
+ # GraphQL::Rails::Resolver (graphql-rails-resolver)
2
+ A utility to ease graphql-ruby integration into a Rails project. This resolver offers a declarative approach to resolving Field arguments in a Rails environment.
3
3
 
4
- # How it works:
5
- `ActiveResolver.rb` serves as a base class for your GraphQL Ruby schema. When a resolver inherits from this base class, you can easily map arguments in a GraphQL Field to an attribute on an ActiveRecord model or a custom method.
4
+ # How it works
5
+ `GraphQL::Rails::Resolver` serves as a base class for your GraphQL Ruby schema. When a resolver inherits from this base class, you can easily map arguments in a GraphQL Field to an attribute on an ActiveRecord model or a custom method.
6
6
 
7
7
  ## Why?
8
- **tl;dr; Active Resolvers achieves three goals: maintainable query type, code re-use, and a declarative integration with Ruby on Rails.**
8
+ **tl;dr; To achieves three goals: maintainable query type, code re-use, and a declarative integration with Ruby on Rails.**
9
9
 
10
10
  Take for example the following Rails model:
11
11
 
@@ -16,6 +16,7 @@ class Post < ApplicationRecord
16
16
 
17
17
  scope :is_public, -> { where(is_public: true) }
18
18
  scope :is_private, -> { where(is_public: false) }
19
+ scope :featured, -> (value) { where(created_at: value) }
19
20
 
20
21
  def tags
21
22
  ["hello", "world"]
@@ -28,11 +29,11 @@ The standard implementation for resolving a `Post` is as follows:
28
29
 
29
30
  ```
30
31
  field :post, PostType do
31
- argument :is_public, types.Boolean, default_value: true
32
- resolve -> (obj, args, ctx) {
33
- post.is_public if args[:is_public]
34
- post.is_private unless args[:is_public]
35
- }
32
+ argument :is_public, types.Boolean, default_value: true
33
+ resolve -> (obj, args, ctx) {
34
+ post.is_public if args[:is_public]
35
+ post.is_private unless args[:is_public]
36
+ }
36
37
  end
37
38
  ```
38
39
 
@@ -43,8 +44,8 @@ Using the pattern from this article, our Field becomes much simpler:
43
44
  **/app/graph/types/query_type.rb**
44
45
  ```
45
46
  field :post, PostType do
46
- argument :is_public, types.Boolean, default_value: true
47
- resolve Resolvers::Post.new
47
+ argument :is_public, types.Boolean, default_value: true
48
+ resolve Resolvers::Post.new
48
49
  end
49
50
  ```
50
51
 
@@ -65,19 +66,27 @@ module Resolvers
65
66
  end
66
67
  end
67
68
  ```
68
- This solution addresses code re-use, however this series of conditionals do not allow you to resolve more than one argument, and it may become difficult to maintain this imperative approach.
69
+ This solution addresses code re-use, but these series of conditionals do not allow you to resolve more than one argument, and it may become difficult to maintain this imperative approach.
69
70
 
70
71
 
71
- ## Hello Active Resolver:
72
+ ## Hello "Active" Resolver
72
73
  **Out with imperative, in with declarative.**
73
74
 
74
- Take the Resolver from the previous example. Using `ActiveResolver`, we inherit and use declarations for arguments and how they will be resolved. These declarations will be mapped to the attributes on the resolved model.
75
+ To begin, we install the gem by adding it to our `Gemfile`:
76
+
77
+ `
78
+ gem 'graphql-rails-resolver'
79
+ `
80
+
81
+ This will load a class by the name of `GraphQL::Rails::Resolver`
82
+
83
+ Take the Resolver from the previous example. Using `GraphQL::Rails::Resolver`, we inherit and use declarations for arguments and how they will be resolved. These declarations will be mapped to the attributes on the resolved model.
75
84
 
76
85
  ```
77
86
  # Class name must match the Rails model name exactly.
78
87
 
79
- class Post < GraphQL::Rails::ActiveResolver
80
- # ID argument is resolved within ActiveResolver
88
+ class Post < GraphQL::Rails::Resolver
89
+ # ID argument is resolved in base class
81
90
 
82
91
  # Resolve :is_public to a class method
83
92
  resolve_method :is_public
@@ -87,6 +96,18 @@ class Post < GraphQL::Rails::ActiveResolver
87
96
  resolve_where :created_at
88
97
  resolve_where :updated_at
89
98
 
99
+ # Resolve :featured argument with default test: if argument `featured` is present
100
+ resolve_scope :featured
101
+
102
+ # Same resolution as the line above, but send the value to the scope function
103
+ resolve_scope :featured, :with_value => true
104
+
105
+ # Resolve :featured scope if it passes custom argument test
106
+ resolve_scope :featured, -> (value) { value == :today }
107
+
108
+ # Resolve :is_public argument with a different scope name
109
+ resolve_scope :is_public, -> (value) { value != true }, :scope_name => :is_private
110
+
90
111
  def is_public(value)
91
112
  @result.is_public if value
92
113
  @result.is_private unless value
@@ -95,13 +116,15 @@ class Post < GraphQL::Rails::ActiveResolver
95
116
  end
96
117
  ```
97
118
 
98
- In the example above, there are two declarations:
119
+ In the example above, there are three declarations:
99
120
 
100
121
  `resolve_where` is a declarative approach using `ActiveRecord.where` to resolve arguments.
101
122
 
102
- `resolve_method` is an imperative approach that's useful for using Model scopes or custom resolution.
123
+ `resolve_scope` is an declarative way to call scopes on a model where a custom test for the argument can be specified with a closure.
124
+ - Use `with_value` to send the argument value to the scope closure.
125
+ - Use `scope_name` to map an argument to a scope by another name.
103
126
 
104
- [Help make scopes declarative!](#making-scopes-declarative)
127
+ `resolve_method` is an imperative approach that allows completely custom resolution.
105
128
 
106
129
 
107
130
 
@@ -115,7 +138,7 @@ end
115
138
  ```
116
139
 
117
140
  ### Find Model by ID
118
- Every Active Resolver includes the ability to resolve a model by ID. Using the following method, by default the resolver will find a model by **NodeIdentification.from_global_id(value)** or **Model.where(:id => value)**. This means a model can be resolved by Global ID or Integer ID.
141
+ `GraphQL::Rails::Resolver` includes the ability to resolve a model by ID. Using the following method, by default the resolver will find a model by **NodeIdentification.from_global_id(value)** or **Model.where(:id => value)**. This means a model can be resolved by Global ID or Integer ID.
119
142
  ```
120
143
  def lookup_id(value)
121
144
  ...
@@ -123,8 +146,8 @@ end
123
146
  ```
124
147
 
125
148
 
126
- ### Override Default Resolution
127
- The default behavior is to use `Model.all` to seed the resolution. This seed can be changed by providing a block or lambda to the class instance:
149
+ ### Override Default Scope
150
+ The default behavior is to use `Model.all` to scope the resolution. This scope can be changed by providing a block or lambda to the class instance:
128
151
  ```
129
152
  Resolvers::Post.new(Proc.new {
130
153
  ::Post.where(:created_at => ...)
@@ -133,22 +156,8 @@ Resolvers::Post.new(Proc.new {
133
156
 
134
157
 
135
158
  # Needs Help
136
- I wanted to release this utility for the hopes of sparking interest in Rails integration with `graphql-ruby`.
137
-
138
- If you wish to contribute to this project, any pull request is warmly welcomed. If time permits, I will continue to update this project to achieve the following:
139
-
140
- ### [Making Scopes Declarative](#making-scopes-declarative):
141
- For first release, scopes can only be resolved using `resolve_method`. The goal for further development is to stop using `resolve_method` and adapt other methods to facilitate resolution.
142
-
143
- The current syntax planned for scope resolution is as follows, where the argument is passed to the scope:
144
-
145
- ```
146
- resolve_scope :is_public, -> (args) { args[:is_public] == true }
147
- resolve_scope :is_private, -> (args) { args[:is_public] == false }
148
- ```
149
-
150
-
159
+ I wanted to release this utility for the hopes of sparking interest in Rails integration with `graphql-ruby`. If you wish to contribute to this project, any pull request is warmly welcomed.
151
160
 
152
161
  # Credits
153
- - Cole Turner ([@colepatrickturner](/colepatrickturner))
154
- - Peter Salanki ([@salanki](/salanki))
162
+ - Cole Turner ([@colepatrickturner](https://github.com/colepatrickturner))
163
+ - Peter Salanki ([@salanki](https://github.com/salanki))
@@ -1,7 +1,9 @@
1
1
  module GraphQL
2
2
  module Rails
3
3
  class Resolver
4
- VERSION = '0.1.2'
4
+ VERSION = '0.1.3'
5
+
6
+ attr_accessor :resolvers
5
7
 
6
8
  def initialize(callable=nil)
7
9
  unless callable.nil?
@@ -12,7 +14,7 @@ module GraphQL
12
14
  @obj = nil
13
15
  @args = nil
14
16
  @ctx = nil
15
- @resolvers = {}
17
+ @resolvers = self.class.resolvers
16
18
  end
17
19
 
18
20
  def call(obj, args, ctx)
@@ -29,7 +31,7 @@ module GraphQL
29
31
 
30
32
  @resolvers.each do |field,method|
31
33
  if args.key? field
32
- method
34
+ @result = method.call(@result, args[field])
33
35
  end
34
36
  end
35
37
 
@@ -75,28 +77,6 @@ module GraphQL
75
77
  "::#{self.class.name.demodulize}".constantize
76
78
  end
77
79
 
78
- def self.resolve(field, method)
79
- self.class_eval do
80
- @resolvers[field] = method
81
- end
82
- end
83
-
84
- def self.resolve_where(field)
85
- self.class_eval do
86
- resolve(field, Proc.new {
87
- @result = @result.where(field, @args[field])
88
- })
89
- end
90
- end
91
-
92
- def self.resolve_method(field)
93
- self.class_eval do
94
- resolve(field, Proc.new {
95
- send(field, @args[field])
96
- })
97
- end
98
- end
99
-
100
80
  def lookup_id(value)
101
81
  if is_global_id(value)
102
82
  type_name, id = NodeIdentification.from_global_id(value)
@@ -112,7 +92,49 @@ module GraphQL
112
92
  end
113
93
  end
114
94
 
95
+ class << self
96
+
97
+ def resolvers
98
+ @resolvers ||= {}
99
+ @resolvers
100
+ end
101
+
102
+ def resolve(field, method)
103
+ @resolvers ||= {}
104
+ @resolvers[field] = method
105
+ end
106
+
107
+ def resolve_where(field)
108
+ resolve(field, lambda { |obj, value|
109
+ where = {}
110
+ where[field] = value
111
+
112
+ obj.where(where)
113
+ })
114
+ end
115
+
116
+ def resolve_scope(field, test=nil, scope_name: nil, with_value: false)
117
+ test = lambda { |value| value.present? } if test.nil?
118
+ scope_name = field if scope_name.nil?
115
119
 
120
+ resolve(field, lambda { |obj, value|
121
+ args = []
122
+ args.push(value) if with_value
123
+
124
+ if test.call(value)
125
+ obj.send(scope_name, *args)
126
+ else
127
+ obj
128
+ end
129
+ })
130
+ end
131
+
132
+ def resolve_method(field)
133
+ resolve(field, lambda { |obj, value|
134
+ obj.send(field, value)
135
+ })
136
+ end
137
+ end
116
138
  end
117
139
  end
118
140
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql-rails-resolver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cole Turner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-22 00:00:00.000000000 Z
11
+ date: 2016-09-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql
@@ -44,6 +44,8 @@ executables: []
44
44
  extensions: []
45
45
  extra_rdoc_files: []
46
46
  files:
47
+ - CHANGELOG.md
48
+ - LICENSE
47
49
  - README.md
48
50
  - lib/graphql/rails.rb
49
51
  - lib/graphql/rails/resolver.rb