graphiform 0.1.3 → 0.2.3

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
  SHA256:
3
- metadata.gz: d6bde49d1fc203265aee73785f6ff23308b5d2098259dd7bbc762dc0a8c16322
4
- data.tar.gz: 061af2e25afdf9dad9fdedab5847212e3b7005c36290dfcbccdc73b085dd1588
3
+ metadata.gz: e55cfe2745a2343ff704c8fa0d6daaf8fde9a24c0d91e78fd938d0c143f74f6e
4
+ data.tar.gz: f4245107d1b61418d0a2e1995f845a42d56f8e45a33efa6cfd57f039795c587a
5
5
  SHA512:
6
- metadata.gz: 0df7c307f8fbaa68fa1a33ee60d9c364603dbd911cb3726fc20073cf1bb9decaf1809387f5048fa080cd4abb6908f51fd744c769cbbb5f8c1e88db7fe631a7a7
7
- data.tar.gz: df1bc69c8e412ae66be318d65c5574fef2cf1d5d2371a98ddd1293a6ceea9e7b4ac6e3bcd794b1660e8c7a6e7fbe26aa97737b723e5f4d3d5b22ad256e42e8ee
6
+ metadata.gz: 8e09ad27673bd942cf6a761a090451f4dab2ebe7a09dfc509fba0311ca412b2ddbdb39cd83dddc237a19fbe2c001b227244ffac601c9301e41d18468f55bd5bd
7
+ data.tar.gz: beb387c2994ec3e01c16441e358e6e49c3cb14c6b47e3a5ee2ec103fce48b7c55b57350bb3d21e11b021bd6210852af51f9c135ccb9dd7074395cdd8b1e5b4fb
@@ -76,8 +76,38 @@ module Graphiform
76
76
  unless defined? @base_resolver
77
77
  @base_resolver = Helpers.get_const_or_create(demodulized_name, ::Resolvers) do
78
78
  Class.new(::Resolvers::BaseResolver) do
79
- # Default resolver just returns the object to prevent exceptions
80
- define_method :resolve do |**_args|
79
+ attr_reader :value
80
+
81
+ class << self
82
+ attr_accessor :addon_resolve_blocks
83
+ end
84
+
85
+ def self.addon_resolve(&block)
86
+ @addon_resolve_blocks ||= []
87
+ @addon_resolve_blocks << block
88
+ end
89
+
90
+ def resolve(**args)
91
+ @value = base_resolve(**args)
92
+
93
+ if self.class.addon_resolve_blocks.present? && !self.class.addon_resolve_blocks.empty?
94
+ self.class.addon_resolve_blocks.each do |addon_resolve_block|
95
+ @value = instance_exec(**args, &addon_resolve_block)
96
+ end
97
+ end
98
+
99
+ @value
100
+ end
101
+
102
+ def apply_built_ins(where: nil, sort: nil, **)
103
+ @value = @value.apply_filters(where.to_h) if where.present? && @value.respond_to?(:apply_filters)
104
+ @value = @value.apply_sorts(sort.to_h) if sort.present? && @value.respond_to?(:apply_sorts)
105
+
106
+ @value
107
+ end
108
+
109
+ # Default resolver - meant to be overridden
110
+ def base_resolve(**)
81
111
  object
82
112
  end
83
113
  end
@@ -86,7 +116,14 @@ module Graphiform
86
116
  local_graphql_filter = graphql_filter
87
117
  local_graphql_sort = graphql_sort
88
118
 
119
+ model = self
89
120
  @base_resolver.class_eval do
121
+ unless respond_to?(:model)
122
+ define_method :model do
123
+ model
124
+ end
125
+ end
126
+
90
127
  argument :where, local_graphql_filter, required: false
91
128
  argument :sort, local_graphql_sort, required: false unless local_graphql_sort.arguments.empty?
92
129
  end
@@ -97,16 +134,14 @@ module Graphiform
97
134
 
98
135
  def graphql_query
99
136
  Helpers.get_const_or_create(demodulized_name, ::Resolvers::Queries) do
100
- model = self
101
137
  local_graphql_type = graphql_type
102
138
  Class.new(graphql_base_resolver) do
103
139
  type local_graphql_type, null: false
104
140
 
105
- define_method :resolve do |where: nil|
106
- val = model.all
107
- val = val.apply_filters(where.to_h) if where.present? && val.respond_to?(:apply_filters)
108
-
109
- val.first
141
+ def base_resolve(**args)
142
+ @value = model.all
143
+ apply_built_ins(**args)
144
+ @value.first
110
145
  end
111
146
  end
112
147
  end
@@ -114,37 +149,30 @@ module Graphiform
114
149
 
115
150
  def graphql_connection_query
116
151
  Helpers.get_const_or_create(demodulized_name, ::Resolvers::ConnectionQueries) do
117
- model = self
118
152
  connection_type = graphql_connection
119
153
  Class.new(graphql_base_resolver) do
120
154
  type connection_type, null: false
121
155
 
122
- define_method :resolve do |where: nil, sort: nil|
123
- val = model.all
124
- val = val.apply_filters(where.to_h) if where.present? && val.respond_to?(:apply_filters)
125
- val = val.apply_sorts(sort.to_h) if sort.present? && val.respond_to?(:apply_sorts)
126
-
127
- val
156
+ def base_resolve(**args)
157
+ @value = model.all
158
+ apply_built_ins(**args)
128
159
  end
129
160
  end
130
161
  end
131
162
  end
132
163
 
133
- def graphql_create_resolver(method_name, resolver_type = graphql_type, read_prepare: nil, **_options)
164
+ def graphql_create_resolver(method_name, resolver_type = graphql_type, read_prepare: nil, read_resolve: nil, **)
134
165
  Class.new(graphql_base_resolver) do
135
166
  type resolver_type, null: false
136
167
 
137
- define_method :resolve do |where: nil, **args|
138
- where_hash = where.to_h
139
-
140
- val = super(**args)
141
-
142
- val = val.public_send(method_name) if val.respond_to? method_name
143
- val = instance_exec(val, context, &read_prepare) if read_prepare
168
+ define_method :base_resolve do |**args|
169
+ @value = object
144
170
 
145
- return val.apply_filters(where_hash) if val.respond_to? :apply_filters
171
+ @value = instance_exec(@value, context, &read_resolve) if read_resolve
172
+ @value = @value.public_send(method_name) if !read_resolve && @value.respond_to?(method_name)
173
+ @value = instance_exec(@value, context, &read_prepare) if read_prepare
146
174
 
147
- val
175
+ apply_built_ins(**args)
148
176
  end
149
177
  end
150
178
  end
@@ -9,17 +9,18 @@ module Graphiform
9
9
  module ClassMethods
10
10
  def graphql_readable_field(
11
11
  name,
12
+ as: nil,
12
13
  **options
13
14
  )
14
- column_def = column(name)
15
- association_def = association(name)
15
+ column_def = column(as || name)
16
+ association_def = association(as || name)
16
17
 
17
- graphql_add_column_field(name, column_def, **options) if column_def.present?
18
- graphql_add_association_field(name, association_def, **options) if association_def.present?
19
- graphql_add_method_field(name, **options) unless column_def.present? || association_def.present?
18
+ graphql_add_column_field(name, column_def, as: as, **options) if column_def.present?
19
+ graphql_add_association_field(name, association_def, as: as, **options) if association_def.present?
20
+ graphql_add_method_field(name, as: as, **options) unless column_def.present? || association_def.present?
20
21
 
21
- graphql_add_scopes_to_filter(name)
22
- graphql_field_to_sort(name)
22
+ graphql_add_scopes_to_filter(name, as || name)
23
+ graphql_field_to_sort(name, as || name)
23
24
  end
24
25
 
25
26
  def graphql_writable_field(
@@ -31,25 +32,30 @@ module Graphiform
31
32
  description: nil,
32
33
  default_value: ::GraphQL::Schema::Argument::NO_DEFAULT,
33
34
  as: nil,
34
- **_options
35
+ **
35
36
  )
36
37
  name = name.to_sym
37
- argument_name = graphql_resolve_argument_name(name)
38
- argument_type = graphql_resolve_argument_type(name, type)
38
+ has_nested_attributes_method = instance_methods.include?("#{as || name}_attributes=".to_sym)
39
+
40
+ argument_name = has_nested_attributes_method ? "#{name}_attributes".to_sym : name
41
+ argument_type = graphql_resolve_argument_type(as || name, type)
42
+ as = has_nested_attributes_method ? "#{as}_attributes".to_sym : as.to_sym if as
39
43
 
40
- return Helpers.logger.warn "Graphiform: Missing `type` for argument #{name}" if argument_type.nil?
44
+ return Helpers.logger.warn "Graphiform: Missing `type` for argument `#{name}` in model `#{self.name}`" if argument_type.nil?
41
45
 
42
46
  prepare = write_prepare || prepare
43
47
 
44
48
  graphql_input.class_eval do
45
- argument \
49
+ argument(
46
50
  argument_name,
47
51
  argument_type,
48
52
  required: required,
49
53
  prepare: prepare,
50
54
  description: description,
51
55
  default_value: default_value,
52
- as: as
56
+ as: as,
57
+ method_access: false
58
+ )
53
59
  end
54
60
  end
55
61
 
@@ -84,14 +90,6 @@ module Graphiform
84
90
 
85
91
  private
86
92
 
87
- def graphql_resolve_argument_name(name)
88
- attributes_name = "#{name}_attributes"
89
-
90
- return attributes_name.to_sym if instance_methods.include?("#{attributes_name}=".to_sym)
91
-
92
- name
93
- end
94
-
95
93
  def graphql_resolve_argument_type(name, type)
96
94
  type = graphql_create_enum(name) if type.blank? && enum_attribute?(name)
97
95
 
@@ -109,12 +107,12 @@ module Graphiform
109
107
  has_many ? [association_def.klass.graphql_input] : association_def.klass.graphql_input
110
108
  end
111
109
 
112
- def graphql_add_scopes_to_filter(name)
113
- added_scopes = auto_scopes_by_attribute(name)
110
+ def graphql_add_scopes_to_filter(name, as)
111
+ added_scopes = auto_scopes_by_attribute(as)
114
112
 
115
113
  return if added_scopes.empty?
116
114
 
117
- association_def = association(name)
115
+ association_def = association(as)
118
116
 
119
117
  if association_def.present?
120
118
  return unless Helpers.association_arguments_valid?(association_def, :graphql_filter)
@@ -130,19 +128,18 @@ module Graphiform
130
128
  enum = graphql_create_enum(name)
131
129
  scope_argument_type = scope_argument_type.is_a?(Array) ? [enum] : enum
132
130
  end
133
- add_scope_def_to_filter(added_scope, scope_argument_type)
131
+ add_scope_def_to_filter(name, added_scope, scope_argument_type)
134
132
  end
135
133
  end
136
134
 
137
- def add_scope_def_to_filter(scope_def, argument_type)
135
+ def add_scope_def_to_filter(name, scope_def, argument_type)
138
136
  return unless argument_type
139
137
 
140
138
  argument_type = Helpers.graphql_type(argument_type)
141
- camelized_attribute = scope_def.attribute.to_s.camelize(:lower)
139
+ argument_attribute = name
142
140
  argument_prefix = scope_def.prefix
143
- argument_suffix = scope_def.suffix
144
- argument_suffix = argument_suffix == '_is' ? '' : argument_suffix
145
- argument_name = "#{argument_prefix}#{camelized_attribute}#{argument_suffix}"
141
+ argument_suffix = scope_def.suffix == '_is' ? '' : scope_def.suffix
142
+ argument_name = "#{argument_prefix}#{argument_attribute}#{argument_suffix}".underscore
146
143
  scope_name = scope_def.name
147
144
 
148
145
  graphql_filter.class_eval do
@@ -150,15 +147,15 @@ module Graphiform
150
147
  argument_name,
151
148
  argument_type,
152
149
  required: false,
153
- camelize: false,
154
- as: scope_name
150
+ as: scope_name,
151
+ method_access: false
155
152
  )
156
153
  end
157
154
  end
158
155
 
159
- def graphql_field_to_sort(name)
160
- column_def = column(name)
161
- association_def = association(name)
156
+ def graphql_field_to_sort(name, as)
157
+ column_def = column(as || name)
158
+ association_def = association(as || name)
162
159
 
163
160
  type = ::Enums::Sort if column_def.present?
164
161
  type = association_def.klass.graphql_sort if Helpers.association_arguments_valid?(association_def, :graphql_sort)
@@ -171,7 +168,9 @@ module Graphiform
171
168
  argument(
172
169
  name,
173
170
  type,
174
- required: false
171
+ required: false,
172
+ as: as,
173
+ method_access: false
175
174
  )
176
175
  end
177
176
  end
@@ -183,18 +182,21 @@ module Graphiform
183
182
  description: nil,
184
183
  deprecation_reason: nil,
185
184
  method: nil,
185
+ as: nil,
186
186
  read_prepare: nil,
187
- **_options
187
+ read_resolve: nil,
188
+ **
188
189
  )
190
+ type = Helpers.graphql_type(type)
191
+ is_resolver = Helpers.resolver?(type)
192
+
189
193
  field_name = field_name.to_sym
190
194
  field_options = {
191
195
  description: description,
192
196
  deprecation_reason: deprecation_reason,
193
- method: method,
197
+ method: is_resolver ? nil : method || as,
194
198
  }
195
199
 
196
- type = Helpers.graphql_type(type)
197
-
198
200
  if Helpers.resolver?(type)
199
201
  field_options[:resolver] = type
200
202
  else
@@ -205,28 +207,42 @@ module Graphiform
205
207
  graphql_type.class_eval do
206
208
  added_field = field(field_name, **field_options)
207
209
 
208
- if read_prepare
210
+ if read_prepare || read_resolve
209
211
  define_method(
210
212
  added_field.method_sym,
211
- -> { instance_exec(object.public_send(added_field.method_sym), context, &read_prepare) }
213
+ lambda do
214
+ value = read_resolve ? instance_exec(object, context, &read_resolve) : object.public_send(added_field.method_sym)
215
+ value = instance_exec(value, context, &read_prepare) if read_prepare
216
+
217
+ value
218
+ end
212
219
  )
213
220
  end
214
221
  end
215
222
  end
216
223
 
217
- def graphql_add_column_field(field_name, column_def, type: nil, null: nil, **options)
218
- is_enum = type.blank? && enum_attribute?(field_name)
224
+ def graphql_add_column_field(field_name, column_def, type: nil, null: nil, as: nil, **options)
225
+ is_enum = type.blank? && enum_attribute?(as || field_name)
219
226
  if is_enum
220
- enum = graphql_create_enum(field_name)
227
+ enum = graphql_create_enum(as || field_name)
221
228
  type = enum
222
229
  end
223
230
  type ||= column_def.type
224
231
  null = column_def.null if null.nil?
225
232
 
226
- graphql_add_field_to_type(field_name, type, null, **options)
233
+ graphql_add_field_to_type(field_name, type, null, as: as, **options)
227
234
  end
228
235
 
229
- def graphql_add_association_field(field_name, association_def, type: nil, null: nil, include_connection: true, read_prepare: nil, **options)
236
+ def graphql_add_association_field(
237
+ field_name,
238
+ association_def,
239
+ type: nil,
240
+ null: nil,
241
+ include_connection: true,
242
+ read_prepare: nil,
243
+ read_resolve: nil,
244
+ **options
245
+ )
230
246
  unless association_def.klass.respond_to?(:graphql_type)
231
247
  return Helpers.logger.warn(
232
248
  "Graphiform: `#{name}` trying to add association `#{field_name}` - `#{association_def.klass.name}` does not include Graphiform"
@@ -245,23 +261,43 @@ module Graphiform
245
261
  if include_connection && has_many
246
262
  graphql_add_field_to_type(
247
263
  "#{field_name}_connection",
248
- klass.graphql_create_resolver(association_def.name, klass.graphql_connection, read_prepare: read_prepare),
264
+ klass.graphql_create_resolver(
265
+ association_def.name,
266
+ klass.graphql_connection,
267
+ read_prepare: read_prepare,
268
+ read_resolve: read_resolve
269
+ ),
249
270
  false,
250
271
  **options
251
272
  )
252
273
  end
253
274
 
254
275
  if type.nil?
255
- type = has_many ? klass.graphql_create_resolver(association_def.name, [klass.graphql_type], read_prepare: read_prepare) : klass.graphql_type
256
- read_prepare = nil if has_many
276
+ type = (
277
+ if has_many
278
+ klass.graphql_create_resolver(
279
+ association_def.name,
280
+ [klass.graphql_type],
281
+ read_prepare: read_prepare,
282
+ read_resolve: read_resolve
283
+ )
284
+ else
285
+ klass.graphql_type
286
+ end
287
+ )
288
+
289
+ if has_many
290
+ read_prepare = nil
291
+ read_resolve = nil
292
+ end
257
293
  end
258
294
 
259
295
  null = association_def.macro != :has_many if null.nil?
260
296
 
261
- graphql_add_field_to_type(field_name, type, null, read_prepare: read_prepare, **options)
297
+ graphql_add_field_to_type(field_name, type, null, read_prepare: read_prepare, read_resolve: read_resolve, **options)
262
298
  end
263
299
 
264
- def graphql_add_method_field(field_name, type:, null: true, **options)
300
+ def graphql_add_method_field(field_name, type: nil, null: true, **options)
265
301
  return Helpers.logger.warn "Graphiform: Missing `type` for field `#{field_name}` in model `#{name}`" if type.nil?
266
302
 
267
303
  graphql_add_field_to_type(field_name, type, null, **options)
@@ -1,3 +1,3 @@
1
1
  module Graphiform
2
- VERSION = '0.1.3'.freeze
2
+ VERSION = '0.2.3'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphiform
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - jayce.pulsipher
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-19 00:00:00.000000000 Z
11
+ date: 2020-05-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord