gql 0.0.19 → 0.0.20

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: 770f58471faa9640c902c42c9d89329b3af9a458
4
- data.tar.gz: d95c3150739cbd190256a55adcec0a65c7a059b2
3
+ metadata.gz: 84b1f6dbe8ad680fd457f4f14dbd0183b4b18d46
4
+ data.tar.gz: 192058fde95f568491e87c6edd719b9a4c85b1c1
5
5
  SHA512:
6
- metadata.gz: bc67c88490eac0c385ae5cf53558249342552d8e1a97c6ba719adc4f0495be148529f928bd400236eca5aeeac5eb8377d94cb965bb5d5025ca1f9c32260d2c23
7
- data.tar.gz: 0927523dd03114407ffecb1797997a5620ab4dfc10efa7f0d84571945e47c24625a3a412deb9bdecf25e383ea18df4467db27f4d42c951b1f391caf732f54cd7
6
+ metadata.gz: dee4291ac7f769adf121c145b8f2a2a93bd0a3417aba29e218120cc2106045f2e4f19cbcd2491b778aff4531f6c04d88acb39500bae1d24763be054131cfe29a
7
+ data.tar.gz: ae67282c3aa9cf8b48155429c7f6714f16562ba3ff77fdf9f4a9edcfabc8fae59d02b7472490599f3959b36a2af82971ad8ff36754be8f3b8b61cf71d757ff64
data/lib/gql.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require 'active_support/dependencies/autoload'
2
+
2
3
  require 'gql/version'
4
+ require 'gql/errors'
3
5
 
4
6
  module GQL
5
7
  extend ActiveSupport::Autoload
@@ -9,33 +11,17 @@ module GQL
9
11
  autoload :Call
10
12
  autoload :Config
11
13
  autoload :Connection
12
- autoload :Error, 'gql/errors'
13
14
  autoload :Executor
14
15
  autoload :Field
16
+ autoload :Lazy
15
17
  autoload :Number
16
18
  autoload :Object
17
19
  autoload :Parser
20
+ autoload :Registry
18
21
  autoload :Scalar
19
22
  autoload :String
20
- autoload :TestCase
21
23
  autoload :Tokenizer
22
24
 
23
- module Errors
24
- extend ActiveSupport::Autoload
25
-
26
- autoload_at 'gql/errors' do
27
- autoload :CallNotFound
28
- autoload :FieldClassNotSet
29
- autoload :FieldNotFound
30
- autoload :InvalidFieldClass
31
- autoload :NoMethodError
32
- autoload :RootClassNotSet
33
- autoload :ScanError
34
- autoload :SyntaxError
35
- autoload :VariableNotFound
36
- end
37
- end
38
-
39
25
  module Schema
40
26
  extend ActiveSupport::Autoload
41
27
 
@@ -55,8 +41,8 @@ module GQL
55
41
  Thread.current[:gql_config] = value
56
42
  end
57
43
 
58
- %w(root_field_class root_target_proc field_types
59
- default_list_field_class default_field_proc
44
+ %w(root_class root_target_proc field_types
45
+ default_list_class default_field_proc
60
46
  default_call_proc debug).each do |method|
61
47
  module_eval <<-DELEGATORS, __FILE__, __LINE__ + 1
62
48
  def #{method}
@@ -2,32 +2,26 @@ require 'active_support/core_ext/class/attribute'
2
2
 
3
3
  module GQL
4
4
  class Array < Field
5
- class_attribute :item_field_class, instance_accessor: false, instance_predicate: false
5
+ class_attribute :item_class, instance_accessor: false, instance_predicate: false
6
6
 
7
7
  class << self
8
8
  def build_class(id, proc, options = {})
9
- item_field_class = options.delete(:item_field_class) || self.item_field_class
10
-
11
- if item_field_class.is_a?(Hash)
12
- item_field_class.values.each do |ifc|
13
- Field.validate_is_subclass! ifc, 'item_field_class'
14
- end
15
- else
16
- Field.validate_is_subclass! item_field_class, 'item_field_class'
17
- item_field_class = Hash.new(item_field_class)
18
- end
9
+ item_class = options.delete(:item_class) || self.item_class
10
+ item_class = ::Hash.new(item_class) unless item_class.is_a?(::Hash)
19
11
 
20
12
  Class.new(self).tap do |field_class|
21
- field_class.id = id.to_s
13
+ field_class.id = id
22
14
  field_class.proc = proc
23
- field_class.item_field_class = item_field_class
15
+ field_class.item_class = item_class
24
16
  end
25
17
  end
26
18
  end
27
19
 
28
20
  def value
29
21
  target.map do |item|
30
- field = self.class.item_field_class[item.class].new(ast_node, item, variables, context)
22
+ field_class = Registry.fetch(self.class.item_class[item.class])
23
+
24
+ field = field_class.new(ast_node, item, variables, context)
31
25
  field.value
32
26
  end
33
27
  end
@@ -1,17 +1,11 @@
1
- require 'active_support/core_ext/class/subclasses'
2
-
3
1
  module GQL
4
2
  class Config
5
- def root_field_class
6
- @@root_field_class ||= nil
3
+ def root_class
4
+ @@root_class ||= nil
7
5
  end
8
6
 
9
- def root_field_class=(value)
10
- unless value.nil? || value <= Field
11
- raise Errors::InvalidFieldClass.new(value, Field)
12
- end
13
-
14
- @@root_field_class = value
7
+ def root_class=(value)
8
+ @@root_class = value
15
9
  end
16
10
 
17
11
  def root_target_proc
@@ -24,12 +18,12 @@ module GQL
24
18
 
25
19
  def field_types
26
20
  @@field_types ||= {
27
- array: Array,
28
- boolean: Boolean,
29
- connection: Connection,
30
- number: Number,
31
- object: Object,
32
- string: String
21
+ array: 'GQL::Array',
22
+ boolean: 'GQL::Boolean',
23
+ connection: 'GQL::Connection',
24
+ number: 'GQL::Number',
25
+ object: 'GQL::Object',
26
+ string: 'GQL::String'
33
27
  }
34
28
  end
35
29
 
@@ -37,16 +31,12 @@ module GQL
37
31
  @@field_types = value
38
32
  end
39
33
 
40
- def default_list_field_class
41
- @@default_list_field_class ||= Field
34
+ def default_list_class
35
+ @@default_list_class ||= 'GQL::Field'
42
36
  end
43
37
 
44
- def default_list_field_class=(value)
45
- unless value.nil? || value <= Field
46
- raise Errors::InvalidFieldClass.new(value, Field)
47
- end
48
-
49
- @@default_list_field_class = value
38
+ def default_list_class=(value)
39
+ @@default_list_class = value
50
40
  end
51
41
 
52
42
  def default_field_proc
@@ -77,6 +67,8 @@ module GQL
77
67
  def debug=(value)
78
68
  value = !!value
79
69
 
70
+ @@debug = nil unless defined?(@@debug)
71
+
80
72
  return if value == @@debug
81
73
 
82
74
  value ? switch_debug_on : switch_debug_off
@@ -86,39 +78,13 @@ module GQL
86
78
 
87
79
  private
88
80
  def switch_debug_on
89
- switch_on_type_field
90
- switch_on_execution_context
91
- end
92
-
93
- def switch_debug_off
94
- switch_off_type_field
95
- switch_off_execution_context
96
- end
97
-
98
- def switch_on_type_field
99
- return if Field.has_field? :__type__
100
-
101
- type_field_class = Field.object :__type__, -> { field_class }, field_class: Schema::Field
102
-
103
- Field.descendants.each do |field_class|
104
- field_class.fields[:__type__] = type_field_class
105
- end
106
- end
107
-
108
- def switch_off_type_field
109
- return unless Field.has_field? :__type__
110
-
111
- [Field, *Field.descendants].each do |field_class|
112
- field_class.remove_field :__type__
113
- end
114
- end
115
-
116
- def switch_on_execution_context
81
+ Field.object :__type__, -> { field_class }, class: Schema::Field
117
82
  Field.send :remove_const, :ExecutionContext if Field.const_defined?(:ExecutionContext)
118
83
  Field.const_set :ExecutionContext, Field::ExecutionContextDebug
119
84
  end
120
85
 
121
- def switch_off_execution_context
86
+ def switch_debug_off
87
+ Field.remove_field :__type__
122
88
  Field.send :remove_const, :ExecutionContext if Field.const_defined?(:ExecutionContext)
123
89
  Field.const_set :ExecutionContext, Field::ExecutionContextNoDebug
124
90
  end
@@ -1,16 +1,12 @@
1
- require 'active_support/core_ext/class/attribute'
2
-
3
1
  module GQL
4
2
  class Connection < Field
5
3
  class << self
6
4
  def build_class(id, proc, options = {})
7
- list_field_class = options.delete(:list_field_class) || GQL.default_list_field_class
8
- item_field_class = options.delete(:item_field_class)
9
-
10
- Field.validate_is_subclass! list_field_class, 'list_field_class'
5
+ list_class = options.delete(:list_class) || GQL.default_list_class
6
+ item_class = options.delete(:item_class)
11
7
 
12
- list_field_class.build_class(id, proc, options).tap do |field_class|
13
- field_class.array :edges, -> { target }, item_field_class: item_field_class
8
+ Registry.fetch(list_class).build_class(id, proc, options).tap do |field_class|
9
+ field_class.array :edges, -> { target }, item_class: item_class
14
10
  end
15
11
  end
16
12
  end
@@ -64,7 +64,7 @@ module GQL
64
64
  class RootClassNotSet < Error
65
65
  def initialize
66
66
  msg = "GQL root field class is not set. "
67
- msg << "Set it with `GQL.root_field_class = MyRootField'."
67
+ msg << "Set it with `GQL.root_class = MyRootField'."
68
68
 
69
69
  super(msg, 121)
70
70
  end
@@ -8,7 +8,7 @@ module GQL
8
8
  end
9
9
 
10
10
  def execute(context = {}, vars = {})
11
- field_class = GQL.root_field_class
11
+ field_class = GQL.root_class
12
12
 
13
13
  raise Errors::RootClassNotSet if field_class.nil?
14
14
 
@@ -16,7 +16,7 @@ module GQL
16
16
 
17
17
  target = GQL.root_target_proc.call(context)
18
18
 
19
- field = field_class.new(ast_root, target, variables, context)
19
+ field = Registry.fetch(field_class).new(ast_root, target, variables, context)
20
20
  field.value
21
21
  end
22
22
  end
@@ -1,7 +1,8 @@
1
1
  require 'active_support/core_ext/class/attribute'
2
2
 
3
- require 'gql/has_calls'
4
- require 'gql/has_fields'
3
+ require 'gql/mixins/common'
4
+ require 'gql/mixins/has_calls'
5
+ require 'gql/mixins/has_fields'
5
6
 
6
7
  module GQL
7
8
  class Field
@@ -14,20 +15,11 @@ module GQL
14
15
  field_class.proc = proc
15
16
  end
16
17
  end
17
-
18
- def validate_is_subclass!(subclass, name)
19
- if subclass.nil?
20
- raise Errors::FieldClassNotSet.new(self, name)
21
- end
22
-
23
- unless subclass <= self
24
- raise Errors::InvalidFieldClass.new(subclass, self)
25
- end
26
- end
27
18
  end
28
19
 
29
- include HasCalls
30
- include HasFields
20
+ extend Mixins::Common
21
+ include Mixins::HasCalls
22
+ include Mixins::HasFields
31
23
 
32
24
  attr_reader :ast_node, :target, :variables, :context
33
25
 
@@ -0,0 +1,31 @@
1
+ require 'active_support/core_ext/class/attribute'
2
+
3
+ module GQL
4
+ class Lazy < Field
5
+ class_attribute :owner, :type, :options, instance_accessor: false, instance_predicate: false
6
+
7
+ class << self
8
+ def build_class(id, proc, options)
9
+ Class.new(self).tap do |field_class|
10
+ field_class.owner = options.delete(:owner)
11
+ field_class.type = options.delete(:type)
12
+ field_class.id = id
13
+ field_class.proc = proc
14
+ field_class.options = options
15
+ end
16
+ end
17
+
18
+ def resolve
19
+ owner.remove_field id
20
+ owner.add_field id, proc, options.merge(type: Registry.fetch(type))
21
+ end
22
+ end
23
+
24
+ def value
25
+ field_class = self.class.resolve
26
+
27
+ field = field_class.new(ast_node, target, variables, context)
28
+ field.value
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ require 'active_support/concern'
2
+ require 'active_support/core_ext/string/inflections'
3
+
4
+ module GQL
5
+ module Mixins
6
+ module Common
7
+ def propagate(type, id, klass)
8
+ const_name = send("const_name_for_#{type}", id)
9
+ accessor = type.to_s.pluralize
10
+
11
+ const_set const_name, klass
12
+
13
+ [self, *descendants].each do |c|
14
+ c.send "#{accessor}=", c.send(accessor).merge(id => klass)
15
+ end
16
+ end
17
+
18
+ def shutdown(type, id)
19
+ const_name = send("const_name_for_#{type}", id)
20
+ accessor = type.to_s.pluralize
21
+
22
+ [self, *descendants].each do |c|
23
+ next unless c.send("has_#{type}?", id)
24
+
25
+ c.send :remove_const, const_name if c.const_defined?(const_name, false)
26
+ c.send(accessor).delete id
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,120 @@
1
+ require 'active_support/concern'
2
+ require 'active_support/core_ext/array/extract_options'
3
+ require 'active_support/core_ext/class/attribute'
4
+ require 'active_support/core_ext/class/subclasses'
5
+ require 'active_support/core_ext/object/try'
6
+ require 'active_support/core_ext/string/inflections'
7
+
8
+ module GQL
9
+ module Mixins
10
+ module HasCalls
11
+ extend ActiveSupport::Concern
12
+
13
+ included do
14
+ class_attribute :calls, :call_proc, instance_accessor: false, instance_predicate: false
15
+ self.calls = {}
16
+ end
17
+
18
+ module ClassMethods
19
+ def add_call(id, *args, &block)
20
+ remove_call id
21
+
22
+ id = id.to_sym
23
+ options = args.extract_options!
24
+ call_spec = args.shift || block || proc_for_call(id)
25
+ result_spec = options[:returns] || call_spec.try(:result_class)
26
+ result_class = result_class_from_spec(result_spec)
27
+
28
+ build_call_class(call_spec, id, result_class).tap do |call_class|
29
+ propagate :call, id, call_class
30
+ end
31
+ end
32
+
33
+ alias :call :add_call
34
+
35
+ def remove_call(id)
36
+ shutdown :call, id.to_sym
37
+ end
38
+
39
+ def has_call?(id)
40
+ calls.has_key? id.to_sym
41
+ end
42
+
43
+ private
44
+ def build_call_class(spec, id, result_class)
45
+ call_class_from_spec(spec).tap do |call_class|
46
+ call_class.id = id
47
+ call_class.result_class = result_class
48
+
49
+ if result_class && result_class.name.nil?
50
+ call_class.const_set :Result, result_class
51
+ end
52
+ end
53
+ end
54
+
55
+ def call_class_from_spec(spec)
56
+ return Class.new(spec) unless spec.is_a?(Proc)
57
+
58
+ Class.new(Call).tap do |call_class|
59
+ call_class.class_eval do
60
+ self.proc = spec
61
+
62
+ def execute(*args)
63
+ instance_exec(*args, &self.class.proc)
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ def const_name_for_call(id)
70
+ :"#{id.to_s.camelize}Call"
71
+ end
72
+
73
+ def proc_for_call(id)
74
+ instance_exec id, &(call_proc || GQL.default_call_proc)
75
+ end
76
+
77
+ def result_class_from_spec(spec)
78
+ result_class =
79
+ case spec
80
+ when ::Array
81
+ result_class_from_connection_spec spec.dup
82
+ when ::Hash
83
+ result_class_from_mapping_spec spec.dup
84
+ else
85
+ spec
86
+ end
87
+
88
+ result_class && Registry.fetch(result_class)
89
+ end
90
+
91
+ def result_class_from_connection_spec(spec)
92
+ if spec.size == 1
93
+ spec.unshift GQL.default_list_class
94
+ end
95
+
96
+ options = {
97
+ list_class: spec.first,
98
+ item_class: spec.last
99
+ }
100
+
101
+ Connection.build_class :result, nil, options
102
+ end
103
+
104
+ def result_class_from_mapping_spec(spec)
105
+ Object.build_class :result, nil, class: spec
106
+ end
107
+ end
108
+
109
+ private
110
+ def value_of_call(ast_call)
111
+ call_class = call_class_for_id(ast_call.id)
112
+ call_class.execute(self.class, ast_call, target, variables, context)
113
+ end
114
+
115
+ def call_class_for_id(id)
116
+ self.class.calls[id] or raise Errors::CallNotFound.new(id, self.class)
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,138 @@
1
+ require 'active_support/concern'
2
+ require 'active_support/core_ext/array/extract_options'
3
+ require 'active_support/core_ext/class/attribute'
4
+ require 'active_support/core_ext/class/subclasses'
5
+ require 'active_support/core_ext/string/inflections'
6
+
7
+ module GQL
8
+ module Mixins
9
+ module HasFields
10
+ extend ActiveSupport::Concern
11
+
12
+ included do
13
+ class_attribute :fields, :field_proc, instance_accessor: false, instance_predicate: false
14
+ self.fields = {}
15
+ end
16
+
17
+ module ClassMethods
18
+ def add_field(id, *args, &block)
19
+ remove_field id
20
+
21
+ id = id.to_sym
22
+ options = args.extract_options!
23
+ type = options.delete(:type) || Field
24
+ proc = args.shift || block || proc_for_field(id)
25
+
26
+ build_field_class(type, id, proc, options).tap do |field_class|
27
+ propagate :field, id, field_class
28
+ end
29
+ end
30
+
31
+ alias :field :add_field
32
+
33
+ def remove_field(id)
34
+ shutdown :field, id.to_sym
35
+ end
36
+
37
+ def has_field?(id)
38
+ fields.has_key? id.to_sym
39
+ end
40
+
41
+ def cursor(id_or_proc)
42
+ id = id_or_proc.is_a?(Proc) ? nil : id_or_proc
43
+ proc = id ? -> { target.public_send(id) } : id_or_proc
44
+
45
+ add_field :cursor, proc, type: Scalar
46
+ end
47
+
48
+ def respond_to?(method, *args)
49
+ super || GQL.field_types.has_key?(method)
50
+ end
51
+
52
+ def method_missing(method, *args, &block)
53
+ if type = GQL.field_types[method]
54
+ define_field_method method, type
55
+ send method, *args, &block
56
+ else
57
+ super
58
+ end
59
+ rescue NoMethodError => exc
60
+ raise Errors::NoMethodError.new(self, method, exc)
61
+ end
62
+
63
+ private
64
+ def build_field_class(type, id, proc, options)
65
+ if type.is_a? ::String
66
+ Lazy.build_class id, proc, options.merge(owner: self, type: type)
67
+ else
68
+ Registry.fetch(type).build_class id, proc, options
69
+ end
70
+ end
71
+
72
+ def const_name_for_field(id)
73
+ prefix = id == :__type__ ? 'Schema_Type' : id.to_s.camelize
74
+ :"#{prefix}Field"
75
+ end
76
+
77
+ def proc_for_field(id)
78
+ instance_exec id, &(field_proc || GQL.default_field_proc)
79
+ end
80
+
81
+ def define_field_method(name, type)
82
+ Field.define_singleton_method name do |*args, &block|
83
+ options = args.extract_options!.merge(type: type)
84
+ args = args.push(options)
85
+
86
+ add_field(*args, &block)
87
+ end
88
+ end
89
+ end
90
+
91
+ private
92
+ def value_of_fields(ast_fields)
93
+ ast_fields.reduce({}) do |result, ast_field|
94
+ key = ast_field.alias_id || ast_field.id
95
+
96
+ result.merge key => value_of_field(ast_field)
97
+ end
98
+ end
99
+
100
+ def value_of_field(ast_field)
101
+ if ast_field.id == :node
102
+ field = self.class.new(ast_field, target, variables, context)
103
+ field.value
104
+ else
105
+ field_class = field_class_for_id(ast_field.id)
106
+ next_target = target_for_field(target, field_class.proc)
107
+
108
+ field = field_class.new(ast_field, next_target, variables, context)
109
+ field.value
110
+ end
111
+ end
112
+
113
+ def field_class_for_id(id)
114
+ self.class.fields[id] or raise Errors::FieldNotFound.new(id, self.class)
115
+ end
116
+
117
+ def target_for_field(current_target, proc)
118
+ args = [current_target, context]
119
+ args.push self.class if GQL.debug
120
+
121
+ method = self.class.const_get(:ExecutionContext).new(*args)
122
+ method.execute proc
123
+ end
124
+
125
+ class ExecutionContextNoDebug < Struct.new(:target, :context)
126
+ def execute(method, args = [])
127
+ instance_exec(*args, &method)
128
+ end
129
+ end
130
+
131
+ class ExecutionContextDebug < Struct.new(:target, :context, :field_class)
132
+ def execute(method, args = [])
133
+ instance_exec(*args, &method)
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
@@ -2,14 +2,26 @@ require 'active_support/core_ext/class/attribute'
2
2
 
3
3
  module GQL
4
4
  class Object < Field
5
+ class_attribute :object_class, instance_accessor: false, instance_predicate: false
6
+
5
7
  class << self
6
8
  def build_class(id, proc, options = {})
7
- field_class = options.delete(:field_class)
8
-
9
- Field.validate_is_subclass! field_class, 'field_class'
9
+ object_class = options.delete(:class) || options.delete(:as)
10
+ object_class = ::Hash.new(object_class) unless object_class.is_a?(::Hash)
10
11
 
11
- field_class.build_class id, proc, options
12
+ Class.new(self).tap do |klass|
13
+ klass.id = id
14
+ klass.proc = proc
15
+ klass.object_class = object_class
16
+ end
12
17
  end
13
18
  end
19
+
20
+ def value
21
+ field_class = Registry.fetch(self.class.object_class[target.class])
22
+
23
+ field = field_class.new(ast_node, target, variables, context)
24
+ field.value
25
+ end
14
26
  end
15
27
  end
@@ -0,0 +1,39 @@
1
+ require 'active_support/core_ext/string/inflections'
2
+ require 'active_support/per_thread_registry'
3
+
4
+ module GQL
5
+ class Registry
6
+ extend ActiveSupport::PerThreadRegistry
7
+
8
+ attr_reader :cache
9
+
10
+ def initialize
11
+ reset
12
+ end
13
+
14
+ def reset
15
+ @cache = {}
16
+ end
17
+
18
+ def fetch(key, baseclass = Field)
19
+ cache[key] || begin
20
+ raise Errors::FieldClassNotSet.new(baseclass, 'TODO') if key.nil?
21
+
22
+ const, name =
23
+ if key.instance_of? ::Class
24
+ [key, key.name]
25
+ else
26
+ [key.constantize, key]
27
+ end
28
+
29
+ raise Errors::InvalidFieldClass.new(const, baseclass) unless const <= baseclass
30
+
31
+ cache.update name => const, const => const
32
+
33
+ cache[key]
34
+ end
35
+ end
36
+
37
+ alias_method :[], :fetch
38
+ end
39
+ end
@@ -5,8 +5,8 @@ module GQL
5
5
 
6
6
  string :id
7
7
  string :name
8
- object :result_class, -> { target.result_class || CallerClass }, field_class: Field
9
- array :parameters, -> { (target.proc || target.instance_method(:execute)).parameters }, item_field_class: Parameter
8
+ object :result_class, -> { target.result_class || CallerClass }, class: Field
9
+ array :parameters, -> { (target.proc || target.instance_method(:execute)).parameters }, item_class: Parameter
10
10
 
11
11
  def scalar_value
12
12
  target.name
@@ -5,8 +5,8 @@ module GQL
5
5
 
6
6
  string :id
7
7
  string :name
8
- connection :calls, -> { target.calls.values }, list_field_class: List, item_field_class: Call
9
- connection :fields, -> { target.fields.values }, list_field_class: List, item_field_class: Field
8
+ connection :calls, -> { target.calls.values }, list_class: List, item_class: Call
9
+ connection :fields, -> { target.fields.values }, list_class: List, item_class: Field
10
10
 
11
11
  def scalar_value
12
12
  target.name
@@ -1,3 +1,3 @@
1
1
  module GQL
2
- VERSION = '0.0.19'
2
+ VERSION = '0.0.20'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.19
4
+ version: 0.0.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Andert
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-12 00:00:00.000000000 Z
11
+ date: 2015-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0.4'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest-perf
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.1'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.1'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: activesupport
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -112,11 +126,14 @@ files:
112
126
  - lib/gql/errors.rb
113
127
  - lib/gql/executor.rb
114
128
  - lib/gql/field.rb
115
- - lib/gql/has_calls.rb
116
- - lib/gql/has_fields.rb
129
+ - lib/gql/lazy.rb
130
+ - lib/gql/mixins/common.rb
131
+ - lib/gql/mixins/has_calls.rb
132
+ - lib/gql/mixins/has_fields.rb
117
133
  - lib/gql/number.rb
118
134
  - lib/gql/object.rb
119
135
  - lib/gql/parser.rb
136
+ - lib/gql/registry.rb
120
137
  - lib/gql/scalar.rb
121
138
  - lib/gql/schema/call.rb
122
139
  - lib/gql/schema/caller_class.rb
@@ -124,7 +141,6 @@ files:
124
141
  - lib/gql/schema/list.rb
125
142
  - lib/gql/schema/parameter.rb
126
143
  - lib/gql/string.rb
127
- - lib/gql/test_case.rb
128
144
  - lib/gql/tokenizer.rb
129
145
  - lib/gql/version.rb
130
146
  homepage: https://github.com/martinandert/gql
@@ -1,104 +0,0 @@
1
- require 'active_support/concern'
2
- require 'active_support/core_ext/array/extract_options'
3
- require 'active_support/core_ext/class/attribute'
4
- require 'active_support/core_ext/string/inflections'
5
- require 'active_support/core_ext/object/try'
6
-
7
- module GQL
8
- module HasCalls
9
- extend ActiveSupport::Concern
10
-
11
- included do
12
- class_attribute :calls, :call_proc, instance_accessor: false, instance_predicate: false
13
- self.calls = {}
14
- end
15
-
16
- module ClassMethods
17
- def add_call(id, *args, &block)
18
- options = args.extract_options!
19
-
20
- call_spec = args.shift || block || proc_for_call(id)
21
- result_spec = options[:returns] || call_spec.try(:result_class)
22
- result_class = result_class_from_spec(result_spec)
23
-
24
- Field.validate_is_subclass! result_class, 'result_class' if result_class
25
-
26
- call_class = call_class_from_spec(call_spec)
27
- call_class.id = id.to_s
28
- call_class.result_class = result_class
29
-
30
- if result_class && result_class.name.nil?
31
- call_class.const_set :Result, result_class
32
- end
33
-
34
- self.const_set const_name_for_call(id), call_class
35
- self.calls = calls.merge(id.to_sym => call_class)
36
- end
37
-
38
- alias :call :add_call
39
-
40
- def remove_call(id)
41
- const_name = const_name_for_call(id)
42
-
43
- send :remove_const, const_name if const_defined?(const_name)
44
- calls.delete id
45
- end
46
-
47
- def has_call?(id)
48
- calls.has_key? id
49
- end
50
-
51
- private
52
- def const_name_for_call(id)
53
- :"#{id.to_s.camelize}Call"
54
- end
55
-
56
- def proc_for_call(id)
57
- instance_exec id, &(call_proc || GQL.default_call_proc)
58
- end
59
-
60
- def result_class_from_spec(spec)
61
- return spec unless spec.is_a? ::Array
62
-
63
- result_class_from_connection_spec spec.dup
64
- end
65
-
66
- def result_class_from_connection_spec(spec)
67
- if spec.size == 1
68
- spec.unshift GQL.default_list_field_class
69
- end
70
-
71
- options = {
72
- list_field_class: spec.first,
73
- item_field_class: spec.last
74
- }
75
-
76
- Connection.build_class :result, nil, options
77
- end
78
-
79
- def call_class_from_spec(spec)
80
- return Class.new(spec) unless spec.is_a?(Proc)
81
-
82
- Class.new(Call).tap do |call_class|
83
- call_class.class_eval do
84
- self.proc = spec
85
-
86
- def execute(*args)
87
- instance_exec(*args, &self.class.proc)
88
- end
89
- end
90
- end
91
- end
92
- end
93
-
94
- private
95
- def value_of_call(ast_call)
96
- call_class = call_class_for_id(ast_call.id)
97
- call_class.execute(self.class, ast_call, target, variables, context)
98
- end
99
-
100
- def call_class_for_id(id)
101
- self.class.calls[id] or raise Errors::CallNotFound.new(id, self.class)
102
- end
103
- end
104
- end
@@ -1,132 +0,0 @@
1
- require 'active_support/concern'
2
- require 'active_support/core_ext/array/extract_options'
3
- require 'active_support/core_ext/class/attribute'
4
- require 'active_support/core_ext/string/inflections'
5
-
6
- module GQL
7
- module HasFields
8
- extend ActiveSupport::Concern
9
-
10
- included do
11
- class_attribute :fields, :field_proc, instance_accessor: false, instance_predicate: false
12
- self.fields = {}
13
- end
14
-
15
- module ClassMethods
16
- def add_field(id, *args, &block)
17
- options = args.extract_options!
18
- type = options.delete(:type) || Field
19
- proc = args.shift || block || proc_for_field(id)
20
-
21
- Field.validate_is_subclass! type, 'type'
22
-
23
- type.build_class(id, proc, options).tap do |field_class|
24
- const_name = const_name_for_field(id)
25
-
26
- const_set const_name, field_class unless const_defined?(const_name)
27
- self.fields = fields.merge(id.to_sym => field_class)
28
- end
29
- end
30
-
31
- alias :field :add_field
32
-
33
- def remove_field(id)
34
- const_name = const_name_for_field(id)
35
-
36
- send :remove_const, const_name if const_defined?(const_name)
37
- fields.delete id
38
- end
39
-
40
- def has_field?(id)
41
- fields.has_key? id
42
- end
43
-
44
- def cursor(id_or_proc)
45
- id = id_or_proc.is_a?(Proc) ? nil : id_or_proc
46
- proc = id ? -> { target.public_send(id) } : id_or_proc
47
-
48
- add_field :cursor, proc, type: Scalar
49
- end
50
-
51
- def respond_to?(method, *args)
52
- super || GQL.field_types.has_key?(method)
53
- end
54
-
55
- def method_missing(method, *args, &block)
56
- if type = GQL.field_types[method]
57
- define_field_method method, type
58
- send method, *args, &block
59
- else
60
- super
61
- end
62
- rescue NoMethodError => exc
63
- raise Errors::NoMethodError.new(self, method, exc)
64
- end
65
-
66
- private
67
- def const_name_for_field(id)
68
- prefix = id == :__type__ ? 'Schema_Type' : id.to_s.camelize
69
- :"#{prefix}Field"
70
- end
71
-
72
- def proc_for_field(id)
73
- instance_exec id, &(field_proc || GQL.default_field_proc)
74
- end
75
-
76
- def define_field_method(name, type)
77
- Field.define_singleton_method name do |*args, &block|
78
- options = args.extract_options!.merge(type: type)
79
- args = args.push(options)
80
-
81
- add_field(*args, &block)
82
- end
83
- end
84
- end
85
-
86
- private
87
- def value_of_fields(ast_fields)
88
- ast_fields.reduce({}) do |result, ast_field|
89
- key = ast_field.alias_id || ast_field.id
90
-
91
- result.merge key => value_of_field(ast_field)
92
- end
93
- end
94
-
95
- def value_of_field(ast_field)
96
- if ast_field.id == :node
97
- field = self.class.new(ast_field, target, variables, context)
98
- field.value
99
- else
100
- field_class = field_class_for_id(ast_field.id)
101
- next_target = target_for_field(target, field_class.proc)
102
-
103
- field = field_class.new(ast_field, next_target, variables, context)
104
- field.value
105
- end
106
- end
107
-
108
- def field_class_for_id(id)
109
- self.class.fields[id] or raise Errors::FieldNotFound.new(id, self.class)
110
- end
111
-
112
- def target_for_field(current_target, proc)
113
- args = [current_target, context]
114
- args.push self.class if GQL.debug
115
-
116
- method = self.class.const_get(:ExecutionContext).new(*args)
117
- method.execute proc
118
- end
119
-
120
- class ExecutionContextNoDebug < Struct.new(:target, :context)
121
- def execute(method, args = [])
122
- instance_exec(*args, &method)
123
- end
124
- end
125
-
126
- class ExecutionContextDebug < Struct.new(:target, :context, :field_class)
127
- def execute(method, args = [])
128
- instance_exec(*args, &method)
129
- end
130
- end
131
- end
132
- end
@@ -1,4 +0,0 @@
1
- module GQL
2
- class TestCase < ActiveSupport::TestCase
3
- end
4
- end