graphiti 1.3.9 → 1.7.5

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: 30f5b9382256603c1f3f8f4ab8c4e614804c1a2e2152617d7b19892bca6bd465
4
- data.tar.gz: 948837bfa0f8deee2f44849aba9df2bb18f2fdf532a1caaab92b16c7d9ba91fd
3
+ metadata.gz: 526bde7653f2c482b92ee75c5a7afee5823f675024b9c6925e86aa04924e27d3
4
+ data.tar.gz: e7441df1db552bf0b30ee3d85a16fa644f4d770cff40bf199e9338c003ce810b
5
5
  SHA512:
6
- metadata.gz: 4fe6fff9c219fd463378bbdc793f648cbeffe27c61c191f11e2aab4723e952d2d8f7cc26b334255e12adca3e9d819b1bbde17697a6621f11a28151d2649d6d9c
7
- data.tar.gz: becca9eaa17f328a99669e1e855a4024862b45d1902ddf30de597f7b33e3f52e4145b0f1dba1542a0d144ba2bc1bdec280ad9d8fa599a102ead9efb5260e1ab3
6
+ metadata.gz: 1cccf050029f667eb96d0c76e379df5ecaddec574eede0708b3847cdb821b35fd1b527a8ffc5759d72f9d9a0f739d1d756cc4ea114dad1606621f6de13a814e3
7
+ data.tar.gz: 2f80a0ce18045b984ec722a395f79028ae1da6d2fbd7923424d5371bf177990c3692fa7c835d5ad27ecfe56b9d0da0a215c7ae3aff82cf47fc9822fb9e88a6c5
@@ -0,0 +1,2 @@
1
+ enabled:
2
+ - cla
@@ -28,10 +28,11 @@ jobs:
28
28
  fail-fast: false
29
29
  matrix:
30
30
  ruby:
31
- - "2.6"
32
31
  - "2.7"
33
32
  - "3.0"
34
33
  - "3.1"
34
+ - "3.2"
35
+ - "3.3"
35
36
  gemfile:
36
37
  - Gemfile
37
38
  - gemfiles/rails_5_2.gemfile
@@ -40,12 +41,13 @@ jobs:
40
41
  - gemfiles/rails_5_2_graphiti_rails.gemfile
41
42
  - gemfiles/rails_6_graphiti_rails.gemfile
42
43
  - gemfiles/rails_7_graphiti_rails.gemfile
44
+ - gemfiles/rails_7_1_graphiti_rails.gemfile
43
45
  appraisal:
44
46
  - true
45
47
  - false
46
48
  include:
47
49
  - ruby: ruby-head
48
- gemfile: Gemfile
50
+ gemfile: gemfiles/rails_7_1.gemfile
49
51
  appraisal: true
50
52
  - ruby: ruby-head
51
53
  gemfile: Gemfile
@@ -66,7 +68,9 @@ jobs:
66
68
  appraisal: false
67
69
  - gemfile: gemfiles/rails_7_graphiti_rails.gemfile
68
70
  appraisal: false
69
- # Rails 5 can't run on Ruby 3
71
+ - gemfile: gemfiles/rails_7_1_graphiti_rails.gemfile
72
+ appraisal: false
73
+ # Rails 5 can't run on Ruby 3
70
74
  - gemfile: gemfiles/rails_5_2.gemfile
71
75
  ruby: 3.0
72
76
  - gemfile: gemfiles/rails_5_2_graphiti_rails.gemfile
@@ -75,11 +79,14 @@ jobs:
75
79
  ruby: 3.1
76
80
  - gemfile: gemfiles/rails_5_2_graphiti_rails.gemfile
77
81
  ruby: 3.1
78
- # Raise 7 can't run on 2.6
79
- - gemfile: gemfiles/rails_7.gemfile
80
- ruby: 2.6
81
- - gemfile: gemfiles/rails_7_graphiti_rails.gemfile
82
- ruby: 2.6
82
+ - gemfile: gemfiles/rails_5_2.gemfile
83
+ ruby: 3.2
84
+ - gemfile: gemfiles/rails_5_2_graphiti_rails.gemfile
85
+ ruby: 3.2
86
+ - gemfile: gemfiles/rails_5_2.gemfile
87
+ ruby: 3.3
88
+ - gemfile: gemfiles/rails_5_2_graphiti_rails.gemfile
89
+ ruby: 3.3
83
90
  continue-on-error: ${{ matrix.ruby == 'ruby-head' }}
84
91
  env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps
85
92
  BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}
@@ -94,3 +101,14 @@ jobs:
94
101
  bundler-cache: true
95
102
  - name: Run tests
96
103
  run: bundle exec rspec
104
+ publish:
105
+ name: Release
106
+ runs-on: ubuntu-latest
107
+ if: github.ref == 'refs/heads/master'
108
+ needs: [test]
109
+ steps:
110
+ - name: Dispatch Release
111
+ uses: benc-uk/workflow-dispatch@v1
112
+ with:
113
+ workflow: Generate New Release
114
+ token: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,36 @@
1
+ ---
2
+ name: Generate New Release
3
+
4
+ on:
5
+ workflow_dispatch:
6
+
7
+ jobs:
8
+ release:
9
+ name: Release
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - name: Checkout
13
+ uses: actions/checkout@v3
14
+ with:
15
+ submodules: true
16
+ persist-credentials: false
17
+ - name: Set up Ruby
18
+ uses: ruby/setup-ruby@v1
19
+ with:
20
+ ruby-version: "3.1"
21
+ - name: Build
22
+ run: |
23
+ gem install bundler
24
+ git submodule update --init --recursive
25
+ bundle install --jobs 4 --retry 3
26
+ - name: Setup Node.js
27
+ uses: actions/setup-node@v2
28
+ with:
29
+ node-version: 14
30
+ - name: Install Dependencies
31
+ run: yarn install --frozen-lockfile
32
+ - name: Release
33
+ env:
34
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
35
+ GEM_HOST_API_KEY: ${{ secrets.GEM_HOST_API_KEY }}
36
+ run: node_modules/.bin/semantic-release
data/.gitignore CHANGED
@@ -7,6 +7,7 @@
7
7
  /spec/reports/
8
8
  /gemfiles/*.lock
9
9
  /tmp/
10
+ node_modules
10
11
  .byebug_history
11
12
  spec/.rspec-examples
12
13
  spec/dummy/log/*
data/.standard.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  fix: true
2
2
  parallel: true
3
- ruby_version: 2.4
3
+ ruby_version: 2.7
4
4
 
5
5
  ignore:
6
6
  - 'vendor/**/*'
data/Appraisals CHANGED
@@ -42,3 +42,18 @@ appraise "rails-7-graphiti-rails" do
42
42
  gem "database_cleaner"
43
43
  gem "graphiti-rails", "~> 0.4.0"
44
44
  end
45
+
46
+ appraise "rails-7-1" do
47
+ gem "rails", "~> 7.1"
48
+ gem "rspec-rails"
49
+ gem "sqlite3", "~> 1.4.0"
50
+ gem "database_cleaner"
51
+ end
52
+
53
+ appraise "rails-7-1-graphiti-rails" do
54
+ gem "rails", "~> 7.1"
55
+ gem "rspec-rails"
56
+ gem "sqlite3", "~> 1.4.0"
57
+ gem "database_cleaner"
58
+ gem "graphiti-rails", "~> 0.4.0"
59
+ end
data/CHANGELOG.md CHANGED
@@ -1,4 +1,122 @@
1
- ## Unreleased
1
+ graphiti changelog
2
+
3
+ ## [1.7.5](https://github.com/graphiti-api/graphiti/compare/v1.7.4...v1.7.5) (2024-09-16)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * Fixes error in version check for ActiveRecord adapter introduced in [#478](https://github.com/graphiti-api/graphiti/issues/478) ([#479](https://github.com/graphiti-api/graphiti/issues/479)) ([42c82c3](https://github.com/graphiti-api/graphiti/commit/42c82c397f20eb91c02835e518ff4c351c028ea7))
9
+
10
+ ## [1.7.4](https://github.com/graphiti-api/graphiti/compare/v1.7.3...v1.7.4) (2024-09-11)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * update ActiveRecord adapter w/ support for Rails 7.2+ ([#478](https://github.com/graphiti-api/graphiti/issues/478)) ([8313e33](https://github.com/graphiti-api/graphiti/commit/8313e3359f0dde28d9940867c7ded964db4c854d))
16
+
17
+ ## [1.7.3](https://github.com/graphiti-api/graphiti/compare/v1.7.2...v1.7.3) (2024-06-26)
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * require OpenStruct explicitly ([#475](https://github.com/graphiti-api/graphiti/issues/475)) ([e0fa18a](https://github.com/graphiti-api/graphiti/commit/e0fa18a8d7f051e385e6e081f79f2ecae92a9260))
23
+
24
+ ## [1.7.2](https://github.com/graphiti-api/graphiti/compare/v1.7.1...v1.7.2) (2024-06-11)
25
+
26
+
27
+ ### Bug Fixes
28
+
29
+ * require necessary ActiveSupport parts in proper order ([bb2a488](https://github.com/graphiti-api/graphiti/commit/bb2a48874a6533522df6eb027d0df8ec14c80a20))
30
+
31
+ ## [1.7.1](https://github.com/graphiti-api/graphiti/compare/v1.7.0...v1.7.1) (2024-04-18)
32
+
33
+
34
+ ### Bug Fixes
35
+
36
+ * properly display .find vs .all in debugger statements ([d2a7a03](https://github.com/graphiti-api/graphiti/commit/d2a7a038a649818979d52ccd898e68dba78b051f))
37
+ * rescue error from sideloads updated_at calculation, defaulting to the current time ([661e3b5](https://github.com/graphiti-api/graphiti/commit/661e3b5212e2649870a200067d0d5d52fa962637))
38
+
39
+ # [1.7.0](https://github.com/graphiti-api/graphiti/compare/v1.6.4...v1.7.0) (2024-03-27)
40
+
41
+
42
+ ### Features
43
+
44
+ * Add support for caching renders in Graphiti, and better support using etags and stale? in the controller ([#424](https://github.com/graphiti-api/graphiti/issues/424)) ([8bae50a](https://github.com/graphiti-api/graphiti/commit/8bae50ab82559e2644d506e16a4f715effd89317))
45
+
46
+ ## [1.6.4](https://github.com/graphiti-api/graphiti/compare/v1.6.3...v1.6.4) (2024-03-27)
47
+
48
+ ## [1.6.3](https://github.com/graphiti-api/graphiti/compare/v1.6.2...v1.6.3) (2024-03-26)
49
+
50
+
51
+ ### Bug Fixes
52
+
53
+ * Remove thread pool executor logic until we get a better handle on what's causing thread pool hangs. refs [#469](https://github.com/graphiti-api/graphiti/issues/469) ([7941b6f](https://github.com/graphiti-api/graphiti/commit/7941b6f75ce1001b034ed6e83c148b893e9f3d99)), closes [#471](https://github.com/graphiti-api/graphiti/issues/471) [#470](https://github.com/graphiti-api/graphiti/issues/470)
54
+
55
+ ## [1.6.2](https://github.com/graphiti-api/graphiti/compare/v1.6.1...v1.6.2) (2024-03-22)
56
+
57
+
58
+ ### Bug Fixes
59
+
60
+ * thread pool scope and mutex need to be global across all instances of Scope for it to be a global thread pool ([#471](https://github.com/graphiti-api/graphiti/issues/471)) ([51fb51c](https://github.com/graphiti-api/graphiti/commit/51fb51c31f0043d98aa07f689a8cf8c758fa823b))
61
+
62
+ ## [1.6.1](https://github.com/graphiti-api/graphiti/compare/v1.6.0...v1.6.1) (2024-03-22)
63
+
64
+
65
+ ### Bug Fixes
66
+
67
+ * correct thread-pool mutex logic which was causing a deadlock ([0400ab0](https://github.com/graphiti-api/graphiti/commit/0400ab0d97a1382b66b5295fdc7aa7db680e77cc))
68
+
69
+ # [1.6.0](https://github.com/graphiti-api/graphiti/compare/v1.5.3...v1.6.0) (2024-03-20)
70
+
71
+
72
+ ### Features
73
+
74
+ * add thread pool and concurrency_max_threads configuration option ([#470](https://github.com/graphiti-api/graphiti/issues/470)) ([697d761](https://github.com/graphiti-api/graphiti/commit/697d76172adec24cd7e7522300c8335233fdcc36))
75
+
76
+ ## [1.5.3](https://github.com/graphiti-api/graphiti/compare/v1.5.2...v1.5.3) (2024-03-18)
77
+
78
+
79
+ ### Bug Fixes
80
+
81
+ * leverage ruby-2.7 parameter forwarding ([#431](https://github.com/graphiti-api/graphiti/issues/431)) ([ae09a46](https://github.com/graphiti-api/graphiti/commit/ae09a464b2156742bb093537deac0578a1a3e40e))
82
+ * prevent :id stripping when :id not in path ([#447](https://github.com/graphiti-api/graphiti/issues/447)) ([e1dd811](https://github.com/graphiti-api/graphiti/commit/e1dd811283f6e6fe7a36b925934df0ecbb4d3411))
83
+
84
+ ## [1.5.2](https://github.com/graphiti-api/graphiti/compare/v1.5.1...v1.5.2) (2024-03-18)
85
+
86
+
87
+ ### Bug Fixes
88
+
89
+ * Enum should allow the conventionally case-sensitive operators ([#434](https://github.com/graphiti-api/graphiti/issues/434)) ([56d34fd](https://github.com/graphiti-api/graphiti/commit/56d34fd4801bc32c13d64aca880b82b717b2ab81))
90
+
91
+ ## [1.5.1](https://github.com/graphiti-api/graphiti/compare/v1.5.0...v1.5.1) (2024-03-18)
92
+
93
+
94
+ ### Bug Fixes
95
+
96
+ * polymorphic `on` expects a symbol ([#433](https://github.com/graphiti-api/graphiti/issues/433)) ([4e58702](https://github.com/graphiti-api/graphiti/commit/4e587021265323bd0b170b57e9c7aecaa7f826d7))
97
+
98
+ # [1.5.0](https://github.com/graphiti-api/graphiti/compare/v1.4.0...v1.5.0) (2024-03-18)
99
+
100
+
101
+ ### Features
102
+
103
+ * add before_sideload hook ([#371](https://github.com/graphiti-api/graphiti/issues/371)) ([f68b61f](https://github.com/graphiti-api/graphiti/commit/f68b61ff09ec61ecf23acc5bc37d0accba14aeed))
104
+
105
+ ## 1.4.0, Sun March 17th 2024
106
+ Features:
107
+ - [461](https://github.com/graphiti-api/graphiti/pull/461), [463](https://github.com/graphiti-api/graphiti/pull/463) Add support for Rails 7.1 + Ruby 3.2 + Ruby 3.3
108
+
109
+ Fixes:
110
+ - [464](https://github.com/graphiti-api/graphiti/pull/464) Check for url presence before trying to append
111
+ - [407](https://github.com/graphiti-api/graphiti/pull/407) Sort types in generated schema
112
+ - [421](https://github.com/graphiti-api/graphiti/pull/421) Re-use resource class for remote sideloads to avoid memory leak
113
+ - [452](https://github.com/graphiti-api/graphiti/pull/452) Resolve inconsistency for filters containing curly brackets
114
+ - [446](https://github.com/graphiti-api/graphiti/pull/446) Fix private call
115
+
116
+ ## 1.3.9, May 25th 2022
117
+ Use an options hash for log subscriber instead of positional arguments
118
+
119
+ ## 1.x ??
2
120
 
3
121
  Features:
4
122
  - [329](https://github.com/graphiti-api/graphiti/pull/329) Propagate `extra_fields` to related resource links.
data/Gemfile CHANGED
@@ -4,6 +4,7 @@ source "https://rubygems.org"
4
4
  gemspec
5
5
 
6
6
  group :test do
7
+ gem "database_cleaner"
7
8
  gem "pry"
8
9
  gem "pry-byebug", platform: [:mri]
9
10
  gem "appraisal"
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
- ![Build Status](https://travis-ci.org/graphiti-api/graphiti.svg?branch=master)
1
+ [![CI](https://github.com/graphiti-api/graphiti/actions/workflows/ci.yml/badge.svg)](https://github.com/graphiti-api/graphiti/actions/workflows/ci.yml)
2
2
  [![Gem Version](https://badge.fury.io/rb/graphiti.svg)](https://badge.fury.io/rb/graphiti)
3
3
  [![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)
4
+ [![semantic-release: angular](https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release)](https://github.com/semantic-release/semantic-release)
4
5
 
5
6
  <p align="center">
6
7
  <a href="https://www.graphiti.dev/guides">
@@ -0,0 +1,18 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 7.1"
6
+ gem "rspec-rails"
7
+ gem "sqlite3", "~> 1.4.0"
8
+ gem "database_cleaner"
9
+
10
+ group :test do
11
+ gem "pry"
12
+ gem "pry-byebug", platform: [:mri]
13
+ gem "appraisal"
14
+ gem "guard"
15
+ gem "guard-rspec"
16
+ end
17
+
18
+ gemspec path: "../"
@@ -0,0 +1,19 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 7.1"
6
+ gem "rspec-rails"
7
+ gem "sqlite3", "~> 1.4.0"
8
+ gem "database_cleaner"
9
+ gem "graphiti-rails", "~> 0.4.0"
10
+
11
+ group :test do
12
+ gem "pry"
13
+ gem "pry-byebug", platform: [:mri]
14
+ gem "appraisal"
15
+ gem "guard"
16
+ gem "guard-rspec"
17
+ end
18
+
19
+ gemspec path: "../"
data/graphiti.gemspec CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
16
16
  spec.bindir = "exe"
17
17
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
18
  spec.require_paths = ["lib"]
19
- spec.required_ruby_version = ">= 2.6"
19
+ spec.required_ruby_version = ">= 2.7"
20
20
 
21
21
  spec.add_dependency "jsonapi-serializable", "~> 0.3.0"
22
22
  spec.add_dependency "jsonapi-renderer", "~> 0.2", ">= 0.2.2"
@@ -39,7 +39,7 @@ module Graphiti
39
39
  :not_match
40
40
  ],
41
41
  uuid: [:eq, :not_eq],
42
- enum: [:eq, :not_eq],
42
+ enum: [:eq, :not_eq, :eql, :not_eql],
43
43
  integer_id: numerical_operators,
44
44
  integer: numerical_operators,
45
45
  big_decimal: numerical_operators,
@@ -26,6 +26,7 @@ module Graphiti
26
26
  alias_method :filter_boolean_eq, :filter_eq
27
27
  alias_method :filter_uuid_eq, :filter_eq
28
28
  alias_method :filter_enum_eq, :filter_eq
29
+ alias_method :filter_enum_eql, :filter_eq
29
30
 
30
31
  def filter_not_eq(scope, attribute, value)
31
32
  scope.where.not(attribute => value)
@@ -37,6 +38,7 @@ module Graphiti
37
38
  alias_method :filter_boolean_not_eq, :filter_not_eq
38
39
  alias_method :filter_uuid_not_eq, :filter_not_eq
39
40
  alias_method :filter_enum_not_eq, :filter_not_eq
41
+ alias_method :filter_enum_not_eql, :filter_not_eq
40
42
 
41
43
  def filter_string_eq(scope, attribute, value, is_not: false)
42
44
  column = column_for(scope, attribute)
@@ -302,7 +304,11 @@ module Graphiti
302
304
  end
303
305
 
304
306
  def close
305
- ::ActiveRecord::Base.clear_active_connections!
307
+ if ::ActiveRecord.version > "7.2"
308
+ ::ActiveRecord::Base.connection_handler.clear_active_connections!
309
+ else
310
+ ::ActiveRecord::Base.clear_active_connections!
311
+ end
306
312
  end
307
313
 
308
314
  def can_group?
@@ -15,10 +15,12 @@ module Graphiti
15
15
  attr_accessor :pagination_links
16
16
  attr_accessor :typecast_reads
17
17
  attr_accessor :raise_on_missing_sidepost
18
+ attr_accessor :before_sideload
18
19
 
19
20
  attr_reader :debug, :debug_models
20
21
 
21
22
  attr_writer :schema_path
23
+ attr_writer :cache_rendering
22
24
 
23
25
  # Set defaults
24
26
  # @api private
@@ -31,6 +33,7 @@ module Graphiti
31
33
  @pagination_links = false
32
34
  @typecast_reads = true
33
35
  @raise_on_missing_sidepost = true
36
+ @cache_rendering = false
34
37
  self.debug = ENV.fetch("GRAPHITI_DEBUG", true)
35
38
  self.debug_models = ENV.fetch("GRAPHITI_DEBUG_MODELS", false)
36
39
 
@@ -51,6 +54,16 @@ module Graphiti
51
54
  end
52
55
  end
53
56
 
57
+ def cache_rendering?
58
+ use_caching = @cache_rendering && Graphiti.cache.respond_to?(:fetch)
59
+
60
+ use_caching.tap do |use|
61
+ if @cache_rendering && !Graphiti.cache&.respond_to?(:fetch)
62
+ raise "You must configure a cache store in order to use cache_rendering. Set Graphiti.cache = Rails.cache, for example."
63
+ end
64
+ end
65
+ end
66
+
54
67
  def schema_path
55
68
  @schema_path ||= raise("No schema_path defined! Set Graphiti.config.schema_path to save your schema.")
56
69
  end
@@ -36,7 +36,7 @@ module Graphiti
36
36
  json[:sideload] = sideload.name
37
37
  end
38
38
  if params
39
- query = "#{payload[:resource].class.name}.all(#{JSON.pretty_generate(params)}).data"
39
+ query = "#{payload[:resource].class.name}.#{payload[:action]}(#{JSON.pretty_generate(params)}).data"
40
40
  logs << [query, :cyan, true]
41
41
  logs << ["The error occurred when running the above query. Copy/paste it into a rake task or Rails console session to reproduce. Keep in mind you may have to set context.", :yellow, true]
42
42
  else
@@ -64,7 +64,7 @@ module Graphiti
64
64
  query = if sideload.class.scope_proc
65
65
  "#{payload[:resource].class.name}: Manual sideload via .scope"
66
66
  else
67
- "#{payload[:resource].class.name}.all(#{params.inspect})"
67
+ "#{payload[:resource].class.name}.#{payload[:action]}(#{params.inspect})"
68
68
  end
69
69
  logs << [" #{query}", :cyan, true]
70
70
  json[:query] = query
@@ -82,7 +82,7 @@ module Graphiti
82
82
  title = "Top Level Data Retrieval (+ sideloads):"
83
83
  logs << [title, :green, true]
84
84
  json[:title] = title
85
- query = "#{payload[:resource].class.name}.all(#{params.inspect})"
85
+ query = "#{payload[:resource].class.name}.#{payload[:action]}(#{params.inspect})"
86
86
  logs << [query, :cyan, true]
87
87
  json[:query] = query
88
88
  logs << ["Returned Models: #{results}"] if debug_models
@@ -98,7 +98,30 @@ module Graphiti
98
98
  took = ((stop - start) * 1000.0).round(2)
99
99
  logs << [""]
100
100
  logs << ["=== Graphiti Debug", :green, true]
101
- logs << ["Rendering:", :green, true]
101
+ if payload[:proxy]&.cached? && Graphiti.config.cache_rendering?
102
+ logs << ["Rendering (cached):", :green, true]
103
+
104
+ Graphiti::Util::CacheDebug.new(payload[:proxy]).analyze do |cache_debug|
105
+ logs << ["Cache key for #{cache_debug.name}", :blue, true]
106
+ logs << if cache_debug.volatile?
107
+ [" \\_ volatile | Request count: #{cache_debug.request_count} | Hit count: #{cache_debug.hit_count}", :red, true]
108
+ else
109
+ [" \\_ stable | Request count: #{cache_debug.request_count} | Hit count: #{cache_debug.hit_count}", :blue, true]
110
+ end
111
+
112
+ if cache_debug.changed_key?
113
+ logs << [" [x] cache key changed #{cache_debug.last_version[:etag]} -> #{cache_debug.current_version[:etag]}", :red]
114
+ logs << [" removed: #{cache_debug.removed_segments}", :red]
115
+ logs << [" added: #{cache_debug.added_segments}", :red]
116
+ elsif cache_debug.new_key?
117
+ logs << [" [+] cache key added #{cache_debug.current_version[:etag]}", :red, true]
118
+ else
119
+ logs << [" [✓] #{cache_debug.current_version[:etag]}", :green, true]
120
+ end
121
+ end
122
+ else
123
+ logs << ["Rendering:", :green, true]
124
+ end
102
125
  logs << ["Took: #{took}ms", :magenta, true]
103
126
  end
104
127
  end
@@ -140,7 +163,6 @@ module Graphiti
140
163
  params ||= {}
141
164
  params = params.to_unsafe_h if params.respond_to?(:to_unsafe_h)
142
165
  params.reject! { |k, v| [:controller, :action, :format, :debug].include?(k.to_sym) }
143
- params.reject! { |k, v| k.to_sym == :include }
144
166
  params.deep_symbolize_keys
145
167
  end
146
168
 
@@ -1,3 +1,5 @@
1
+ require "digest"
2
+
1
3
  module Graphiti
2
4
  class Query
3
5
  attr_reader :resource, :association_name, :params, :action
@@ -76,11 +78,14 @@ module Graphiti
76
78
  end
77
79
  end
78
80
 
81
+ class RemoteSideloadResource < ::Graphiti::Resource
82
+ self.remote = "_remote_sideload_".freeze
83
+ self.abstract_class = true # exclude from schema
84
+ end
85
+
79
86
  def resource_for_sideload(sideload)
80
87
  if @resource.remote?
81
- Class.new(Graphiti::Resource) {
82
- self.remote = "_remote_sideload_"
83
- }.new
88
+ RemoteSideloadResource.new
84
89
  else
85
90
  sideload.resource
86
91
  end
@@ -229,8 +234,22 @@ module Graphiti
229
234
  ![false, "false"].include?(@params[:paginate])
230
235
  end
231
236
 
237
+ def cache_key
238
+ "args-#{query_cache_key}"
239
+ end
240
+
232
241
  private
233
242
 
243
+ def query_cache_key
244
+ attrs = {extra_fields: extra_fields,
245
+ fields: fields,
246
+ links: links?,
247
+ pagination_links: pagination_links?,
248
+ format: params[:format]}
249
+
250
+ Digest::SHA1.hexdigest(attrs.to_s)
251
+ end
252
+
234
253
  def cast_page_param(name, value)
235
254
  if [:before, :after].include?(name)
236
255
  decode_cursor(value)
@@ -68,7 +68,14 @@ module Graphiti
68
68
  options[:meta][:debug] = Debugger.to_a if debug_json?
69
69
  options[:proxy] = proxy
70
70
 
71
- renderer.render(records, options)
71
+ if proxy.cache? && Graphiti.config.cache_rendering?
72
+ Graphiti.cache.fetch("graphiti:render/#{proxy.cache_key}", version: proxy.updated_at, expires_in: proxy.cache_expires_in) do
73
+ options.delete(:cache) # ensure that we don't use JSONAPI-Resources's built-in caching logic
74
+ renderer.render(records, options)
75
+ end
76
+ else
77
+ renderer.render(records, options)
78
+ end
72
79
  end
73
80
  end
74
81
 
@@ -205,7 +205,7 @@ module Graphiti
205
205
  options[name] ||= send(:"relationships_#{name}_by_default")
206
206
  end
207
207
  end
208
- private :attribute_option
208
+ private :relationship_option
209
209
  end
210
210
  end
211
211
  end
@@ -4,8 +4,13 @@ module Graphiti
4
4
  extend ActiveSupport::Concern
5
5
 
6
6
  class_methods do
7
+ def cache_resource(expires_in: false)
8
+ @cache_resource = true
9
+ @cache_expires_in = expires_in
10
+ end
11
+
7
12
  def all(params = {}, base_scope = nil)
8
- validate!(params)
13
+ validate_request!(params)
9
14
  _all(params, {}, base_scope)
10
15
  end
11
16
 
@@ -13,11 +18,11 @@ module Graphiti
13
18
  def _all(params, opts, base_scope)
14
19
  runner = Runner.new(self, params, opts.delete(:query), :all)
15
20
  opts[:params] = params
16
- runner.proxy(base_scope, opts)
21
+ runner.proxy(base_scope, opts.merge(caching_options))
17
22
  end
18
23
 
19
24
  def find(params = {}, base_scope = nil)
20
- validate!(params)
25
+ validate_request!(params)
21
26
  _find(params, base_scope)
22
27
  end
23
28
 
@@ -31,21 +36,29 @@ module Graphiti
31
36
  params[:filter][:id] = id if id
32
37
 
33
38
  runner = Runner.new(self, params, nil, :find)
34
- runner.proxy base_scope,
39
+
40
+ find_options = {
35
41
  single: true,
36
42
  raise_on_missing: true,
37
43
  bypass_required_filters: true
44
+ }.merge(caching_options)
45
+
46
+ runner.proxy base_scope, find_options
38
47
  end
39
48
 
40
49
  def build(params, base_scope = nil)
41
- validate!(params)
50
+ validate_request!(params)
42
51
  runner = Runner.new(self, params)
43
52
  runner.proxy(base_scope, single: true, raise_on_missing: true)
44
53
  end
45
54
 
46
55
  private
47
56
 
48
- def validate!(params)
57
+ def caching_options
58
+ {cache: @cache_resource, cache_expires_in: @cache_expires_in}
59
+ end
60
+
61
+ def validate_request!(params)
49
62
  return if Graphiti.context[:graphql] || !validate_endpoints?
50
63
 
51
64
  if context&.respond_to?(:request)
@@ -76,7 +76,7 @@ module Graphiti
76
76
  path = request_path
77
77
  if [:update, :show, :destroy].include?(context_namespace) && has_id
78
78
  path = request_path.split("/")
79
- path.pop
79
+ path.pop if path.last == has_id.to_s
80
80
  path = path.join("/")
81
81
  end
82
82
  e[:full_path].to_s == path && e[:actions].include?(context_namespace)
@@ -68,7 +68,7 @@ module Graphiti
68
68
  model_ref = model
69
69
  has_many name, opts do
70
70
  params do |hash|
71
- hash[:filter][:"#{as}_type"] = { eql: model_ref.name }
71
+ hash[:filter][:"#{as}_type"] = {eql: model_ref.name}
72
72
  end
73
73
 
74
74
  instance_eval(&blk) if blk
@@ -82,7 +82,7 @@ module Graphiti
82
82
  model_ref = model
83
83
  has_one name, opts do
84
84
  params do |hash|
85
- hash[:filter][:"#{as}_type"] = { eql: model_ref.name }
85
+ hash[:filter][:"#{as}_type"] = {eql: model_ref.name}
86
86
  end
87
87
 
88
88
  instance_eval(&blk) if blk