graphql-active_record 0.2.0 → 0.3.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
  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