hq-graphql 1.1.1 → 1.1.2

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
- SHA1:
3
- metadata.gz: 13d8a60ff262b288fd5918633fc2db7450620e2b
4
- data.tar.gz: 611a0ae3cea59bc3318339dc4d06d9c6370ccbde
2
+ SHA256:
3
+ metadata.gz: 7efcc65afc49394548596015925cb1507dbcc34a5a7517256b430bef6528e9a0
4
+ data.tar.gz: 73412d83d3ed91883e2429b1d6ace253fc7df899358d4a22ff5f70afebdf9a31
5
5
  SHA512:
6
- metadata.gz: 4ac1a7aee6c9eb6df449258dfc71624900fee0e70d6c50f8d57596acf6a9b76ce7a81da4ab26aaa7d6b1bd3bc104402c5deff3630821a193a74a040f45ef2757
7
- data.tar.gz: f78cee42cdece49c7211ceec67ac576438eb9bc4e707d9dbb9d6deab6f0835f88ee954cf25f8d8b7b875e29b9126b1aa0adbad8c30b78c702c2ef6d7234e0b8b
6
+ metadata.gz: d91c6236223a1e7d87c4a2fc46bcc3648d291db13d376d7afef25c0441007f4e651072081fcba1ec8edea259b689930d106473d03a91908ab9a4ebf62348c99e
7
+ data.tar.gz: 425964b4dfd40e6f30b34a061c8486ce1bcef8d3860ece699790aac1064943a36a203dfc373a66d5f8372eedc4cff5298fe01611eb0a1ada0bf67614c9238a3e
data/README.md CHANGED
@@ -89,7 +89,7 @@ class Schema < ::GraphQL::Schema
89
89
  end
90
90
  ```
91
91
 
92
- ### Root Queries
92
+ ### Default Root Queries
93
93
  Create a root query:
94
94
  ```ruby
95
95
  class AdvisorResource
@@ -106,6 +106,26 @@ class Schema < ::GraphQL::Schema
106
106
  end
107
107
  ```
108
108
 
109
+ ### Custom Root Queries
110
+ ```ruby
111
+ class AdvisorResource
112
+ include ::HQ::GraphQL::Resource
113
+ self.model_name = "Advisor"
114
+
115
+ def_root :advisors, is_array: true, null: false do
116
+ argument :active, ::GraphQL::Types::Boolean, required: false
117
+
118
+ def resolve(active: nil)
119
+ scope = Advisor.all
120
+
121
+ if active
122
+ scope = scope.where(active: true)
123
+ end
124
+ end
125
+ end
126
+ end
127
+ ```
128
+
109
129
  ## Create a new ::HQ::GraphQL::Object
110
130
  ```ruby
111
131
  class AdvisorType < ::HQ::GraphQL::Object
@@ -8,7 +8,16 @@ module HQ
8
8
  def format_nested_attributes
9
9
  self.each.inject({}) do |formatted_attrs, (key, value) |
10
10
  if self.class.nested_attributes.include?(key.to_s)
11
- formatted_attrs["#{key}_attributes"] = value.format_nested_attributes
11
+ formatted_value =
12
+ if value.is_a?(Array)
13
+ value.map(&:format_nested_attributes)
14
+ elsif value
15
+ value.format_nested_attributes
16
+ end
17
+
18
+ formatted_attrs[:"#{key}_attributes"] = formatted_value if formatted_value
19
+ elsif key.to_s == "x"
20
+ formatted_attrs[:X] = value
12
21
  else
13
22
  formatted_attrs[key] = value
14
23
  end
@@ -35,6 +44,8 @@ module HQ
35
44
  model_associations.each do |association|
36
45
  argument_from_association association
37
46
  end
47
+
48
+ argument :X, String, required: false
38
49
  end
39
50
  end
40
51
 
@@ -11,7 +11,7 @@ module HQ
11
11
  end
12
12
 
13
13
  module ClassMethods
14
- attr_accessor :model_name
14
+ attr_writer :graphql_name, :model_name
15
15
 
16
16
  def find_record(attrs, context)
17
17
  primary_key = model_klass.primary_key.to_sym
@@ -19,6 +19,14 @@ module HQ
19
19
  scope(context).find_by(primary_key => primary_key_value)
20
20
  end
21
21
 
22
+ def graphql_name
23
+ @graphql_name || model_name.demodulize
24
+ end
25
+
26
+ def model_name
27
+ @model_name || name.demodulize
28
+ end
29
+
22
30
  def model_klass
23
31
  @model_klass ||= model_name&.safe_constantize
24
32
  end
@@ -46,12 +54,12 @@ module HQ
46
54
  end
47
55
 
48
56
  def mutations(create: true, update: true, destroy: true)
57
+ scoped_graphql_name = graphql_name
49
58
  scoped_model_name = model_name
50
- model_display_name = model_name.demodulize
51
59
  scoped_self = self
52
60
 
53
61
  if create
54
- create_mutation = ::HQ::GraphQL::Resource::Mutation.build(model_name, graphql_name: "#{model_display_name}Create") do
62
+ create_mutation = ::HQ::GraphQL::Resource::Mutation.build(model_name, graphql_name: "#{scoped_graphql_name}Create") do
55
63
  define_method(:resolve) do |**args|
56
64
  resource = scoped_self.model_klass.new
57
65
  resource.assign_attributes(args[:attributes].format_nested_attributes)
@@ -73,13 +81,13 @@ module HQ
73
81
  end
74
82
  end
75
83
 
76
- mutation_klasses["create_#{model_display_name.underscore}"] = create_mutation
84
+ mutation_klasses["create_#{scoped_graphql_name.underscore}"] = create_mutation
77
85
  end
78
86
 
79
87
  if update
80
88
  update_mutation = ::HQ::GraphQL::Resource::Mutation.build(
81
89
  model_name,
82
- graphql_name: "#{model_display_name}Update",
90
+ graphql_name: "#{scoped_graphql_name}Update",
83
91
  require_primary_key: true
84
92
  ) do
85
93
  define_method(:resolve) do |**args|
@@ -94,14 +102,14 @@ module HQ
94
102
  }
95
103
  else
96
104
  {
97
- resource: resource,
105
+ resource: nil,
98
106
  errors: errors_from_resource(resource)
99
107
  }
100
108
  end
101
109
  else
102
110
  {
103
111
  resource: nil,
104
- errors: { resource: "Unable to find #{model_display_name}" }
112
+ errors: { resource: "Unable to find #{scoped_graphql_name}" }
105
113
  }
106
114
  end
107
115
  end
@@ -111,13 +119,13 @@ module HQ
111
119
  end
112
120
  end
113
121
 
114
- mutation_klasses["update_#{model_display_name.underscore}"] = update_mutation
122
+ mutation_klasses["update_#{scoped_graphql_name.underscore}"] = update_mutation
115
123
  end
116
124
 
117
125
  if destroy
118
126
  destroy_mutation = ::HQ::GraphQL::Resource::Mutation.build(
119
127
  model_name,
120
- graphql_name: "#{model_display_name}Destroy",
128
+ graphql_name: "#{scoped_graphql_name}Destroy",
121
129
  require_primary_key: true
122
130
  ) do
123
131
  define_method(:resolve) do |**attrs|
@@ -131,20 +139,20 @@ module HQ
131
139
  }
132
140
  else
133
141
  {
134
- resource: resource,
142
+ resource: nil,
135
143
  errors: errors_from_resource(resource)
136
144
  }
137
145
  end
138
146
  else
139
147
  {
140
148
  resource: nil,
141
- errors: { resource: "Unable to find #{model_display_name}" }
149
+ errors: { resource: "Unable to find #{scoped_graphql_name}" }
142
150
  }
143
151
  end
144
152
  end
145
153
  end
146
154
 
147
- mutation_klasses["destroy_#{model_display_name.underscore}"] = destroy_mutation
155
+ mutation_klasses["destroy_#{scoped_graphql_name.underscore}"] = destroy_mutation
148
156
  end
149
157
  end
150
158
 
@@ -152,8 +160,45 @@ module HQ
152
160
  @query_klass = build_graphql_object(**options, &block)
153
161
  end
154
162
 
155
- def root_query
156
- ::HQ::GraphQL.root_queries << self
163
+ def def_root(field_name, is_array: false, null: true, &block)
164
+ graphql = self
165
+ resolver = -> {
166
+ Class.new(::GraphQL::Schema::Resolver) do
167
+ type = is_array ? [graphql.query_klass] : graphql.query_klass
168
+ type type, null: null
169
+ class_eval(&block) if block
170
+ end
171
+ }
172
+ ::HQ::GraphQL.root_queries << {
173
+ field_name: field_name, resolver: resolver
174
+ }
175
+ end
176
+
177
+ def root_query(find_one: true, find_all: true)
178
+ field_name = graphql_name.underscore
179
+ scoped_self = self
180
+
181
+ if find_one
182
+ def_root field_name, is_array: false, null: true do
183
+ klass = scoped_self.model_klass
184
+ primary_key = klass.primary_key
185
+ pk_column = klass.columns.detect { |c| c.name == primary_key.to_s }
186
+
187
+ argument primary_key, ::HQ::GraphQL::Types.type_from_column(pk_column), required: true
188
+
189
+ define_method(:resolve) do |**attrs|
190
+ scoped_self.find_record(attrs, context)
191
+ end
192
+ end
193
+ end
194
+
195
+ if find_all
196
+ def_root field_name.pluralize, is_array: true, null: false do
197
+ define_method(:resolve) do |**attrs|
198
+ scoped_self.scope(context).all
199
+ end
200
+ end
201
+ end
157
202
  end
158
203
 
159
204
  def scope(context)
@@ -165,9 +210,10 @@ module HQ
165
210
  private
166
211
 
167
212
  def build_graphql_object(**options, &block)
213
+ scoped_graphql_name = graphql_name
168
214
  scoped_model_name = model_name
169
215
  Class.new(::HQ::GraphQL::Object) do
170
- graphql_name scoped_model_name
216
+ graphql_name scoped_graphql_name
171
217
 
172
218
  with_model scoped_model_name, **options
173
219
 
@@ -176,9 +222,10 @@ module HQ
176
222
  end
177
223
 
178
224
  def build_input_object(**options, &block)
225
+ scoped_graphql_name = graphql_name
179
226
  scoped_model_name = model_name
180
227
  Class.new(::HQ::GraphQL::InputObject) do
181
- graphql_name "#{scoped_model_name.demodulize}Input"
228
+ graphql_name "#{scoped_graphql_name}Input"
182
229
 
183
230
  with_model scoped_model_name, **options
184
231
 
@@ -6,19 +6,8 @@ module HQ
6
6
  super
7
7
  base.class_eval do
8
8
  lazy_load do
9
- ::HQ::GraphQL.root_queries.each do |graphql|
10
- klass = graphql.model_klass
11
- field_name = klass.name.demodulize.underscore
12
- primary_key = klass.primary_key
13
- pk_column = klass.columns.detect { |c| c.name == primary_key.to_s }
14
-
15
- field field_name, graphql.query_klass, null: true do
16
- argument primary_key, ::HQ::GraphQL::Types.type_from_column(pk_column), required: true
17
- end
18
-
19
- define_method(field_name) do |**attrs|
20
- graphql.find_record(attrs, context)
21
- end
9
+ ::HQ::GraphQL.root_queries.each do |field_name:, resolver:|
10
+ field field_name, resolver: resolver.call
22
11
  end
23
12
  end
24
13
  end
@@ -40,6 +40,7 @@ module HQ
40
40
  def klass_for(klass_or_string)
41
41
  klass = klass_or_string.is_a?(String) ? klass_or_string.constantize : klass_or_string
42
42
  ::HQ::GraphQL.types.detect { |t| t.model_klass == klass }&.query_klass ||
43
+ ::HQ::GraphQL.types.detect { |t| t.model_klass == klass.base_class }&.query_klass ||
43
44
  raise(Error, Error::MISSING_TYPE_MSG % { klass: klass.name })
44
45
  end
45
46
  end
@@ -1,5 +1,5 @@
1
1
  module HQ
2
2
  module GraphQL
3
- VERSION = "1.1.1"
3
+ VERSION = "1.1.2"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hq-graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Danny Jones
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-27 00:00:00.000000000 Z
11
+ date: 2019-07-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -33,7 +33,7 @@ dependencies:
33
33
  version: '1.0'
34
34
  - - ">="
35
35
  - !ruby/object:Gem::Version
36
- version: 1.8.10
36
+ version: 1.9.6
37
37
  type: :runtime
38
38
  prerelease: false
39
39
  version_requirements: !ruby/object:Gem::Requirement
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '1.0'
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: 1.8.10
46
+ version: 1.9.6
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rspec_junit_formatter
49
49
  requirement: !ruby/object:Gem::Requirement
@@ -111,26 +111,6 @@ files:
111
111
  - lib/hq/graphql/types/object.rb
112
112
  - lib/hq/graphql/types/uuid.rb
113
113
  - lib/hq/graphql/version.rb
114
- - spec/factories/advisors.rb
115
- - spec/factories/organizations.rb
116
- - spec/factories/users.rb
117
- - spec/internal/app/models/advisor.rb
118
- - spec/internal/app/models/organization.rb
119
- - spec/internal/app/models/test_type.rb
120
- - spec/internal/app/models/user.rb
121
- - spec/internal/config/database.circleci.yml
122
- - spec/internal/config/database.yml
123
- - spec/internal/db/schema.rb
124
- - spec/lib/graphql/active_record_extensions_spec.rb
125
- - spec/lib/graphql/input_object_spec.rb
126
- - spec/lib/graphql/inputs_spec.rb
127
- - spec/lib/graphql/object_spec.rb
128
- - spec/lib/graphql/resource_spec.rb
129
- - spec/lib/graphql/types/object_spec.rb
130
- - spec/lib/graphql/types/uuid_spec.rb
131
- - spec/lib/graphql/types_spec.rb
132
- - spec/rails_helper.rb
133
- - spec/spec_helper.rb
134
114
  homepage: https://github.com/OneHQ/hq-graphql
135
115
  licenses:
136
116
  - MIT
@@ -151,28 +131,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
151
131
  version: '0'
152
132
  requirements: []
153
133
  rubyforge_project:
154
- rubygems_version: 2.5.2.2
134
+ rubygems_version: 2.7.6
155
135
  signing_key:
156
136
  specification_version: 4
157
137
  summary: OneHQ GraphQL Library
158
- test_files:
159
- - spec/spec_helper.rb
160
- - spec/internal/app/models/advisor.rb
161
- - spec/internal/app/models/organization.rb
162
- - spec/internal/app/models/test_type.rb
163
- - spec/internal/app/models/user.rb
164
- - spec/internal/config/database.circleci.yml
165
- - spec/internal/config/database.yml
166
- - spec/internal/db/schema.rb
167
- - spec/factories/organizations.rb
168
- - spec/factories/advisors.rb
169
- - spec/factories/users.rb
170
- - spec/lib/graphql/types/object_spec.rb
171
- - spec/lib/graphql/types/uuid_spec.rb
172
- - spec/lib/graphql/active_record_extensions_spec.rb
173
- - spec/lib/graphql/object_spec.rb
174
- - spec/lib/graphql/inputs_spec.rb
175
- - spec/lib/graphql/resource_spec.rb
176
- - spec/lib/graphql/input_object_spec.rb
177
- - spec/lib/graphql/types_spec.rb
178
- - spec/rails_helper.rb
138
+ test_files: []
@@ -1,6 +0,0 @@
1
- FactoryBot.define do
2
- factory :advisor do
3
- name { Faker::Name.name }
4
- organization { FactoryBot.build(:organization) }
5
- end
6
- end
@@ -1,5 +0,0 @@
1
- FactoryBot.define do
2
- factory :organization do
3
- name { Faker::Company.name }
4
- end
5
- end
@@ -1,6 +0,0 @@
1
- FactoryBot.define do
2
- factory :user do
3
- name { Faker::Name.name }
4
- organization { FactoryBot.build(:organization) }
5
- end
6
- end
@@ -1,3 +0,0 @@
1
- class Advisor < ActiveRecord::Base
2
- belongs_to :organization
3
- end
@@ -1,3 +0,0 @@
1
- class Organization < ::ActiveRecord::Base
2
- has_many :users, inverse_of: :organization
3
- end
@@ -1 +0,0 @@
1
- class TestType < ::ActiveRecord::Base; end
@@ -1,3 +0,0 @@
1
- class User < ::ActiveRecord::Base
2
- belongs_to :organization, inverse_of: :users
3
- end
@@ -1,24 +0,0 @@
1
- common: &common
2
- adapter: postgresql
3
- encoding: utf8
4
- host: <%= ENV["DBHOST"] || "127.0.0.1" %>
5
- port: <%= ENV["DBPORT"] || "5432" %>
6
- database: <%= ENV["DBNAME"] || "hq-graphql" %>
7
- username: <%= ENV["DBUSER"] || "postgres" %>
8
- password: <%= ENV["DBPASSWORD"] || "" %>
9
- pool: 5
10
- reconnect: true
11
- timeout: 5000
12
-
13
- development:
14
- <<: *common
15
-
16
- test:
17
- <<: *common
18
-
19
- staging:
20
- <<: *common
21
-
22
- production:
23
- <<: *common
24
- pool: 10
@@ -1,8 +0,0 @@
1
- test:
2
- adapter: postgresql
3
- database: <%= ENV['DB'] || 'hq-graphql_test' %>
4
- username: <%= ENV['DB_USERNAME'] || %x[id -un] %> # `id -un` returns the active user in OSX (at least as of 10.10)
5
- password:
6
- timeout: 5000
7
- encoding: utf8
8
- pool: 25
@@ -1,30 +0,0 @@
1
- ActiveRecord::Schema.define do
2
- enable_extension "uuid-ossp"
3
-
4
- create_table "organizations", force: true, id: :uuid do |t|
5
- t.string :name, limit: 63, null: false
6
- t.timestamps null: false
7
- end
8
-
9
- create_table "users", force: true, id: :uuid do |t|
10
- t.belongs_to :organization, null: false, index: true, foreign_key: true, type: :uuid
11
- t.string :name, null: false
12
- t.timestamps null: false
13
- end
14
-
15
- create_table "advisors", force: true, id: :uuid do |t|
16
- t.references :organization, null: false, index: true, foreign_key: true, type: :uuid
17
- t.string :name, null: false
18
- t.timestamps null: false
19
- end
20
-
21
- create_table "test_types", force: true, id: :uuid do |t|
22
- t.jsonb :data_jsonb
23
- t.json :data_json
24
- t.integer :count
25
- t.decimal :amount
26
- t.boolean :is_bool
27
- t.string :name
28
- end
29
-
30
- end
@@ -1,63 +0,0 @@
1
- require 'rails_helper'
2
-
3
- describe ::HQ::GraphQL::ActiveRecordExtensions do
4
- let(:extended_klass) do
5
- Class.new do
6
- include ::HQ::GraphQL::ActiveRecordExtensions
7
-
8
- @counter = 0
9
-
10
- lazy_load do
11
- @counter += 1
12
- end
13
-
14
- def self.counter
15
- @counter
16
- end
17
- end
18
- end
19
-
20
- describe ".add_attributes" do
21
- it "aliases add_attributes" do
22
- add_attributes = extended_klass.method(:add_attributes)
23
- aggregate_failures do
24
- expect(add_attributes).to eql(extended_klass.method(:add_attribute))
25
- expect(add_attributes).to eql(extended_klass.method(:add_attrs))
26
- expect(add_attributes).to eql(extended_klass.method(:add_attr))
27
- end
28
- end
29
- end
30
-
31
- describe ".remove_attributes" do
32
- it "aliases remove_attributes" do
33
- remove_attributes = extended_klass.method(:remove_attributes)
34
- aggregate_failures do
35
- expect(remove_attributes).to eql(extended_klass.method(:remove_attribute))
36
- expect(remove_attributes).to eql(extended_klass.method(:remove_attrs))
37
- expect(remove_attributes).to eql(extended_klass.method(:remove_attr))
38
- end
39
- end
40
- end
41
-
42
- describe ".add_associations" do
43
- it "aliases add_associations" do
44
- expect(extended_klass.method(:add_associations)).to eql(extended_klass.method(:add_association))
45
- end
46
- end
47
-
48
- describe ".remove_associations" do
49
- it "aliases remove_associations" do
50
- expect(extended_klass.method(:remove_associations)).to eql(extended_klass.method(:remove_association))
51
- end
52
- end
53
-
54
- describe ".lazy_load" do
55
- it "lazy loads once" do
56
- # First time it works
57
- expect { extended_klass.lazy_load! }.to change { extended_klass.counter }.by(1)
58
- # Second time it does nothing
59
- expect { extended_klass.lazy_load! }.to change { extended_klass.counter }.by(0)
60
- end
61
- end
62
-
63
- end