hq-graphql 1.1.1 → 1.1.2

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
- 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