Skip to content

Add DSL-only mode: to_query_string + spread#115

Merged
dblock merged 14 commits into
ashkan18:masterfrom
rellampec:feature/dsl-mode-only-option
Jun 11, 2026
Merged

Add DSL-only mode: to_query_string + spread#115
dblock merged 14 commits into
ashkan18:masterfrom
rellampec:feature/dsl-mode-only-option

Conversation

@rellampec

@rellampec rellampec commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Add DSL-only mode: to_query_string + spread

Addresses enhancement proposal: Decouple DSL from GraphQL::Client logic

What

Two new methods for building GraphQL query strings from the DSL without triggering
schema loading, HTTP, or graphql-client validation.

Client#to_query_string(&block) — serializes a DSL block to a String and
returns it. The string can be fed back to client.execute for fragment-free queries,
or sent with your own HTTP client to replace graphql-client entirely.

Query#spread(fragment_name) — emits ...FragmentName in the query string.
Cleaner alternative to the ___Const triple-underscore convention.

Why

Framework layers that need to inspect, log, or augment the query string before
sending (e.g. appending fragment definitions, custom connection pooling) need the
serialized string before graphql-client's validation runs. This also opens a fully
external HTTP path.

Changes

  • lib/graphlient/client.rbto_query_string
  • lib/graphlient/query.rbspread
  • spec/graphlient/client_dsl_spec.rb — new spec file (7 examples)
  • README.mdBuild Query Strings without Validation + Fragment Spreads sections

CI fixes included

  • WebMock stub_request.to_rack replaces Faraday::Adapter::Rack for cross-Ruby-version reliability
  • Regex match on TCP error message (Windows vs Linux format difference)
  • Ruby 3.4 added to CI matrix; mutex_m added to Gemfile (removed from stdlib in 3.4)
  • .gitignore updated for .vscode/, .idea/

Checklist

  • 73 examples, 0 failures
  • Rubocop clean
  • CI: Ruby 2.7 – 3.4 green
  • No breaking changes

rellampec added 11 commits June 5, 2026 09:32
- Client#to_query_string(**kargs, &block): builds full query document from
  DSL block and returns a String without touching Faraday or HTTP.
- Query#spread(fragment_name): emits ...FragmentName in the query string,
  replacing the deprecated ___Const graphql-client convention.
- spec_helper.rb: rescue LoadError on byebug require (Windows Ruby 3.2).
- CLAUDE.md: AI agent instructions for this fork.
static_client_query_spec: add schema_path: 'spec/support/fixtures/invoice_api.json'
  The client was fetching the schema from the live URL at module load time
  (before WebMock is active), causing 403 in CI. Using a local schema file
  avoids the network call and matches the pattern in webmock_client_query_spec.

client_dsl_spec: nodes { } → nodes do end (Style/BlockDelimiters)

query.rb: add rubocop:disable Metrics/ClassLength
  Class grew past 100 lines after DSL additions (spread, fragment resolution).

spec_helper.rb: add rubocop:disable Lint/HandleExceptions on rescue LoadError
  The empty rescue is intentional — byebug unavailable on some platforms.

Note: faraday_adapter_spec.rb:147 fails locally on Windows (TCP error message
format differs from Linux) but passes in CI on ubuntu-latest. Pre-existing.
On Linux, Errno::ECONNREFUSED.new(msg).message prepends 'Connection refused - '.
On Windows, the OS prepends a different string. Use a regex that matches the
core error_message content rather than the exact platform-specific prefix.
AI agent instructions are local-only and not relevant to the upstream repo.
CLAUDE.md is removed from git tracking but kept in the working directory.
Added to .gitignore so future sessions don't accidentally commit it.
Root cause: on Ruby 3.1, WebMock's Faraday middleware intercepts requests
before they reach Faraday::Adapter::Rack, returning 403 for any URL without
a stub. This caused 25 CI failures on that Ruby version.

spec/support/context/dummy_client.rb:
  Replace Faraday::Adapter::Rack with stub_request.to_rack(app).
  WebMock routes both schema introspection and query execution through
  the Sinatra dummy app at the WebMock level (before Faraday dispatch).
  Removed schema_path: so graphql-client gets the full live schema
  (including test fields: executionErrorInvoice, partialSuccess etc.).

spec/graphlient/static_client_query_spec.rb:
  Same to_rack approach for execution tests (schema_path kept here since
  the module constants are created at file-load time, before any before block).
  Removed Faraday::Adapter::Rack from the static client constructor.

spec/graphlient/client_schema_spec.rb:
  Use include instead of eq for error message — Faraday 2.x appends
  the URL to the message; include matches on both old and new formats.

73 examples, 0 failures
spec/support/context/dummy_client.rb:
spec/graphlient/static_client_query_spec.rb:
  Replace em-dashes (--) with ASCII semicolons/colons in comments.
  Style/AsciiComments cop requires pure ASCII.

Gemfile:
  Add mutex_m gem -- activesupport 5.x requires mutex_m which was removed
  from Ruby's standard library in Ruby 3.4. Adding it explicitly silences
  the warning and fixes the LoadError on Ruby 3.4.

.github/workflows/ci.yml:
  Add Ruby 3.4 to the required CI matrix (was previously only in ruby-head
  which is allowed to fail). Ruby 3.4 is now released and should be tested.
New sections:
  'Build Query Strings without Validation' -- explains the serialization-only
    path (no schema load, no graphql-client validation, no HTTP), shows the
    basic usage, clarifies when the string can be fed back to client.execute
    (fragment-free queries only), explains why fragment spreads cannot go back
    through the gem (graphql-client's constant-based fragment model), and
    shows how to_query_string is the escape hatch for replacing graphql-client
    with your own HTTP transport entirely.

  'Fragment Spreads' -- documents Query#spread as the modern alternative to
    the triple-underscore convention; covers basic usage and multiple spreads.
@rellampec

Copy link
Copy Markdown
Contributor Author

The Danger job is failing due to an expired token in the workflow — unrelated to this PR's changes.

rellampec added a commit to rellampec/graphlient that referenced this pull request Jun 10, 2026
rellampec added a commit to rellampec/graphlient that referenced this pull request Jun 10, 2026
- All entries single-line matching file convention (no continuation lines)
- ashkan18#115 entries restored to their original order and not modified
- ashkan18#116 prefix added to all directives/fragments/scalars/CI entries
@dblock

dblock commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

I fixed CI / Danger in #117, rebase?

@dblock dblock left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some cosmetics for now, still have to read the details in the PR, also @ashkan18 and @yuki24 take a look?

Comment thread lib/graphlient/query.rb Outdated
@@ -1,5 +1,5 @@
module Graphlient
class Query
class Query # rubocop:disable Metrics/ClassLength

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

run rubocop -a ; rubocop --auto-gen-config.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dblock there's a refactor on next MR that resolves this rubocop violation: #116

Wanted to keep the current MR clear and clean of refactoring, as it resolves the major blocker.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ran the command

Comment thread CHANGELOG.md Outdated
* Your contribution here.
* [#113](https://github.com/ashkan18/graphlient/pull/113): Fix CI builds - [@yuki24](https://github.com/yuki24).
* [#112](https://github.com/ashkan18/graphlient/pull/112): Update graphql-client github repository links in README - [@th1988](https://github.com/th1988).
* [#115](https://github.com/ashkan18/graphlient/pull/115): `Client#to_query_string(**kargs, &block)`: builds the full GraphQL query document from the

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make it a 1-liner. Add to README if you need something longer.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, will work on this asap

…cop to ~> 1.0

Removed two inline disable comments (Metrics/ClassLength on Query, Lint/HandleExceptions in
spec_helper) in favour of the rubocop_todo.yml approach suggested by upstream maintainer.
Bumped rubocop dev dependency from pinned 0.56.0 to ~> 1.0 (required for Ruby 3.2 compatibility
— Psych.safe_load signature changed). TargetRubyVersion kept at 2.3 to reflect the gem's
minimum supported Ruby. Ran rubocop -a (11 auto-corrections) then --auto-gen-config to
regenerate .rubocop_todo.yml with current cop names (Metrics/LineLength renamed to
Layout/LineLength, Style/MethodMissingSuper removed, etc.).
@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown

Danger Report

No issues found.

View run

@rellampec rellampec requested a review from dblock June 11, 2026 15:44

@dblock dblock left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great! Can we lock rubocop to a specific version in a future PR please, see my comment.

module Graphlient::Client::Spec
# schema_path avoids an HTTP schema fetch at file-load time.
# No Rack adapter needed here; parsing is local and execution is handled
# by the stub_request below.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice.

Comment thread .gitignore
.rvmrc

# AI agent instructions — local only, not for the upstream repo
CLAUDE.md

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should commit an AGENTS.md!

Comment thread Gemfile
group :development do
gem 'byebug', platform: :ruby
gem 'rubocop', '0.56.0'
gem 'rubocop', '~> 1.0'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is a gem and we don't check in Gemfile.lock, this should be locked to a specific version. Otherwise future CI runs will keep breaking without changes.

@dblock dblock merged commit 6a0998c into ashkan18:master Jun 11, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants