graphlient 0.7.0 → 0.9.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.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +38 -38
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -20
  4. data/.github/workflows/ci.yml +33 -29
  5. data/.github/workflows/danger-comment.yml +10 -0
  6. data/.github/workflows/danger.yml +13 -22
  7. data/.github/workflows/rubocop.yml +19 -19
  8. data/.gitignore +59 -52
  9. data/.rspec +1 -1
  10. data/.rubocop.yml +26 -28
  11. data/.rubocop_todo.yml +72 -48
  12. data/CHANGELOG.md +128 -107
  13. data/CONTRIBUTING.md +125 -125
  14. data/Dangerfile +24 -24
  15. data/Gemfile +35 -27
  16. data/LICENSE +21 -21
  17. data/README.md +800 -508
  18. data/RELEASING.md +63 -63
  19. data/Rakefile +15 -15
  20. data/UPGRADING.md +23 -23
  21. data/graphlient.gemspec +19 -19
  22. data/lib/graphlient/adapters/http/adapter.rb +41 -41
  23. data/lib/graphlient/adapters/http/faraday_adapter.rb +79 -45
  24. data/lib/graphlient/adapters/http/http_adapter.rb +40 -39
  25. data/lib/graphlient/adapters/http.rb +3 -3
  26. data/lib/graphlient/adapters.rb +1 -1
  27. data/lib/graphlient/client.rb +98 -73
  28. data/lib/graphlient/errors/client_error.rb +6 -6
  29. data/lib/graphlient/errors/connection_failed_error.rb +6 -6
  30. data/lib/graphlient/errors/error.rb +13 -12
  31. data/lib/graphlient/errors/execution_error.rb +29 -29
  32. data/lib/graphlient/errors/faraday_server_error.rb +12 -12
  33. data/lib/graphlient/errors/graphql_error.rb +53 -52
  34. data/lib/graphlient/errors/http_options_error.rb +6 -6
  35. data/lib/graphlient/errors/http_server_error.rb +13 -13
  36. data/lib/graphlient/errors/server_error.rb +7 -7
  37. data/lib/graphlient/errors/timeout_error.rb +6 -6
  38. data/lib/graphlient/errors.rb +10 -10
  39. data/lib/graphlient/extensions/query.rb +15 -15
  40. data/lib/graphlient/extensions.rb +1 -1
  41. data/lib/graphlient/query/directive.rb +47 -0
  42. data/lib/graphlient/query/serializer/arguments.rb +67 -0
  43. data/lib/graphlient/query/serializer/directives.rb +17 -0
  44. data/lib/graphlient/query/serializer/evaluator.rb +15 -0
  45. data/lib/graphlient/query/serializer/fragments.rb +28 -0
  46. data/lib/graphlient/query/serializer/scalars.rb +63 -0
  47. data/lib/graphlient/query/serializer.rb +153 -0
  48. data/lib/graphlient/query.rb +29 -128
  49. data/lib/graphlient/schema.rb +27 -26
  50. data/lib/graphlient/version.rb +3 -3
  51. data/lib/graphlient.rb +8 -8
  52. data/spec/graphlient/adapters/http/faraday_adapter_spec.rb +172 -112
  53. data/spec/graphlient/adapters/http/http_adapter_spec.rb +60 -60
  54. data/spec/graphlient/client_dsl_spec.rb +153 -0
  55. data/spec/graphlient/client_query_spec.rb +369 -346
  56. data/spec/graphlient/client_schema_spec.rb +75 -55
  57. data/spec/graphlient/extensions/query_spec.rb +16 -16
  58. data/spec/graphlient/github_query_spec.rb +32 -32
  59. data/spec/graphlient/query_dsl_spec.rb +231 -0
  60. data/spec/graphlient/query_spec.rb +105 -105
  61. data/spec/graphlient/schema_spec.rb +56 -56
  62. data/spec/graphlient/static_client_query_spec.rb +75 -68
  63. data/spec/graphlient/webmock_client_query_spec.rb +41 -41
  64. data/spec/spec_helper.rb +26 -14
  65. data/spec/support/context/dummy_client.rb +33 -26
  66. data/spec/support/context/github_client.rb +18 -18
  67. data/spec/support/dummy_app.rb +21 -19
  68. data/spec/support/dummy_schema.rb +17 -17
  69. data/spec/support/fixtures/github/schema.yml +14282 -14282
  70. data/spec/support/fixtures/github/user.yml +76 -76
  71. data/spec/support/fixtures/github/viewer.yml +76 -76
  72. data/spec/support/fixtures/invoice_api.json +1288 -1288
  73. data/spec/support/mutations/create_invoice.rb +18 -18
  74. data/spec/support/queries/query.rb +48 -47
  75. data/spec/support/schema/github.json +44479 -44479
  76. data/spec/support/types/invoice_type.rb +13 -13
  77. data/spec/support/types/mutation_type.rb +5 -5
  78. data/spec/support/vcr.rb +9 -9
  79. metadata +13 -8
  80. data/Gemfile.danger +0 -5
@@ -1,73 +1,98 @@
1
- module Graphlient
2
- class Client
3
- attr_accessor :uri, :options
4
-
5
- def initialize(url, options = {}, &_block)
6
- @url = url
7
- @options = options.dup
8
- yield self if block_given?
9
- end
10
-
11
- def parse(query_str = nil, &block)
12
- query_str ||= Graphlient::Query.new do
13
- instance_eval(&block)
14
- end
15
- client.parse(query_str.to_s)
16
- rescue GraphQL::Client::Error => e
17
- raise Graphlient::Errors::ClientError, e.message
18
- end
19
-
20
- def execute(query, variables = nil)
21
- query_params = {}
22
- query_params[:context] = @options if @options
23
- query_params[:variables] = variables if variables
24
- query = client.parse(query) if query.is_a?(String)
25
- rc = client.query(query, **query_params)
26
- raise Graphlient::Errors::GraphQLError, rc if rc.errors.any?
27
- # see https://github.com/github/graphql-client/pull/132
28
- # see https://github.com/exAspArk/graphql-errors/issues/2
29
- raise Graphlient::Errors::ExecutionError, rc if errors_in_result?(rc)
30
- rc
31
- rescue GraphQL::Client::Error => e
32
- raise Graphlient::Errors::ClientError, e.message
33
- end
34
-
35
- def query(query_or_variables = nil, variables = nil, &block)
36
- if block_given?
37
- execute(parse(&block), query_or_variables)
38
- else
39
- execute(query_or_variables, variables)
40
- end
41
- end
42
-
43
- def http_adapter_class
44
- options[:http] || Adapters::HTTP::FaradayAdapter
45
- end
46
-
47
- def http(&block)
48
- adapter_options = { headers: @options[:headers], http_options: @options[:http_options] }
49
-
50
- @http ||= http_adapter_class.new(@url, adapter_options, &block)
51
- end
52
-
53
- def schema
54
- @schema ||= Graphlient::Schema.new(http, schema_path)
55
- end
56
-
57
- private
58
-
59
- def schema_path
60
- return options[:schema_path].to_s if options[:schema_path]
61
- end
62
-
63
- def client
64
- @client ||= GraphQL::Client.new(schema: schema.graphql_schema, execute: http).tap do |client|
65
- client.allow_dynamic_queries = @options.key?(:allow_dynamic_queries) ? options[:allow_dynamic_queries] : true
66
- end
67
- end
68
-
69
- def errors_in_result?(response)
70
- response.data && response.data.errors && response.data.errors.all.any?
71
- end
72
- end
73
- end
1
+ module Graphlient
2
+ class Client
3
+ attr_accessor :uri, :options
4
+
5
+ class InvalidConfigurationError < StandardError; end
6
+
7
+ def initialize(url, options = {}, &_block)
8
+ @url = url
9
+ @options = options.dup
10
+ raise_error_if_invalid_configuration!
11
+ yield self if block_given?
12
+ end
13
+
14
+ def parse(query_str = nil, &block)
15
+ query_str ||= Graphlient::Query.new do
16
+ instance_eval(&block)
17
+ end
18
+ client.parse(query_str.to_s)
19
+ rescue GraphQL::Client::Error => e
20
+ raise Graphlient::Errors::ClientError, e.message
21
+ end
22
+
23
+ def to_query_string(**_kargs, &block)
24
+ Graphlient::Query.new do
25
+ instance_eval(&block)
26
+ end.to_s
27
+ end
28
+
29
+ def execute(query, variables = nil)
30
+ query_params = {}
31
+ query_params[:context] = @options if @options
32
+ query_params[:variables] = variables if variables
33
+ query = client.parse(query) if query.is_a?(String)
34
+ rc = client.query(query, **query_params)
35
+ raise Graphlient::Errors::GraphQLError, rc if rc.errors.any?
36
+ # see https://github.com/github-community-projects/graphql-client/pull/132
37
+ # see https://github.com/exAspArk/graphql-errors/issues/2
38
+ raise Graphlient::Errors::ExecutionError, rc if errors_in_result?(rc)
39
+
40
+ rc
41
+ rescue GraphQL::Client::Error => e
42
+ raise Graphlient::Errors::ClientError, e.message
43
+ end
44
+
45
+ def query(query_or_variables = nil, variables = nil, &block)
46
+ if block_given?
47
+ execute(parse(&block), query_or_variables)
48
+ else
49
+ execute(query_or_variables, variables)
50
+ end
51
+ end
52
+
53
+ def http_adapter_class
54
+ options[:http] || Adapters::HTTP::FaradayAdapter
55
+ end
56
+
57
+ def http(&block)
58
+ adapter_options = { headers: @options[:headers], http_options: @options[:http_options] }
59
+
60
+ @http ||= http_adapter_class.new(@url, adapter_options, &block)
61
+ end
62
+
63
+ # Register a custom scalar type for use in variable declarations.
64
+ # Call inside the client initialiser block:
65
+ # client = Graphlient::Client.new(url) do |c|
66
+ # c.scalar :date, 'Date'
67
+ # c.scalar :uuid, 'UUID'
68
+ # c.scalar :decimal, 'Decimal'
69
+ # end
70
+ def scalar(sym, graphql_type)
71
+ Query.scalar(sym, graphql_type)
72
+ end
73
+
74
+ def schema
75
+ @schema ||= options[:schema] || Graphlient::Schema.new(http, schema_path)
76
+ end
77
+
78
+ private
79
+
80
+ def raise_error_if_invalid_configuration!
81
+ raise InvalidConfigurationError, 'schema_path and schema cannot both be provided' if options.key?(:schema_path) && options.key?(:schema)
82
+ end
83
+
84
+ def schema_path
85
+ options[:schema_path].to_s if options[:schema_path]
86
+ end
87
+
88
+ def client
89
+ @client ||= GraphQL::Client.new(schema: schema.graphql_schema, execute: http).tap do |client|
90
+ client.allow_dynamic_queries = @options.key?(:allow_dynamic_queries) ? options[:allow_dynamic_queries] : true
91
+ end
92
+ end
93
+
94
+ def errors_in_result?(response)
95
+ response.data && response.data.errors && response.data.errors.all.any?
96
+ end
97
+ end
98
+ end
@@ -1,6 +1,6 @@
1
- module Graphlient
2
- module Errors
3
- class ClientError < Error
4
- end
5
- end
6
- end
1
+ module Graphlient
2
+ module Errors
3
+ class ClientError < Error
4
+ end
5
+ end
6
+ end
@@ -1,6 +1,6 @@
1
- module Graphlient
2
- module Errors
3
- class ConnectionFailedError < ServerError
4
- end
5
- end
6
- end
1
+ module Graphlient
2
+ module Errors
3
+ class ConnectionFailedError < ServerError
4
+ end
5
+ end
6
+ end
@@ -1,12 +1,13 @@
1
- module Graphlient
2
- module Errors
3
- class Error < StandardError
4
- attr_reader :inner_exception
5
- def initialize(message, inner_exception = nil)
6
- super(message)
7
-
8
- @inner_exception = inner_exception
9
- end
10
- end
11
- end
12
- end
1
+ module Graphlient
2
+ module Errors
3
+ class Error < StandardError
4
+ attr_reader :inner_exception
5
+
6
+ def initialize(message, inner_exception = nil)
7
+ super(message)
8
+
9
+ @inner_exception = inner_exception
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,29 +1,29 @@
1
- module Graphlient
2
- module Errors
3
- class ExecutionError < Error
4
- attr_reader :response
5
-
6
- def initialize(response)
7
- super('the server responded with a GraphQL execution error')
8
- @response = response
9
- end
10
-
11
- def errors
12
- response.data.errors
13
- end
14
-
15
- def to_s
16
- errors.details.map do |key, details|
17
- details = create_details(details).join("\n")
18
- [key, details].compact.join(': ')
19
- end.join("\n")
20
- end
21
-
22
- private
23
-
24
- def create_details(details)
25
- details.map { |detail| detail['message'] }
26
- end
27
- end
28
- end
29
- end
1
+ module Graphlient
2
+ module Errors
3
+ class ExecutionError < Error
4
+ attr_reader :response
5
+
6
+ def initialize(response)
7
+ super('the server responded with a GraphQL execution error')
8
+ @response = response
9
+ end
10
+
11
+ def errors
12
+ response.data.errors
13
+ end
14
+
15
+ def to_s
16
+ errors.details.map do |key, details|
17
+ details = create_details(details).join("\n")
18
+ [key, details].compact.join(': ')
19
+ end.join("\n")
20
+ end
21
+
22
+ private
23
+
24
+ def create_details(details)
25
+ details.map { |detail| detail['message'] }
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,12 +1,12 @@
1
- module Graphlient
2
- module Errors
3
- class FaradayServerError < ServerError
4
- def initialize(inner_exception)
5
- super(inner_exception.message, inner_exception)
6
- @inner_exception = inner_exception
7
- @response = inner_exception.response[:body]
8
- @status_code = inner_exception.response[:status]
9
- end
10
- end
11
- end
12
- end
1
+ module Graphlient
2
+ module Errors
3
+ class FaradayServerError < ServerError
4
+ def initialize(inner_exception)
5
+ super(inner_exception.message, inner_exception)
6
+ @inner_exception = inner_exception
7
+ @response = inner_exception.response[:body]
8
+ @status_code = inner_exception.response[:status]
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,52 +1,53 @@
1
- module Graphlient
2
- module Errors
3
- class GraphQLError < Error
4
- attr_reader :response
5
- def initialize(response)
6
- super('the server responded with a GraphQL error')
7
- @response = response
8
- end
9
-
10
- def errors
11
- @response.errors
12
- end
13
-
14
- def to_s
15
- errors.details.map do |key, details|
16
- details = create_details(details).join("\n")
17
- [key == 'data' ? nil : key, details].compact.join(': ')
18
- end.join("\n")
19
- end
20
-
21
- private
22
-
23
- def create_details(details)
24
- details.map { |detail| create_detail(detail) }
25
- end
26
-
27
- ##
28
- # Generates human readable error explanation from a GraphQL error message
29
- # It first tries `problem` attribute of the error response
30
- # then checks for error root level `path` and tries to generate error from that
31
- # and if none exist, it fallbacks to just return error message
32
- def create_detail(detail)
33
- if detail.key?('problems')
34
- [detail['message'], create_problems(detail['problems']).compact.join("\n ")].join("\n ")
35
- elsif detail.key?('path')
36
- [detail['path'].compact.join(' '), detail['message']].join(': ')
37
- else
38
- detail['message']
39
- end
40
- end
41
-
42
- def create_problems(problems)
43
- problems.map { |problem| create_problem(problem) }
44
- end
45
-
46
- def create_problem(problem)
47
- paths = problem.key?('path') && !problem['path'].empty? ? "#{problem['path'].join(', ')}: " : ''
48
- [paths, problem['explanation']].compact.join
49
- end
50
- end
51
- end
52
- end
1
+ module Graphlient
2
+ module Errors
3
+ class GraphQLError < Error
4
+ attr_reader :response
5
+
6
+ def initialize(response)
7
+ super('the server responded with a GraphQL error')
8
+ @response = response
9
+ end
10
+
11
+ def errors
12
+ @response.errors
13
+ end
14
+
15
+ def to_s
16
+ errors.details.map do |key, details|
17
+ details = create_details(details).join("\n")
18
+ [key == 'data' ? nil : key, details].compact.join(': ')
19
+ end.join("\n")
20
+ end
21
+
22
+ private
23
+
24
+ def create_details(details)
25
+ details.map { |detail| create_detail(detail) }
26
+ end
27
+
28
+ ##
29
+ # Generates human readable error explanation from a GraphQL error message
30
+ # It first tries `problem` attribute of the error response
31
+ # then checks for error root level `path` and tries to generate error from that
32
+ # and if none exist, it fallbacks to just return error message
33
+ def create_detail(detail)
34
+ if detail.key?('problems')
35
+ [detail['message'], create_problems(detail['problems']).compact.join("\n ")].join("\n ")
36
+ elsif detail.key?('path')
37
+ [detail['path'].compact.join(' '), detail['message']].join(': ')
38
+ else
39
+ detail['message']
40
+ end
41
+ end
42
+
43
+ def create_problems(problems)
44
+ problems.map { |problem| create_problem(problem) }
45
+ end
46
+
47
+ def create_problem(problem)
48
+ paths = problem.key?('path') && !problem['path'].empty? ? "#{problem['path'].join(', ')}: " : ''
49
+ [paths, problem['explanation']].compact.join
50
+ end
51
+ end
52
+ end
53
+ end
@@ -1,6 +1,6 @@
1
- module Graphlient
2
- module Errors
3
- class HttpOptionsError < Error
4
- end
5
- end
6
- end
1
+ module Graphlient
2
+ module Errors
3
+ class HttpOptionsError < Error
4
+ end
5
+ end
6
+ end
@@ -1,13 +1,13 @@
1
- module Graphlient
2
- module Errors
3
- class HttpServerError < Error
4
- attr_reader :status_code, :response
5
-
6
- def initialize(message, response)
7
- super(message, response)
8
- @status_code = response.code
9
- @response = response.body
10
- end
11
- end
12
- end
13
- end
1
+ module Graphlient
2
+ module Errors
3
+ class HttpServerError < Error
4
+ attr_reader :status_code, :response
5
+
6
+ def initialize(message, response)
7
+ super(message, response)
8
+ @status_code = response.code
9
+ @response = response.body
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,7 +1,7 @@
1
- module Graphlient
2
- module Errors
3
- class ServerError < Error
4
- attr_reader :status_code, :response
5
- end
6
- end
7
- end
1
+ module Graphlient
2
+ module Errors
3
+ class ServerError < Error
4
+ attr_reader :status_code, :response
5
+ end
6
+ end
7
+ end
@@ -1,6 +1,6 @@
1
- module Graphlient
2
- module Errors
3
- class TimeoutError < Error
4
- end
5
- end
6
- end
1
+ module Graphlient
2
+ module Errors
3
+ class TimeoutError < Error
4
+ end
5
+ end
6
+ end
@@ -1,10 +1,10 @@
1
- require_relative 'errors/error'
2
- require_relative 'errors/client_error'
3
- require_relative 'errors/server_error'
4
- require_relative 'errors/graphql_error'
5
- require_relative 'errors/execution_error'
6
- require_relative 'errors/faraday_server_error'
7
- require_relative 'errors/http_options_error'
8
- require_relative 'errors/http_server_error'
9
- require_relative 'errors/connection_failed_error'
10
- require_relative 'errors/timeout_error'
1
+ require_relative 'errors/error'
2
+ require_relative 'errors/client_error'
3
+ require_relative 'errors/server_error'
4
+ require_relative 'errors/graphql_error'
5
+ require_relative 'errors/execution_error'
6
+ require_relative 'errors/faraday_server_error'
7
+ require_relative 'errors/http_options_error'
8
+ require_relative 'errors/http_server_error'
9
+ require_relative 'errors/connection_failed_error'
10
+ require_relative 'errors/timeout_error'
@@ -1,15 +1,15 @@
1
- module Graphlient
2
- module Extensions
3
- module Query
4
- def method_missing(method_name, *args, &block)
5
- Graphlient::Query.new do
6
- send(method_name, *args, &block)
7
- end
8
- end
9
-
10
- def respond_to_missing?(method_name, include_private = false)
11
- super
12
- end
13
- end
14
- end
15
- end
1
+ module Graphlient
2
+ module Extensions
3
+ module Query
4
+ def method_missing(method_name, *args, &block)
5
+ Graphlient::Query.new do
6
+ send(method_name, *args, &block)
7
+ end
8
+ end
9
+
10
+ def respond_to_missing?(method_name, include_private = false)
11
+ super
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1 +1 @@
1
- require_relative 'extensions/query'
1
+ require_relative 'extensions/query'
@@ -0,0 +1,47 @@
1
+ module Graphlient
2
+ class Query
3
+ # Value object returned by `_directive_name(args)` in the DSL.
4
+ #
5
+ # Rather than writing directly to the query string (which would produce
6
+ # the wrong position -- before the field name), _skip / _include etc.
7
+ # return a Directive instance. append_node / spread / on detect Directive
8
+ # objects in their argument list and place them AFTER the field name,
9
+ # producing correct GraphQL output:
10
+ #
11
+ # feeInCents _skip(if: :skip_fee)
12
+ # -> feeInCents @skip(if: $skip_fee)
13
+ #
14
+ # spread :InvoiceFields, _skip(if: :x)
15
+ # -> ...InvoiceFields @skip(if: $x)
16
+ #
17
+ # spread(_skip(if: :x), on: :DraftInvoice) { draft_id }
18
+ # -> ... on DraftInvoice @skip(if: $x) { draftId }
19
+ class Directive
20
+ attr_reader :name, :args
21
+
22
+ def initialize(name, args = {})
23
+ @name = name.to_s.delete_prefix('_').freeze
24
+ @args = args
25
+ end
26
+
27
+ def to_s
28
+ return "@#{name}" if args.empty?
29
+
30
+ formatted = args.map { |k, v| "#{k}: #{format_value(v)}" }.join(', ')
31
+ "@#{name}(#{formatted})"
32
+ end
33
+
34
+ private
35
+
36
+ # Symbols become variable references ($name); everything else is literal.
37
+ def format_value(value)
38
+ case value
39
+ when Symbol then "$#{value}"
40
+ when String then "\"#{value}\""
41
+ when Numeric, TrueClass, FalseClass then value.to_s
42
+ else value.to_s
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,67 @@
1
+ module Graphlient
2
+ class Query
3
+ class Serializer
4
+ module Arguments
5
+ private
6
+
7
+ def variable_processor
8
+ @variable_processor ||= ->(k, v) { "$#{k}: #{variable_string(v)}" }
9
+ end
10
+
11
+ # Translate a DSL variable type symbol to its GraphQL type string.
12
+ # :id/:id! -> ID/ID! :int -> Int :date -> Date (if registered) [:int] -> [Int]
13
+ def variable_string(val)
14
+ case val
15
+ when :id, :id!
16
+ val.to_s.upcase
17
+ when ->(v) { scalar?(v) }
18
+ scalar_type(val)
19
+ when Array
20
+ "[#{variable_string(val.first)}]"
21
+ else
22
+ val.to_s
23
+ end
24
+ end
25
+
26
+ # Separate Directive objects from regular field arguments.
27
+ def field_args(args)
28
+ args.reject { |a| a.is_a?(Directive) }
29
+ end
30
+
31
+ def directive_args(args)
32
+ args.select { |a| a.is_a?(Directive) }
33
+ end
34
+
35
+ def hash_arg(args)
36
+ args.detect { |arg| arg.is_a?(Hash) }
37
+ end
38
+
39
+ def args_str(hash_args, arg_processor: nil)
40
+ hash_args.map do |k, v|
41
+ arg_processor ? arg_processor.call(k, v) : argument_string(k, v)
42
+ end.join(', ')
43
+ end
44
+
45
+ def argument_string(key, val)
46
+ "#{key}: #{argument_value_string(val)}"
47
+ end
48
+
49
+ def argument_value_string(value)
50
+ case value
51
+ when String then "\"#{value}\""
52
+ when Numeric then value.to_s
53
+ when Array then "[#{value.map { |v| argument_value_string(v) }.join(', ')}]"
54
+ when Hash then "{ #{value.map { |k, v| "#{k}: #{argument_value_string(v)}" }.join(', ')} }"
55
+ when Symbol then symbol_argument_value(value)
56
+ else
57
+ value
58
+ end
59
+ end
60
+
61
+ def symbol_argument_value(value)
62
+ @variables.respond_to?(:key?) && @variables.key?(value) ? "$#{value}" : value.to_s.camelize(:lower)
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end