graphiti 2.0.0 → 2.0.1

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
  SHA256:
3
- metadata.gz: ac45688980e3b5a1b21c320161e5b8e67610dbcc2e0b4379f072cc86d8ff453f
4
- data.tar.gz: f1d4398684f5b44872251db6cbe8155a80b5c96388ebb42b4af45fa17373035c
3
+ metadata.gz: 1c38c96bcf6d48078c1361d22da7e563506b385b4bfe74b7b0fbdb8bd45ccb3a
4
+ data.tar.gz: 52e3079715304dc15408f6945f7515a6ba07db792cc55eda66887d2227e533c1
5
5
  SHA512:
6
- metadata.gz: 47b24e17dafad601b9ac9cf0898a7a838f9a4cedef37e88fd579e0a3b30cd4e14ac322e0b71bc0d0d2a168f04881f9cb2cbcc4d90984a0944440a04f533ca189
7
- data.tar.gz: 582d454ccaf706f46308dec57bbfe5db9b44663f84383c482fde1d23bc7e02dfe28045009d03e3607e19d9070f8e206dda99c79d42a0a78ebab88c8d9bd17b2b
6
+ metadata.gz: ab09db3099f66a44e8a453ee336aa93075b06a5cb46119a505380d08e9a7ae305f58da4a5822e319fb0e74b381537aee556681bcc6b9e353a7d1bec58705b2fa
7
+ data.tar.gz: 963db95d086610db6bd4600b56db8674804aac397ef4e4bbf687a387d4f2fea10cee7b0842f7d7d2bc89d65387210702d93b810819e5e663a8e7ed46bad9d6f5
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  graphiti changelog
2
2
 
3
+ ## [2.0.1](https://github.com/graphiti-api/graphiti/compare/v2.0.0...v2.0.1) (2026-09-02)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * count distinct on the primary key rather than every column ([be85c18](https://github.com/graphiti-api/graphiti/commit/be85c18b695bf482f95ae72496600b40e3531c44)), closes [#439](https://github.com/graphiti-api/graphiti/issues/439)
9
+ * keep the request body out of pagination links ([64040f2](https://github.com/graphiti-api/graphiti/commit/64040f200c307062d0b04204013e35963cec4ceb)), closes [#369](https://github.com/graphiti-api/graphiti/issues/369)
10
+ * read flags through one coercion ([72a39a7](https://github.com/graphiti-api/graphiti/commit/72a39a7c126e2d6d89fb4a829cad20efd207df4d))
11
+ * respect polymorphic_name when sideposting ([45d9eb7](https://github.com/graphiti-api/graphiti/commit/45d9eb73b1dba2e4587ee67387f0c3117c9c4fcf)), closes [#437](https://github.com/graphiti-api/graphiti/issues/437)
12
+ * stop the debugger requiring an id on every model ([8111b68](https://github.com/graphiti-api/graphiti/commit/8111b6897bd735bed84a63c312a6a01cf69317a1)), closes [#152](https://github.com/graphiti-api/graphiti/issues/152)
13
+
3
14
  # [2.0.0](https://github.com/graphiti-api/graphiti/compare/v1.13.3...v2.0.0) (2026-09-01)
4
15
 
5
16
 
@@ -198,7 +198,7 @@ module Graphiti
198
198
  # (see Adapters::Abstract#count)
199
199
  def count(scope, attr)
200
200
  if attr.to_sym == :total
201
- scope.distinct.count(:all)
201
+ scope.distinct.count(distinct_count_column(scope))
202
202
  else
203
203
  scope.distinct.count(attr)
204
204
  end
@@ -281,6 +281,10 @@ module Graphiti
281
281
  # Nothing to do in the else case, happened when we merged foreign key
282
282
  end
283
283
 
284
+ def polymorphic_type_value(parent_object)
285
+ parent_object.class.polymorphic_name
286
+ end
287
+
284
288
  def save(model_instance)
285
289
  model_instance.save
286
290
  model_instance
@@ -309,6 +313,13 @@ module Graphiti
309
313
 
310
314
  private
311
315
 
316
+ def distinct_count_column(scope)
317
+ primary_key = scope.klass.primary_key
318
+ return :all unless primary_key.is_a?(String)
319
+
320
+ scope.klass.arel_table[primary_key]
321
+ end
322
+
312
323
  def column_for(scope, name)
313
324
  table = scope.klass.arel_table
314
325
  if (other = scope.attribute_alias(name))
@@ -61,13 +61,17 @@ module Graphiti
61
61
  update_foreign_type(attrs, x, null: true) if x[:is_polymorphic]
62
62
  else
63
63
  if x[:sideload].polymorphic_has_one? || x[:sideload].polymorphic_has_many?
64
- attrs[:"#{x[:sideload].polymorphic_as}_type"] = parent_object.class.name
64
+ attrs[:"#{x[:sideload].polymorphic_as}_type"] = polymorphic_type_value(parent_object)
65
65
  end
66
66
  attrs[x[:foreign_key]] = parent_object.send(x[:primary_key])
67
67
  update_foreign_type(attrs, x) if x[:is_polymorphic]
68
68
  end
69
69
  end
70
70
 
71
+ def polymorphic_type_value(parent_object)
72
+ parent_object.class.name
73
+ end
74
+
71
75
  def update_foreign_type(attrs, x, null: false)
72
76
  grouping_field = x[:sideload].parent.grouper.field_name
73
77
  attrs[grouping_field] = null ? nil : x[:sideload].group_name
@@ -72,11 +72,8 @@ module Graphiti
72
72
  Debugger.debug_models = @debug_models
73
73
  end
74
74
 
75
- # every value comes back from ENV as a string and "false" is truthy
76
75
  def coerce_flag(val)
77
- return false if ["false", "0", ""].include?(val.to_s.strip.downcase)
78
-
79
- !!val
76
+ Types.flag(val)
80
77
  end
81
78
 
82
79
  def with_option(key, value)
@@ -63,12 +63,14 @@ module Graphiti
63
63
  end
64
64
 
65
65
  private def results(raw_results)
66
- raw_results.map { |r| "[#{r.class.name}, #{r.id.inspect}]" }.join(", ")
66
+ raw_results.map { |r|
67
+ identifier = r.respond_to?(:id) ? r.id.inspect : "no id"
68
+ "[#{r.class.name}, #{identifier}]"
69
+ }.join(", ")
67
70
  end
68
71
 
69
72
  private def on_sideload_data(payload, params, took)
70
73
  sideload = payload[:sideload]
71
- results = results(payload[:results])
72
74
  add_chunk(payload[:resource], payload[:parent]) do |logs, json|
73
75
  logs << [" \\_ #{sideload.name}", :yellow, true]
74
76
  json[:name] = sideload.name
@@ -79,14 +81,13 @@ module Graphiti
79
81
  end
80
82
  logs << [" #{query}", :cyan, true]
81
83
  json[:query] = query
82
- logs << [" Returned Models: #{results}"] if debug_models
84
+ logs << [" Returned Models: #{results(payload[:results])}"] if debug_models
83
85
  logs << [" Took: #{took}ms", :magenta, true]
84
86
  json[:took] = took
85
87
  end
86
88
  end
87
89
 
88
90
  private def on_primary_data(payload, params, took)
89
- results = results(payload[:results])
90
91
  add_chunk(payload[:resource], payload[:parent]) do |logs, json|
91
92
  logs << [""]
92
93
  logs << ["=== Graphiti Debug", :green, true]
@@ -96,7 +97,7 @@ module Graphiti
96
97
  query = "#{payload[:resource].class.name}.#{payload[:action]}(#{params.inspect})"
97
98
  logs << [query, :cyan, true]
98
99
  json[:query] = query
99
- logs << ["Returned Models: #{results}"] if debug_models
100
+ logs << ["Returned Models: #{results(payload[:results])}"] if debug_models
100
101
  logs << ["Took: #{took}ms", :magenta, true]
101
102
  json[:took] = took
102
103
  end
@@ -32,7 +32,7 @@ module Graphiti
32
32
  private
33
33
 
34
34
  def pagination_params
35
- @pagination_params ||= @proxy.query.params.except(:action, :controller, :format)
35
+ @pagination_params ||= @proxy.query.params.except(:action, :controller, :format, :data, :included)
36
36
  end
37
37
 
38
38
  def pagination_link(page)
@@ -2,7 +2,6 @@ require "digest"
2
2
 
3
3
  module Graphiti
4
4
  class Query
5
- TRUTHY_LINKS = [true, "true"].freeze
6
5
  LINKLESS_FORMATS = [:json, :xml, "json", "xml"].freeze
7
6
 
8
7
  attr_reader :resource, :association_name, :params, :action
@@ -80,7 +79,7 @@ module Graphiti
80
79
  def links_requested?
81
80
  return @links_requested if defined?(@links_requested)
82
81
 
83
- @links_requested = TRUTHY_LINKS.include?(@params[:links])
82
+ @links_requested = Types.flag(@params[:links])
84
83
  end
85
84
 
86
85
  def suppress_links?
@@ -107,11 +106,11 @@ module Graphiti
107
106
 
108
107
  def page_links_requested?
109
108
  [@params[:page_links], @params[:pagination_links]]
110
- .any? { |value| [true, "true"].include?(value) }
109
+ .any? { |value| Types.flag(value) }
111
110
  end
112
111
 
113
112
  def debug_requested?
114
- !!@params[:debug]
113
+ Types.flag(@params[:debug])
115
114
  end
116
115
 
117
116
  def hash
@@ -11,7 +11,11 @@ module Graphiti
11
11
  new(resources).generate
12
12
  end
13
13
 
14
- def self.generate!(resources = nil, path: Graphiti.config.schema_path, force: ENV["FORCE_SCHEMA"] == "true")
14
+ def self.forced?
15
+ Types.flag(ENV["FORCE_SCHEMA"])
16
+ end
17
+
18
+ def self.generate!(resources = nil, path: Graphiti.config.schema_path, force: forced?)
15
19
  result = check(resources, path: path)
16
20
  return result.errors if !force && !result.compatible?
17
21
 
@@ -131,7 +131,7 @@ module Graphiti
131
131
  ::RSpec.describe "Graphiti Schema" do
132
132
  it "generates a backwards-compatible schema" do
133
133
  check = Graphiti::Schema.check(resources, path: path || Graphiti.config.schema_path)
134
- forced = ENV["FORCE_SCHEMA"] == "true"
134
+ forced = Graphiti::Schema.forced?
135
135
  check.write! if check.compatible? || forced
136
136
 
137
137
  expect(check.compatible? || forced).to eq(true), check.message
@@ -222,6 +222,12 @@ module Graphiti
222
222
  map[key.to_sym] = value
223
223
  end
224
224
 
225
+ def self.flag(value)
226
+ self[:boolean][:params].call(value.to_s.strip)
227
+ rescue Dry::Types::CoercionError
228
+ false
229
+ end
230
+
225
231
  def self.name_for(key)
226
232
  key = key.to_sym
227
233
  type = map[key]
@@ -1,3 +1,3 @@
1
1
  module Graphiti
2
- VERSION = "2.0.0"
2
+ VERSION = "2.0.1"
3
3
  end
@@ -9,7 +9,7 @@ namespace :graphiti do
9
9
  Graphiti.logger = Graphiti.stdout_logger
10
10
  Graphiti::Debugger.preserve = true
11
11
  require "pp"
12
- path, debug = args[:path], args[:debug]
12
+ path, debug = args[:path], Graphiti::Types.flag(args[:debug])
13
13
  puts "Graphiti Request: #{path}"
14
14
  json = helpers.make_request(path, debug)
15
15
  pp json
@@ -20,7 +20,7 @@ namespace :graphiti do
20
20
  desc "Write the schema file. Refuses backwards-incompatible changes unless FORCE_SCHEMA=true. Takes an optional path, defaulting to Graphiti.config.schema_path."
21
21
  task :generate, [:path] => [:environment] do |_, args|
22
22
  check = Graphiti::Schema.check(path: helpers.schema_path(args[:path]))
23
- abort check.message unless check.compatible? || ENV["FORCE_SCHEMA"] == "true"
23
+ abort check.message unless check.compatible? || Graphiti::Schema.forced?
24
24
 
25
25
  puts "Schema written: #{check.write!}"
26
26
  end
@@ -49,12 +49,15 @@ namespace :graphiti do
49
49
 
50
50
  desc "Execute benchmark without web server."
51
51
  task :benchmark, [:path, :requests] => [:environment] do |_, args|
52
+ requests = args[:requests].to_i
53
+ abort "Needs a request count, as in graphiti:benchmark[/path,100]" unless requests > 0
54
+
52
55
  helpers.setup_rails!
53
56
  took = Benchmark.ms {
54
- args[:requests].to_i.times do
57
+ requests.times do
55
58
  helpers.make_request(args[:path])
56
59
  end
57
60
  }
58
- puts "Took: #{(took / args[:requests].to_f).round(2)}ms"
61
+ puts "Took: #{(took / requests).round(2)}ms"
59
62
  end
60
63
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphiti
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lee Richmond