graphql-active_record 0.2.0 → 0.3.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
  SHA1:
3
- metadata.gz: ddd18445547cbfe82e3526ffbcac6bb8e609ff8a
4
- data.tar.gz: 2bace41aa51e44c9c8d3725123f6324557b9aa41
3
+ metadata.gz: 10caa39790c95eaa28ada47d7f82ca23552c22dc
4
+ data.tar.gz: bd0c481b90ea4d88c6e033775a86c42924896b66
5
5
  SHA512:
6
- metadata.gz: b2060751108d72871b669d620a5169069f40581777df3a5c5314dd16329f7b99d8ac229741d3f896f5bbb9cc2528d38f4f05cf542613ffd6f0a816b11f303fac
7
- data.tar.gz: b6adb77476fbf746558d22e5629730507568a0dce4fc9f3253de624e3027c12f9f52d6765baa17902a979936082a2c476046b01760fa649b60469d602324a3e0
6
+ metadata.gz: c6ec6a31f0cc12597eb16481f8e211c17ad0997ae06c8a2b38f5e3caaa082ab4118b5a263172930f6ab0a20a78ec59623b3356abb5987c11f19561c6b8053b60
7
+ data.tar.gz: 92f9b98456949e083d1eaefc4a2e780185c981ecb8a3ab7487068971de3483de31fb12467ff6ca44cd50cc724760b02fadabf44426bc453ba0b9b66aabe56cb3
data/.gitignore CHANGED
@@ -7,3 +7,5 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+
11
+ *.gem
data/README.md CHANGED
@@ -1,15 +1,13 @@
1
- # Graphql::Active::Record
1
+ # GraphQL::ActiveRecordExtensions
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/graphql/active/record`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ Active Record includes for GraphQL
6
4
 
7
5
  ## Installation
8
6
 
9
7
  Add this line to your application's Gemfile:
10
8
 
11
9
  ```ruby
12
- gem 'graphql-active-record'
10
+ gem 'graphql-active_record'
13
11
  ```
14
12
 
15
13
  And then execute:
@@ -18,11 +16,18 @@ And then execute:
18
16
 
19
17
  Or install it yourself as:
20
18
 
21
- $ gem install graphql-active-record
19
+ $ gem install graphql-active_record
22
20
 
23
21
  ## Usage
24
22
 
25
- TODO: Write usage instructions here
23
+ Use like:
24
+
25
+ ```ruby
26
+ GraphQL::ActiveRecordExtensions::Field.new(type: Type, model: Model)
27
+
28
+ # using UUID
29
+ GraphQL::ActiveRecordExtensions::Field.new(type: Type, model: Model, use_uuid: true)
30
+ ```
26
31
 
27
32
  ## Development
28
33
 
@@ -32,7 +37,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
32
37
 
33
38
  ## Contributing
34
39
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/graphql-active-record.
40
+ Bug reports and pull requests are welcome on GitHub at https://github.com/brettjurgens/graphql-active-record.
36
41
 
37
42
 
38
43
  ## License
@@ -1,11 +1,11 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'graphql/active_record_extension/version'
4
+ require 'graphql/active_record_extensions/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "graphql-active_record"
8
- spec.version = Graphql::ActiveRecordExtension::VERSION
8
+ spec.version = GraphQL::ActiveRecordExtensions::VERSION
9
9
  spec.authors = ["Brett Jurgens"]
10
10
  spec.email = ["brett@brettjurgens.com"]
11
11
 
@@ -1,137 +1,5 @@
1
1
  require 'active_record'
2
2
  require 'graphql'
3
3
 
4
- require "graphql/active_record_extension/version"
5
-
6
- ##
7
- # This class allows GraphQL to translate ActiveRecord objects into
8
- # GraphQL objects easily and does an auto-include to make it
9
- # somewhat more efficient (hopefully)
10
- class GraphQL::ActiveRecordExtension < ::GraphQL::Field
11
- def initialize(model:, type:, use_uuid: false)
12
- @model = model
13
- @use_uuid = use_uuid
14
-
15
- self.type = type
16
- self.description = "Find a #{model.name} by ID"
17
- self.arguments = {
18
- id: GraphQL::Argument.define do
19
- type !GraphQL::ID_TYPE
20
- description "Id for record"
21
- end
22
- }
23
- end
24
-
25
- ##
26
- # override of GraphQL::Field.resolve
27
- # basically just provides the final object (in this case an AR model)
28
- # can check RDoc for graphql-ruby gem
29
- #
30
- # @param object not used
31
- # @param arguments List[GraphQL::Argument] List of Arguments for the field (i.e. id, uuid, etc.)
32
- # @param ctx [GraphQL::Context] the context of the GraphQL query
33
- #
34
- # @return eager-loaded ActiveRecord model
35
- def resolve(object, arguments, ctx)
36
- includes = map_includes(@model, ctx.ast_node.selections, ctx)
37
-
38
- model_with_includes = @model.includes(*includes)
39
- if @use_uuid
40
- model_with_includes.find_by_uuid(arguments['id'])
41
- else
42
- model_with_includes.find(arguments['id'])
43
- end
44
-
45
- rescue ActiveRecord::ConfigurationError => e
46
- @model.find(arguments['id'])
47
- end
48
-
49
- private
50
- ##
51
- # generates an array for use in AR::QueryMethods.includes
52
- # allows for nested includes as well
53
- # supports fragments
54
- #
55
- # @param model [ActiveRecord::Base] an ActiveRecord model
56
- # @param selections [GraphQL::Selection] selections on the current model
57
- # @param ctx [GraphQL::Context] the context of the GraphQL query. Used to map fragments to models
58
- #
59
- # @return Array of tables to include in the query
60
- def map_includes(model, selections, ctx)
61
- selections.map do |selection|
62
-
63
- table_name, node = handle_fragments(selection, ctx)
64
-
65
- if node.present? && node.selections.present?
66
- singular = table_name.singularize.to_sym
67
- plural = table_name.pluralize.to_sym
68
-
69
- # make sure that the next model is an ActiveRecord model
70
- next_model = singular.to_s.classify.safe_constantize
71
-
72
- if next_model.blank? || !(next_model < ActiveRecord::Base)
73
- next_model = model
74
- end
75
-
76
- nested = map_includes(next_model, node.selections, ctx)
77
-
78
- final_type = if model.reflections[singular].present?
79
- # this is for has_one relationships
80
- singular
81
-
82
- elsif model.reflections[plural].present?
83
- # this is for has_many relationships
84
- plural
85
-
86
- else
87
- # this is for non-AR models (i.e. Product)
88
- # so they use the correct parent
89
- # TODO Try to get possible_types and include those
90
- nil
91
- end
92
-
93
- if nested.present?
94
- if final_type
95
- # flatten is used for cases like Interfaces
96
- # i.e. Customer -> Product -> Loan
97
- # Product isn't an AR type
98
- { final_type => nested.flatten }
99
- else
100
- nested.compact
101
- end
102
-
103
- else
104
- final_type
105
- end
106
- else
107
- nil
108
- end
109
- end.compact
110
- end
111
-
112
- ##
113
- # method to handle fragments in GQL Query
114
- # works by finding the fragment reference in the context
115
- #
116
- # @param node [GraphQL::Language::Nodes::*] current node
117
- # @param ctx [GraphQL::Context] GQL Context used to map fragment to node
118
- #
119
- # @return [String, GraphQL::Language::Nodes::*] tuple of node name and node
120
- def handle_fragments(node, ctx)
121
- if node.class == GraphQL::Language::Nodes::FragmentSpread
122
- fragment = ctx.query.fragments[node.name]
123
- [fragment.type.underscore, fragment]
124
- elsif node.class == GraphQL::Language::Nodes::InlineFragment
125
- ##
126
- # avoid auto-including things in InlineFragments
127
- # If using an interface, not all fields are guaranteed to
128
- # exist in all of the implementing types, but at this point,
129
- # we can't tell if it will, because we don't know what type
130
- # we are dealing with.
131
- ##
132
- [nil, nil]
133
- else
134
- [node.name, node]
135
- end
136
- end
137
- end
4
+ require "graphql/active_record_extensions/version"
5
+ require "graphql/active_record_extensions/field"
@@ -0,0 +1,136 @@
1
+ ##
2
+ # This class allows GraphQL to translate ActiveRecord objects into
3
+ # GraphQL objects easily and does an auto-include to make it
4
+ # somewhat more efficient (hopefully)
5
+ module GraphQL
6
+ module ActiveRecordExtensions
7
+ class Field < ::GraphQL::Field
8
+ def initialize(model:, type:, use_uuid: false)
9
+ @model = model
10
+ @use_uuid = use_uuid
11
+
12
+ self.type = type
13
+ self.description = "Find a #{model.name} by ID"
14
+ self.arguments = {
15
+ id: GraphQL::Argument.define do
16
+ type !GraphQL::ID_TYPE
17
+ description "Id for record"
18
+ end
19
+ }
20
+ end
21
+
22
+ ##
23
+ # override of GraphQL::Field.resolve
24
+ # basically just provides the final object (in this case an AR model)
25
+ # can check RDoc for graphql-ruby gem
26
+ #
27
+ # @param object not used
28
+ # @param arguments List[GraphQL::Argument] List of Arguments for the field (i.e. id, uuid, etc.)
29
+ # @param ctx [GraphQL::Context] the context of the GraphQL query
30
+ #
31
+ # @return eager-loaded ActiveRecord model
32
+ def resolve(object, arguments, ctx)
33
+ includes = map_includes(@model, ctx.ast_node.selections, ctx)
34
+
35
+ model_with_includes = @model.includes(*includes)
36
+ if @use_uuid
37
+ model_with_includes.find_by_uuid(arguments['id'])
38
+ else
39
+ model_with_includes.find(arguments['id'])
40
+ end
41
+
42
+ rescue ActiveRecord::ConfigurationError => e
43
+ @model.find(arguments['id'])
44
+ end
45
+
46
+ private
47
+ ##
48
+ # generates an array for use in AR::QueryMethods.includes
49
+ # allows for nested includes as well
50
+ # supports fragments
51
+ #
52
+ # @param model [ActiveRecord::Base] an ActiveRecord model
53
+ # @param selections [GraphQL::Selection] selections on the current model
54
+ # @param ctx [GraphQL::Context] the context of the GraphQL query. Used to map fragments to models
55
+ #
56
+ # @return Array of tables to include in the query
57
+ def map_includes(model, selections, ctx)
58
+ selections.map do |selection|
59
+
60
+ table_name, node = handle_fragments(selection, ctx)
61
+
62
+ if node.present? && node.selections.present?
63
+ singular = table_name.singularize.to_sym
64
+ plural = table_name.pluralize.to_sym
65
+
66
+ # make sure that the next model is an ActiveRecord model
67
+ next_model = singular.to_s.classify.safe_constantize
68
+
69
+ if next_model.blank? || !(next_model < ActiveRecord::Base)
70
+ next_model = model
71
+ end
72
+
73
+ nested = map_includes(next_model, node.selections, ctx)
74
+
75
+ final_type = if model.reflections[singular].present?
76
+ # this is for has_one relationships
77
+ singular
78
+
79
+ elsif model.reflections[plural].present?
80
+ # this is for has_many relationships
81
+ plural
82
+
83
+ else
84
+ # this is for non-AR models (i.e. Product)
85
+ # so they use the correct parent
86
+ # TODO Try to get possible_types and include those
87
+ nil
88
+ end
89
+
90
+ if nested.present?
91
+ if final_type
92
+ # flatten is used for cases like Interfaces
93
+ # i.e. Customer -> Product -> Loan
94
+ # Product isn't an AR type
95
+ { final_type => nested.flatten }
96
+ else
97
+ nested.compact
98
+ end
99
+
100
+ else
101
+ final_type
102
+ end
103
+ else
104
+ nil
105
+ end
106
+ end.compact
107
+ end
108
+
109
+ ##
110
+ # method to handle fragments in GQL Query
111
+ # works by finding the fragment reference in the context
112
+ #
113
+ # @param node [GraphQL::Language::Nodes::*] current node
114
+ # @param ctx [GraphQL::Context] GQL Context used to map fragment to node
115
+ #
116
+ # @return [String, GraphQL::Language::Nodes::*] tuple of node name and node
117
+ def handle_fragments(node, ctx)
118
+ if node.class == GraphQL::Language::Nodes::FragmentSpread
119
+ fragment = ctx.query.fragments[node.name]
120
+ [fragment.type.underscore, fragment]
121
+ elsif node.class == GraphQL::Language::Nodes::InlineFragment
122
+ ##
123
+ # avoid auto-including things in InlineFragments
124
+ # If using an interface, not all fields are guaranteed to
125
+ # exist in all of the implementing types, but at this point,
126
+ # we can't tell if it will, because we don't know what type
127
+ # we are dealing with.
128
+ ##
129
+ [nil, nil]
130
+ else
131
+ [node.name, node]
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,5 @@
1
+ module GraphQL
2
+ module ActiveRecordExtensions
3
+ VERSION = "0.3.0"
4
+ end
5
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql-active_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Jurgens
@@ -96,12 +96,9 @@ files:
96
96
  - bin/console
97
97
  - bin/setup
98
98
  - graphql-active-record.gemspec
99
- - graphql-active_record-0.1.1.gem
100
- - graphql-active_record-0.1.2.gem
101
- - graphql-active_record-0.1.3.gem
102
- - graphql-active_record-0.1.4.gem
103
99
  - lib/graphql/active_record_extension.rb
104
- - lib/graphql/active_record_extension/version.rb
100
+ - lib/graphql/active_record_extensions/field.rb
101
+ - lib/graphql/active_record_extensions/version.rb
105
102
  homepage: http://github.com/brettjurgens/graphql-active-record
106
103
  licenses:
107
104
  - MIT
Binary file
Binary file
Binary file
Binary file
@@ -1,5 +0,0 @@
1
- module Graphql
2
- module ActiveRecordExtension
3
- VERSION = "0.2.0"
4
- end
5
- end