lib/graphql/remote_loader/loader.rb in graphql-remote_loader-1.0.3 vs lib/graphql/remote_loader/loader.rb in graphql-remote_loader-1.0.4

- old
+ new

@@ -9,18 +9,20 @@ # We include a unique prime as part of the batch key to use as part # of the alias on all fields. This is used to # a) Avoid name collisions in the generated query # b) Determine which fields in the result JSON should be # handed fulfilled to each promise - def self.load(query, context: {}) + def self.load(query, context: {}, variables: {}) @index ||= 1 @index += 1 prime = Prime.take(@index - 1).last store_context(context) + interpolate_variables!(query, variables) + self.for.load([query, prime, @context]) end # Loads the value, then if the query was successful, fulfills promise with # the leaf value instead of the full results hash. @@ -66,11 +68,11 @@ end private def perform(queries_and_primes) - query_string = QueryMerger.merge(queries_and_primes) + query_string = QueryMerger.merge(queries_and_primes).gsub(/\s+/, " ") context = queries_and_primes[-1][-1] response = query(query_string, context: context).to_h data, errors = response["data"], response["errors"] @@ -83,9 +85,36 @@ response["errors"] = dup(errors_key) unless errors_key.empty? scrub_primes_from_error_paths!(response["errors"]) fulfill([query, prime, context], response) + end + end + + # Interpolates variables into the given query. + # For String variables, surrounds the interpolated string in quotes. + # To interpolate a String as an Int, Float, or Bool, convert to the appropriate Ruby type. + # + # E.g. + # interpolate_variables("foo(bar: $my_var)", { my_var: "buzz" }) + # => "foo(bar: \"buzz\")" + def self.interpolate_variables!(query, variables = {}) + variables.each do |variable, value| + case value + when Integer, Float, TrueClass, FalseClass + # These types are safe to directly interpolate into the query, and GraphQL does not expect these types to be quoted. + query.gsub!("$#{variable.to_s}", value.to_s) + else + # A string is either a GraphQL String or ID type. + # This means we need to + # a) Surround the value in quotes + # b) escape special characters in the string + # + # This else also catches unknown objects, which could break the query if we directly interpolate. + # These objects get converted to strings, then escaped. + + query.gsub!("$#{variable.to_s}", value.to_s.inspect) + end end end def dup(hash) JSON.parse(hash.to_json)