graphiti-activegraph 1.3.3 → 1.4.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.
- checksums.yaml +4 -4
- data/.github/workflows/specs.yml +58 -58
- data/.hound.yml +7 -4
- data/.rubocop.yml +48 -6
- data/CHANGELOG.md +83 -71
- data/graphiti-activegraph.gemspec +35 -35
- data/lib/graphiti/active_graph/resource_proxy.rb +97 -86
- data/lib/graphiti/active_graph/resources/persistence.rb +31 -25
- data/lib/graphiti/active_graph/runner.rb +47 -39
- data/lib/graphiti/active_graph/sideload_resolve.rb +119 -119
- data/lib/graphiti/active_graph/util/serializer_relationships.rb +22 -0
- data/lib/graphiti/active_graph/version.rb +7 -5
- data/lib/graphiti-activegraph.rb +44 -43
- metadata +6 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e31914fe6d6f7f7ab7a391ede7de332f9e3dfb6ee633f8efc7c601b9ae18ad4e
|
|
4
|
+
data.tar.gz: 65cbf76ded94827c57e8ce27ab009001e53883d33e0f75feafd9c6b887da6087
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a7ee5ff8f6d47403706a64c2dc002b2f9cdc7b439f1f4ccd11e904981e489f2e8320e6e3cea029b18ccf89b0bf41b28a865d9c268d062e9cb247c34395b9e79e
|
|
7
|
+
data.tar.gz: fb36ab1994476e560ea25beaa000f16b2159da649a5516919aa46a762c68643a2f97dcb289a2f334093a5f157a4e733a0d85cc8259690bae035d88a870922414
|
data/.github/workflows/specs.yml
CHANGED
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
name: Specs
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [ "master" ]
|
|
6
|
-
pull_request:
|
|
7
|
-
branches: [ "master" ]
|
|
8
|
-
|
|
9
|
-
# Allows you to run this workflow manually from the Actions tab
|
|
10
|
-
workflow_dispatch:
|
|
11
|
-
|
|
12
|
-
permissions:
|
|
13
|
-
actions: write
|
|
14
|
-
contents: read
|
|
15
|
-
|
|
16
|
-
jobs:
|
|
17
|
-
test:
|
|
18
|
-
runs-on: ubuntu-latest
|
|
19
|
-
|
|
20
|
-
strategy:
|
|
21
|
-
fail-fast: false
|
|
22
|
-
matrix:
|
|
23
|
-
ruby-version: [ '3.4', '4.0.3' ] # Removed 'jruby' till https://github.com/jruby/jruby/issues/8642 is fixed
|
|
24
|
-
neo4j: [ '5.26.0', '5.23.0' ]
|
|
25
|
-
include:
|
|
26
|
-
- ruby: jruby
|
|
27
|
-
java-version: 17
|
|
28
|
-
env:
|
|
29
|
-
JRUBY_OPTS: --debug -J-Xmx1280m -Xcompile.invokedynamic=false -J-XX:+TieredCompilation -J-XX:TieredStopAtLevel=1 -J-noverify -Xcompile.mode=OFF
|
|
30
|
-
steps:
|
|
31
|
-
- name: Start neo4j
|
|
32
|
-
run: docker run --name neo4j --env NEO4J_AUTH=neo4j/password --env NEO4J_ACCEPT_LICENSE_AGREEMENT=yes --env NEO4J_dbms_directories_import= -p7687:7687 -p7474:7474 -v `pwd`/tmp:/var/lib/neo4j/import --rm neo4j:${{ matrix.neo4j }}-enterprise &
|
|
33
|
-
|
|
34
|
-
- uses: actions/checkout@v3
|
|
35
|
-
|
|
36
|
-
- name: Set up Ruby
|
|
37
|
-
uses: ruby/setup-ruby@v1
|
|
38
|
-
with:
|
|
39
|
-
ruby-version: ${{ matrix.ruby-version }}
|
|
40
|
-
bundler-cache: true
|
|
41
|
-
|
|
42
|
-
- name: Set up Java
|
|
43
|
-
uses: actions/setup-java@v4
|
|
44
|
-
if: matrix.java-version
|
|
45
|
-
with:
|
|
46
|
-
distribution: 'temurin'
|
|
47
|
-
java-version: ${{ matrix.java-version }}
|
|
48
|
-
|
|
49
|
-
- name: Wait for neo4j
|
|
50
|
-
run: while [ $((curl localhost:7474/ > /dev/null 2>&1); echo $?) -ne 0 ]; do sleep 1; done
|
|
51
|
-
|
|
52
|
-
- name: Run tests
|
|
53
|
-
run: bundle exec rspec
|
|
54
|
-
|
|
55
|
-
- name: Upload coverage reports to Codecov
|
|
56
|
-
uses: codecov/codecov-action@v5
|
|
57
|
-
with:
|
|
58
|
-
token: ${{ secrets.CODECOV_TOKEN }}
|
|
1
|
+
name: Specs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ "master" ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ "master" ]
|
|
8
|
+
|
|
9
|
+
# Allows you to run this workflow manually from the Actions tab
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
actions: write
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
test:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
|
|
20
|
+
strategy:
|
|
21
|
+
fail-fast: false
|
|
22
|
+
matrix:
|
|
23
|
+
ruby-version: [ '3.4', '4.0.3' ] # Removed 'jruby' till https://github.com/jruby/jruby/issues/8642 is fixed
|
|
24
|
+
neo4j: [ '5.26.0', '5.23.0' ]
|
|
25
|
+
include:
|
|
26
|
+
- ruby: jruby
|
|
27
|
+
java-version: 17
|
|
28
|
+
env:
|
|
29
|
+
JRUBY_OPTS: --debug -J-Xmx1280m -Xcompile.invokedynamic=false -J-XX:+TieredCompilation -J-XX:TieredStopAtLevel=1 -J-noverify -Xcompile.mode=OFF
|
|
30
|
+
steps:
|
|
31
|
+
- name: Start neo4j
|
|
32
|
+
run: docker run --name neo4j --env NEO4J_AUTH=neo4j/password --env NEO4J_ACCEPT_LICENSE_AGREEMENT=yes --env NEO4J_PLUGINS='["apoc"]' --env NEO4J_dbms_directories_import= -p7687:7687 -p7474:7474 -v `pwd`/tmp:/var/lib/neo4j/import --rm neo4j:${{ matrix.neo4j }}-enterprise &
|
|
33
|
+
|
|
34
|
+
- uses: actions/checkout@v3
|
|
35
|
+
|
|
36
|
+
- name: Set up Ruby
|
|
37
|
+
uses: ruby/setup-ruby@v1
|
|
38
|
+
with:
|
|
39
|
+
ruby-version: ${{ matrix.ruby-version }}
|
|
40
|
+
bundler-cache: true
|
|
41
|
+
|
|
42
|
+
- name: Set up Java
|
|
43
|
+
uses: actions/setup-java@v4
|
|
44
|
+
if: matrix.java-version
|
|
45
|
+
with:
|
|
46
|
+
distribution: 'temurin'
|
|
47
|
+
java-version: ${{ matrix.java-version }}
|
|
48
|
+
|
|
49
|
+
- name: Wait for neo4j
|
|
50
|
+
run: while [ $((curl localhost:7474/ > /dev/null 2>&1); echo $?) -ne 0 ]; do sleep 1; done
|
|
51
|
+
|
|
52
|
+
- name: Run tests
|
|
53
|
+
run: bundle exec rspec
|
|
54
|
+
|
|
55
|
+
- name: Upload coverage reports to Codecov
|
|
56
|
+
uses: codecov/codecov-action@v5
|
|
57
|
+
with:
|
|
58
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
data/.hound.yml
CHANGED
data/.rubocop.yml
CHANGED
|
@@ -1,6 +1,48 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Layout/LineLength:
|
|
6
|
-
Max: 120
|
|
1
|
+
AllCops:
|
|
2
|
+
TargetRubyVersion: 3.0
|
|
3
|
+
SuggestExtensions: false
|
|
4
|
+
|
|
5
|
+
Layout/LineLength:
|
|
6
|
+
Max: 120
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
Metrics/BlockLength:
|
|
10
|
+
Exclude:
|
|
11
|
+
- 'spec/**/*'
|
|
12
|
+
|
|
13
|
+
Style/Documentation:
|
|
14
|
+
Enabled: false
|
|
15
|
+
|
|
16
|
+
Style/ClassAndModuleChildren:
|
|
17
|
+
Enabled: false
|
|
18
|
+
|
|
19
|
+
Metrics/AbcSize:
|
|
20
|
+
Enabled: false
|
|
21
|
+
|
|
22
|
+
Metrics/MethodLength:
|
|
23
|
+
Enabled: false
|
|
24
|
+
|
|
25
|
+
Metrics/ClassLength:
|
|
26
|
+
Enabled: false
|
|
27
|
+
|
|
28
|
+
Metrics/CyclomaticComplexity:
|
|
29
|
+
Enabled: false
|
|
30
|
+
|
|
31
|
+
Metrics/PerceivedComplexity:
|
|
32
|
+
Enabled: false
|
|
33
|
+
|
|
34
|
+
Metrics/ParameterLists:
|
|
35
|
+
Enabled: false
|
|
36
|
+
|
|
37
|
+
Style/FrozenStringLiteralComment:
|
|
38
|
+
Enabled: false
|
|
39
|
+
|
|
40
|
+
Naming/FileName:
|
|
41
|
+
Enabled: false
|
|
42
|
+
|
|
43
|
+
Style/StringLiterals:
|
|
44
|
+
Enabled: false
|
|
45
|
+
|
|
46
|
+
Layout/SpaceInsideHashLiteralBraces:
|
|
47
|
+
Enabled: false
|
|
48
|
+
|
data/CHANGELOG.md
CHANGED
|
@@ -1,71 +1,83 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to this project will be documented in this file.
|
|
4
|
-
|
|
5
|
-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
-
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
-
|
|
8
|
-
## [Unreleased]
|
|
9
|
-
|
|
10
|
-
## [1.
|
|
11
|
-
|
|
12
|
-
### Changed
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
-
|
|
21
|
-
|
|
22
|
-
## [1.3.
|
|
23
|
-
|
|
24
|
-
###
|
|
25
|
-
|
|
26
|
-
- **
|
|
27
|
-
|
|
28
|
-
## [1.3.
|
|
29
|
-
|
|
30
|
-
###
|
|
31
|
-
|
|
32
|
-
- **
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
- **
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
- **
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [1.4.0] - 2026-09-02
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Added support for Graphiti 1.13.4, including `Resource.wrap` and per-request relationship guards.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Forward Graphiti cache options, including `cache_tag`, through the ActiveGraph runner and resource proxy overrides.
|
|
19
|
+
- Keep statically unreadable relationships out of ActiveGraph serializers while preserving Graphiti 1.13's dynamic readability guards.
|
|
20
|
+
- Preserve Graphiti 1.13's scope resolution block and `around_persistence` mutation warning behavior in ActiveGraph overrides.
|
|
21
|
+
|
|
22
|
+
## [1.3.3] - 2026-05-05
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- **Ruby 4 and Graphiti 1.9.0 support**: Added support for Ruby 4 and Graphiti 1.9.0 and made minor performance improvements.
|
|
27
|
+
|
|
28
|
+
## [1.3.2] - 2026-02-11
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- **Grouping criteria**: parsing improved to ignore commas inside parentheses, allowing for more complex grouping criteria (e.g. group_by='custom_function(arg1,arg2),another_value'). Previous implementation would split the criteria at the comma inside the parentheses, leading to inability to pass the function call. (PR #51)
|
|
33
|
+
|
|
34
|
+
## [1.3.1] - 2025-11-5
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- **Deserializer: relationship id(s) helpers**: introduced `relationship_id` and `relationship_ids` methods in `Deserializer` to fetch relationship id(s) by association name from request payload. (PR #49)
|
|
39
|
+
|
|
40
|
+
## [1.3.0] - 2025-10-13
|
|
41
|
+
|
|
42
|
+
### Added
|
|
43
|
+
|
|
44
|
+
- **Extra fields preloading in main query**: Support preloading associations for `extra_fields` for main and sideloaded records. Adds `preload` option to `extra_attribute` in resource classes. Example: `extra_attribute :full_post_title, :string, preload: :author`. (PR #45)
|
|
45
|
+
- **Extra fields preloading in separate query**: Collect IDs from the main query result and run a single separate query to load and calculate `extra_fields` values for all records. does not support preloading for deep sideloads. (PR #47)
|
|
46
|
+
|
|
47
|
+
## [1.2.0] - 2025-05-20
|
|
48
|
+
|
|
49
|
+
### Added
|
|
50
|
+
|
|
51
|
+
- **Graphiti Compatibility**: Added support for Graphiti versions up to 1.8.x, fixing previously broken sideloading behavior.
|
|
52
|
+
|
|
53
|
+
### Fixed
|
|
54
|
+
|
|
55
|
+
- **Serializer**: Resolved an issue where polymorphic resources were not functioning correctly in serializers.
|
|
56
|
+
|
|
57
|
+
## [1.1.0] - 2025-05-2
|
|
58
|
+
|
|
59
|
+
### Added
|
|
60
|
+
|
|
61
|
+
- **Deep sideloading**: introduced Include scoping class to support deep sideloading using single query (e.g. include='author.posts')
|
|
62
|
+
- **Deep sorting**: added SortNormalizer to support sorting by deep sideloaded resource's attribute (e.g. sort='author.posts.title')
|
|
63
|
+
- **Links control**: Control the links(pagination and resource) in response via request query params (pagination_links=true|false, links=true|false)
|
|
64
|
+
|
|
65
|
+
## [1.0.0] - 2025-03-18
|
|
66
|
+
|
|
67
|
+
### Added
|
|
68
|
+
|
|
69
|
+
- **MRI Support**: Introduced compatibility with MRI (Matz's Ruby Interpreter), expanding the gem's usability beyond JRuby (#38).
|
|
70
|
+
- **Documentation Updates**: Expanded the README to provide clearer guidance on gem usage and integration (#38).
|
|
71
|
+
- **Sideloading Workflow**: Enhanced scoping mechanisms and added support for eager loading associations to improve data retrieval efficiency and flexibility (#38).
|
|
72
|
+
|
|
73
|
+
### Changed
|
|
74
|
+
|
|
75
|
+
- **Resource Class**: Instead of modifying the `Graphiti::Resource` class, we now define `Graphiti::ActiveGraph::Resource`,
|
|
76
|
+
which must be inherited in all resource classes to enable ActiveGraph support (#38).
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
*Note: For details on changes prior to version 1.0.0, please refer to the [`CHANGELOG_PRE_1.0.0.md`](CHANGELOG_PRE_1.0.0.md) file.*
|
|
81
|
+
|
|
82
|
+
[unreleased]: https://github.com/mrhardikjoshi/graphiti-activegraph/compare/v1.0.0...master
|
|
83
|
+
[1.0.0]: https://github.com/mrhardikjoshi/graphiti-activegraph/compare/9f837108ae57287c65b0f6fd2609dd56a95cd461...v1.0.0
|
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
lib = File.expand_path('../lib', __FILE__)
|
|
2
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
|
-
require 'graphiti/active_graph/version'
|
|
4
|
-
|
|
5
|
-
Gem::Specification.new do |spec|
|
|
6
|
-
spec.name = 'graphiti-activegraph'
|
|
7
|
-
spec.version = Graphiti::ActiveGraph::VERSION
|
|
8
|
-
spec.authors = ['Hardik Joshi']
|
|
9
|
-
spec.email = ['hardikjoshi1991@gmail.com']
|
|
10
|
-
|
|
11
|
-
spec.summary = 'Easily build jsonapi.org-compatible APIs for GraphDB'
|
|
12
|
-
spec.homepage = 'https://github.com/mrhardikjoshi/graphiti-activegraph'
|
|
13
|
-
spec.license = 'MIT'
|
|
14
|
-
|
|
15
|
-
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
16
|
-
spec.bindir = 'exe'
|
|
17
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
18
|
-
spec.require_paths = ['lib']
|
|
19
|
-
|
|
20
|
-
spec.add_dependency 'graphiti', '>= 1.
|
|
21
|
-
spec.add_dependency 'activegraph', '>= 12.0.0.beta.5'
|
|
22
|
-
spec.add_dependency 'parslet', '>= 2.0.0'
|
|
23
|
-
spec.add_dependency 'activegraph-extensions', '>= 0.1.0'
|
|
24
|
-
|
|
25
|
-
spec.add_development_dependency 'graphiti_spec_helpers', '>= 1.0.0'
|
|
26
|
-
spec.add_development_dependency 'standard'
|
|
27
|
-
spec.add_development_dependency 'pry'
|
|
28
|
-
spec.add_development_dependency 'ffaker'
|
|
29
|
-
spec.add_development_dependency 'simplecov'
|
|
30
|
-
spec.add_development_dependency 'simplecov_json_formatter'
|
|
31
|
-
spec.add_development_dependency 'factory_bot_rails'
|
|
32
|
-
spec.add_development_dependency 'rake', '>= 10.0'
|
|
33
|
-
spec.add_development_dependency 'rspec', '>= 3.9.0'
|
|
34
|
-
spec.add_development_dependency 'ostruct'
|
|
35
|
-
end
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
|
+
require 'graphiti/active_graph/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'graphiti-activegraph'
|
|
7
|
+
spec.version = Graphiti::ActiveGraph::VERSION
|
|
8
|
+
spec.authors = ['Hardik Joshi']
|
|
9
|
+
spec.email = ['hardikjoshi1991@gmail.com']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'Easily build jsonapi.org-compatible APIs for GraphDB'
|
|
12
|
+
spec.homepage = 'https://github.com/mrhardikjoshi/graphiti-activegraph'
|
|
13
|
+
spec.license = 'MIT'
|
|
14
|
+
|
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
16
|
+
spec.bindir = 'exe'
|
|
17
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
18
|
+
spec.require_paths = ['lib']
|
|
19
|
+
|
|
20
|
+
spec.add_dependency 'graphiti', '>= 1.9.0', '<= 1.13.4'
|
|
21
|
+
spec.add_dependency 'activegraph', '>= 12.0.0.beta.5'
|
|
22
|
+
spec.add_dependency 'parslet', '>= 2.0.0'
|
|
23
|
+
spec.add_dependency 'activegraph-extensions', '>= 0.1.0'
|
|
24
|
+
|
|
25
|
+
spec.add_development_dependency 'graphiti_spec_helpers', '>= 1.0.0'
|
|
26
|
+
spec.add_development_dependency 'standard'
|
|
27
|
+
spec.add_development_dependency 'pry'
|
|
28
|
+
spec.add_development_dependency 'ffaker'
|
|
29
|
+
spec.add_development_dependency 'simplecov'
|
|
30
|
+
spec.add_development_dependency 'simplecov_json_formatter'
|
|
31
|
+
spec.add_development_dependency 'factory_bot_rails'
|
|
32
|
+
spec.add_development_dependency 'rake', '>= 10.0'
|
|
33
|
+
spec.add_development_dependency 'rspec', '>= 3.9.0'
|
|
34
|
+
spec.add_development_dependency 'ostruct'
|
|
35
|
+
end
|
|
@@ -1,86 +1,97 @@
|
|
|
1
|
-
module Graphiti::ActiveGraph
|
|
2
|
-
module ResourceProxy
|
|
3
|
-
include Graphiti::ActiveGraph::SideloadResolve
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
@
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
@
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
success
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
1
|
+
module Graphiti::ActiveGraph
|
|
2
|
+
module ResourceProxy
|
|
3
|
+
include Graphiti::ActiveGraph::SideloadResolve
|
|
4
|
+
|
|
5
|
+
attr_reader :preloaded, :cache_tag
|
|
6
|
+
|
|
7
|
+
def initialize(
|
|
8
|
+
resource,
|
|
9
|
+
scope,
|
|
10
|
+
query,
|
|
11
|
+
payload: nil,
|
|
12
|
+
single: false,
|
|
13
|
+
raise_on_missing: false,
|
|
14
|
+
cache: nil,
|
|
15
|
+
cache_expires_in: nil,
|
|
16
|
+
cache_tag: nil,
|
|
17
|
+
preloaded: false
|
|
18
|
+
)
|
|
19
|
+
@resource = resource
|
|
20
|
+
@scope = scope
|
|
21
|
+
@query = query
|
|
22
|
+
@payload = payload
|
|
23
|
+
@single = single
|
|
24
|
+
@raise_on_missing = raise_on_missing
|
|
25
|
+
@cache = cache
|
|
26
|
+
@cache_expires_in = cache_expires_in
|
|
27
|
+
@cache_tag = cache_tag
|
|
28
|
+
@preloaded = preloaded
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def data
|
|
32
|
+
return @data if @data
|
|
33
|
+
|
|
34
|
+
return super unless @preloaded
|
|
35
|
+
|
|
36
|
+
resolve_sideloads(@preloaded)
|
|
37
|
+
@single ? data_for_preloaded_record : data_for_preloaded_records
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
alias_method :resolve_data, :data
|
|
41
|
+
|
|
42
|
+
def data_for_preloaded_record
|
|
43
|
+
@preloaded = @preloaded.is_a?(Array) ? @preloaded[0] : @preloaded
|
|
44
|
+
@resource.decorate_record(@preloaded)
|
|
45
|
+
@data = @preloaded
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def data_for_preloaded_records
|
|
49
|
+
@preloaded.each do |r|
|
|
50
|
+
@resource.decorate_record(r)
|
|
51
|
+
end
|
|
52
|
+
@data = @preloaded
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def stats
|
|
56
|
+
@stats ||= if @query.stats && !resource.relation_resource?
|
|
57
|
+
payload = ::Graphiti::Stats::Payload.new @resource,
|
|
58
|
+
@query,
|
|
59
|
+
@scope.unpaginated_object,
|
|
60
|
+
data
|
|
61
|
+
payload.generate
|
|
62
|
+
else
|
|
63
|
+
{}
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def save(action: :create)
|
|
68
|
+
# TODO: remove this. Only used for persisting many-to-many with AR
|
|
69
|
+
# (see activerecord adapter)
|
|
70
|
+
original = Graphiti.context[:namespace]
|
|
71
|
+
begin
|
|
72
|
+
Graphiti.context[:namespace] = action
|
|
73
|
+
::Graphiti::RequestValidator.new(@resource, @payload.params, action).validate!
|
|
74
|
+
validator = persist {
|
|
75
|
+
@resource.persist_with_relationships \
|
|
76
|
+
@payload.meta(action: action),
|
|
77
|
+
@payload.attributes,
|
|
78
|
+
@payload.relationships
|
|
79
|
+
}
|
|
80
|
+
ensure
|
|
81
|
+
Graphiti.context[:namespace] = original
|
|
82
|
+
end
|
|
83
|
+
@data, success = validator.to_a
|
|
84
|
+
|
|
85
|
+
if success && !resource.relation_resource?
|
|
86
|
+
# If the context namespace is `update` or `create`, certain
|
|
87
|
+
# adapters will cause N+1 validation calls, so lets explicitly
|
|
88
|
+
# switch to a lookup context.
|
|
89
|
+
Graphiti.with_context(Graphiti.context[:object], :show) do
|
|
90
|
+
@scope.resolve_sideloads([@data])
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
success
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -1,25 +1,31 @@
|
|
|
1
|
-
module Graphiti::ActiveGraph
|
|
2
|
-
module Resources
|
|
3
|
-
module Persistence
|
|
4
|
-
def update(update_params, meta = nil)
|
|
5
|
-
model_instance = nil
|
|
6
|
-
id = update_params[:id]
|
|
7
|
-
update_params = update_params.except(:id)
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
run_callbacks :
|
|
17
|
-
model_instance =
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
end
|
|
1
|
+
module Graphiti::ActiveGraph
|
|
2
|
+
module Resources
|
|
3
|
+
module Persistence
|
|
4
|
+
def update(update_params, meta = nil)
|
|
5
|
+
model_instance = nil
|
|
6
|
+
id = update_params[:id]
|
|
7
|
+
update_params = update_params.except(:id)
|
|
8
|
+
|
|
9
|
+
snapshot = attributes_snapshot(:update, update_params) if respond_to?(:attributes_snapshot, true)
|
|
10
|
+
|
|
11
|
+
run_callbacks :persistence, :update, update_params, meta do
|
|
12
|
+
if respond_to?(:warn_attributes_mutated_in_around_persistence, true)
|
|
13
|
+
warn_attributes_mutated_in_around_persistence(:update, snapshot, update_params)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
run_callbacks :attributes, :update, update_params, meta do |params|
|
|
17
|
+
model_instance = id ? model.find(id) : self.class._find(id: id).data
|
|
18
|
+
call_with_meta(:assign_attributes, model_instance, params, meta)
|
|
19
|
+
model_instance
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
run_callbacks :save, :update, model_instance, meta do
|
|
23
|
+
model_instance = call_with_meta(:save, model_instance, meta)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
model_instance
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -1,39 +1,47 @@
|
|
|
1
|
-
module Graphiti::ActiveGraph
|
|
2
|
-
module Runner
|
|
3
|
-
def initialize(resource_class, params, query = nil, action = nil)
|
|
4
|
-
@resource_class = resource_class
|
|
5
|
-
@params = params
|
|
6
|
-
@query = query
|
|
7
|
-
@action = action
|
|
8
|
-
|
|
9
|
-
validator = ::Graphiti::RequestValidator.new(jsonapi_resource, params, action)
|
|
10
|
-
|
|
11
|
-
validator.validate! unless params[:skip_render_val]
|
|
12
|
-
|
|
13
|
-
@deserialized_payload = validator.deserialized_payload
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def proxy(base = nil, opts = {})
|
|
17
|
-
base ||= jsonapi_resource.base_scope
|
|
18
|
-
scope_opts = opts.slice(
|
|
19
|
-
:
|
|
20
|
-
:
|
|
21
|
-
:
|
|
22
|
-
:
|
|
23
|
-
:
|
|
24
|
-
:
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
1
|
+
module Graphiti::ActiveGraph
|
|
2
|
+
module Runner
|
|
3
|
+
def initialize(resource_class, params, query = nil, action = nil)
|
|
4
|
+
@resource_class = resource_class
|
|
5
|
+
@params = params
|
|
6
|
+
@query = query
|
|
7
|
+
@action = action
|
|
8
|
+
|
|
9
|
+
validator = ::Graphiti::RequestValidator.new(jsonapi_resource, params, action)
|
|
10
|
+
|
|
11
|
+
validator.validate! unless params[:skip_render_val]
|
|
12
|
+
|
|
13
|
+
@deserialized_payload = validator.deserialized_payload
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def proxy(base = nil, opts = {})
|
|
17
|
+
base ||= jsonapi_resource.base_scope
|
|
18
|
+
scope_opts = opts.slice(
|
|
19
|
+
:sideload_parent_length,
|
|
20
|
+
:default_paginate,
|
|
21
|
+
:after_resolve,
|
|
22
|
+
:sideload,
|
|
23
|
+
:parent,
|
|
24
|
+
:params,
|
|
25
|
+
:bypass_required_filters,
|
|
26
|
+
:preloaded
|
|
27
|
+
).merge(unpaginated_query: params[:unpaginated_query])
|
|
28
|
+
scope = jsonapi_scope(base, scope_opts)
|
|
29
|
+
preloaded = opts[:preloaded]
|
|
30
|
+
options = {
|
|
31
|
+
payload: deserialized_payload,
|
|
32
|
+
single: opts[:single],
|
|
33
|
+
raise_on_missing: opts[:raise_on_missing],
|
|
34
|
+
cache: opts[:cache],
|
|
35
|
+
cache_expires_in: opts[:cache_expires_in],
|
|
36
|
+
cache_tag: opts[:cache_tag],
|
|
37
|
+
preloaded: preloaded
|
|
38
|
+
}
|
|
39
|
+
::Graphiti::ResourceProxy.new(
|
|
40
|
+
jsonapi_resource,
|
|
41
|
+
scope,
|
|
42
|
+
query,
|
|
43
|
+
**options
|
|
44
|
+
)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -1,119 +1,119 @@
|
|
|
1
|
-
module Graphiti::ActiveGraph
|
|
2
|
-
module SideloadResolve
|
|
3
|
-
PRELOAD_METHOD_PREFIX = 'preload_'.freeze
|
|
4
|
-
|
|
5
|
-
def initialize(object, resource, query, opts = {})
|
|
6
|
-
@object = object
|
|
7
|
-
@resource = resource
|
|
8
|
-
@query = query
|
|
9
|
-
@opts = opts
|
|
10
|
-
@unpaginated_object = opts[:unpaginated_query].presence || @object
|
|
11
|
-
|
|
12
|
-
return if opts[:preloaded]
|
|
13
|
-
@object = @resource.around_scoping(@object, @query.hash) { |scope|
|
|
14
|
-
apply_scoping(scope, opts)
|
|
15
|
-
}
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def resolve_sideloads(parents)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def resolve
|
|
22
|
-
resolve_with_callbacks.tap { |results| preload_extra_fields(results) }
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
private
|
|
26
|
-
|
|
27
|
-
def resolve_with_callbacks
|
|
28
|
-
if @query.zero_results?
|
|
29
|
-
[]
|
|
30
|
-
else
|
|
31
|
-
resolved = broadcast_data { |payload|
|
|
32
|
-
@object = @resource.before_resolve(@object, @query)
|
|
33
|
-
payload[:results] = @resource.resolve(@object)
|
|
34
|
-
payload[:results]
|
|
35
|
-
}
|
|
36
|
-
resolved.compact!
|
|
37
|
-
assign_serializer(resolved)
|
|
38
|
-
yield resolved if block_given?
|
|
39
|
-
@opts[:after_resolve]&.call(resolved)
|
|
40
|
-
resolve_sideloads(resolved) unless @query.sideloads.empty?
|
|
41
|
-
resolved
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def preload_extra_fields(results)
|
|
46
|
-
@query.extra_fields.each do |type, extra_field_names|
|
|
47
|
-
extra_field_names.each do |name|
|
|
48
|
-
next unless preload_extra_field?(type, name)
|
|
49
|
-
|
|
50
|
-
records_for_preload = collect_records_for_preload(type, results)
|
|
51
|
-
result_map = fetch_preloaded_data(type, name, records_for_preload)
|
|
52
|
-
assign_preloaded_data(records_for_preload, name, result_map)
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def fetch_preloaded_data(type, extra_field_name, results)
|
|
58
|
-
resource_for_preload(type).model.public_send(default_preload_method(extra_field_name), results.pluck(:id).uniq)
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def assign_preloaded_data(results, extra_field_name, result_map)
|
|
62
|
-
results.each { |r| r.public_send("#{extra_field_name}=", result_map[r.id]) }
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def preload_extra_field?(type, extra_field_name)
|
|
66
|
-
resource = resource_for_preload(type)
|
|
67
|
-
resource && resource.extra_attribute?(extra_field_name) && resource.model.respond_to?(default_preload_method(extra_field_name))
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def resource_for_preload(type)
|
|
71
|
-
return @resource if type == @resource.type
|
|
72
|
-
|
|
73
|
-
find_resource_in_included_associations(type) unless @query.sideloads.empty?
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def find_resource_in_included_associations(type, sideload_query = @query)
|
|
77
|
-
sideload_query.sideloads.values.each do |sideload|
|
|
78
|
-
return sideload.resource if sideload.resource.type == type
|
|
79
|
-
|
|
80
|
-
resource = find_resource_in_included_associations(type, sideload)
|
|
81
|
-
return resource if resource
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
nil
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
def default_preload_method(extra_field_name)
|
|
88
|
-
"#{PRELOAD_METHOD_PREFIX}#{extra_field_name}"
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def collect_records_for_preload(type, results)
|
|
92
|
-
base_records = resource_matches_type?(@resource, type) ? Array(results) : []
|
|
93
|
-
sideloaded_records = collect_sideloaded_records(Array(results), @query, type)
|
|
94
|
-
(base_records + sideloaded_records).flatten.compact.uniq
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
def collect_sideloaded_records(source_records, sideload_query, type)
|
|
98
|
-
return [] if source_records.empty? || sideload_query.sideloads.empty?
|
|
99
|
-
|
|
100
|
-
sideload_query.sideloads.flat_map do |sideload_name, nested_query|
|
|
101
|
-
associated_records = collect_associated_records(source_records, sideload_name)
|
|
102
|
-
matched_records = resource_matches_type?(nested_query.resource, type) ? associated_records : []
|
|
103
|
-
matched_records + collect_sideloaded_records(associated_records, nested_query, type)
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def resource_matches_type?(resource, type)
|
|
108
|
-
resource&.type == type
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def collect_associated_records(source_records, sideload_name)
|
|
112
|
-
source_records.flat_map do |parent|
|
|
113
|
-
next [] unless parent.respond_to?(sideload_name)
|
|
114
|
-
|
|
115
|
-
Array(parent.public_send(sideload_name)).compact
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
end
|
|
119
|
-
end
|
|
1
|
+
module Graphiti::ActiveGraph
|
|
2
|
+
module SideloadResolve
|
|
3
|
+
PRELOAD_METHOD_PREFIX = 'preload_'.freeze
|
|
4
|
+
|
|
5
|
+
def initialize(object, resource, query, opts = {})
|
|
6
|
+
@object = object
|
|
7
|
+
@resource = resource
|
|
8
|
+
@query = query
|
|
9
|
+
@opts = opts
|
|
10
|
+
@unpaginated_object = opts[:unpaginated_query].presence || @object
|
|
11
|
+
|
|
12
|
+
return if opts[:preloaded]
|
|
13
|
+
@object = @resource.around_scoping(@object, @query.hash) { |scope|
|
|
14
|
+
apply_scoping(scope, opts)
|
|
15
|
+
}
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def resolve_sideloads(parents)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def resolve(&blk)
|
|
22
|
+
resolve_with_callbacks(&blk).tap { |results| preload_extra_fields(results) }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def resolve_with_callbacks
|
|
28
|
+
if @query.zero_results?
|
|
29
|
+
[]
|
|
30
|
+
else
|
|
31
|
+
resolved = broadcast_data { |payload|
|
|
32
|
+
@object = @resource.before_resolve(@object, @query)
|
|
33
|
+
payload[:results] = @resource.resolve(@object)
|
|
34
|
+
payload[:results]
|
|
35
|
+
}
|
|
36
|
+
resolved.compact!
|
|
37
|
+
assign_serializer(resolved)
|
|
38
|
+
yield resolved if block_given?
|
|
39
|
+
@opts[:after_resolve]&.call(resolved)
|
|
40
|
+
resolve_sideloads(resolved) unless @query.sideloads.empty?
|
|
41
|
+
resolved
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def preload_extra_fields(results)
|
|
46
|
+
@query.extra_fields.each do |type, extra_field_names|
|
|
47
|
+
extra_field_names.each do |name|
|
|
48
|
+
next unless preload_extra_field?(type, name)
|
|
49
|
+
|
|
50
|
+
records_for_preload = collect_records_for_preload(type, results)
|
|
51
|
+
result_map = fetch_preloaded_data(type, name, records_for_preload)
|
|
52
|
+
assign_preloaded_data(records_for_preload, name, result_map)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def fetch_preloaded_data(type, extra_field_name, results)
|
|
58
|
+
resource_for_preload(type).model.public_send(default_preload_method(extra_field_name), results.pluck(:id).uniq)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def assign_preloaded_data(results, extra_field_name, result_map)
|
|
62
|
+
results.each { |r| r.public_send("#{extra_field_name}=", result_map[r.id]) }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def preload_extra_field?(type, extra_field_name)
|
|
66
|
+
resource = resource_for_preload(type)
|
|
67
|
+
resource && resource.extra_attribute?(extra_field_name) && resource.model.respond_to?(default_preload_method(extra_field_name))
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def resource_for_preload(type)
|
|
71
|
+
return @resource if type == @resource.type
|
|
72
|
+
|
|
73
|
+
find_resource_in_included_associations(type) unless @query.sideloads.empty?
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def find_resource_in_included_associations(type, sideload_query = @query)
|
|
77
|
+
sideload_query.sideloads.values.each do |sideload|
|
|
78
|
+
return sideload.resource if sideload.resource.type == type
|
|
79
|
+
|
|
80
|
+
resource = find_resource_in_included_associations(type, sideload)
|
|
81
|
+
return resource if resource
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
nil
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def default_preload_method(extra_field_name)
|
|
88
|
+
"#{PRELOAD_METHOD_PREFIX}#{extra_field_name}"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def collect_records_for_preload(type, results)
|
|
92
|
+
base_records = resource_matches_type?(@resource, type) ? Array(results) : []
|
|
93
|
+
sideloaded_records = collect_sideloaded_records(Array(results), @query, type)
|
|
94
|
+
(base_records + sideloaded_records).flatten.compact.uniq
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def collect_sideloaded_records(source_records, sideload_query, type)
|
|
98
|
+
return [] if source_records.empty? || sideload_query.sideloads.empty?
|
|
99
|
+
|
|
100
|
+
sideload_query.sideloads.flat_map do |sideload_name, nested_query|
|
|
101
|
+
associated_records = collect_associated_records(source_records, sideload_name)
|
|
102
|
+
matched_records = resource_matches_type?(nested_query.resource, type) ? associated_records : []
|
|
103
|
+
matched_records + collect_sideloaded_records(associated_records, nested_query, type)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def resource_matches_type?(resource, type)
|
|
108
|
+
resource&.type == type
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def collect_associated_records(source_records, sideload_name)
|
|
112
|
+
source_records.flat_map do |parent|
|
|
113
|
+
next [] unless parent.respond_to?(sideload_name)
|
|
114
|
+
|
|
115
|
+
Array(parent.public_send(sideload_name)).compact
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Graphiti
|
|
4
|
+
module ActiveGraph
|
|
5
|
+
module Util
|
|
6
|
+
module SerializerRelationships
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
def apply?(sideload)
|
|
10
|
+
return super if dynamically_readable?(sideload)
|
|
11
|
+
|
|
12
|
+
super && sideload.readable?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def dynamically_readable?(sideload)
|
|
16
|
+
flag = sideload.instance_variable_get(:@readable)
|
|
17
|
+
flag.is_a?(Symbol) || flag.is_a?(String) || flag.is_a?(Proc)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
data/lib/graphiti-activegraph.rb
CHANGED
|
@@ -1,43 +1,44 @@
|
|
|
1
|
-
require 'active_support'
|
|
2
|
-
require 'active_graph'
|
|
3
|
-
|
|
4
|
-
# Workaround for jruby prepend issue https://github.com/jruby/jruby/issues/6971
|
|
5
|
-
module Graphiti
|
|
6
|
-
module ActiveGraph
|
|
7
|
-
end
|
|
8
|
-
module Scoping
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
require 'graphiti/scoping/filterable'
|
|
12
|
-
require 'graphiti/resource/persistence'
|
|
13
|
-
require 'graphiti/resource/interface'
|
|
14
|
-
# End workaround for jruby prepend issue
|
|
15
|
-
|
|
16
|
-
require 'zeitwerk'
|
|
17
|
-
loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
|
|
18
|
-
loader.inflector.inflect 'version' => 'VERSION'
|
|
19
|
-
loader.ignore(File.expand_path('graphiti-activegraph.rb', __dir__))
|
|
20
|
-
loader.setup
|
|
21
|
-
|
|
22
|
-
Graphiti::Scoping::Filterable.prepend Graphiti::ActiveGraph::Scoping::Filterable
|
|
23
|
-
Graphiti::Resource::Persistence.prepend Graphiti::ActiveGraph::Resources::Persistence
|
|
24
|
-
Graphiti::Resource::Interface::ClassMethods.prepend Graphiti::ActiveGraph::Resources::Interface::ClassMethods
|
|
25
|
-
require 'graphiti'
|
|
26
|
-
Graphiti::Scoping::Filter.prepend Graphiti::ActiveGraph::Scoping::Filter
|
|
27
|
-
Graphiti::Serializer.prepend Graphiti::ActiveGraph::Serializer
|
|
28
|
-
Graphiti::Util::
|
|
29
|
-
Graphiti::Util::
|
|
30
|
-
Graphiti::Util::
|
|
31
|
-
Graphiti::
|
|
32
|
-
Graphiti::
|
|
33
|
-
Graphiti::
|
|
34
|
-
Graphiti::
|
|
35
|
-
Graphiti::
|
|
36
|
-
Graphiti::
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
JSONAPI
|
|
1
|
+
require 'active_support'
|
|
2
|
+
require 'active_graph'
|
|
3
|
+
|
|
4
|
+
# Workaround for jruby prepend issue https://github.com/jruby/jruby/issues/6971
|
|
5
|
+
module Graphiti
|
|
6
|
+
module ActiveGraph
|
|
7
|
+
end
|
|
8
|
+
module Scoping
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
require 'graphiti/scoping/filterable'
|
|
12
|
+
require 'graphiti/resource/persistence'
|
|
13
|
+
require 'graphiti/resource/interface'
|
|
14
|
+
# End workaround for jruby prepend issue
|
|
15
|
+
|
|
16
|
+
require 'zeitwerk'
|
|
17
|
+
loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
|
|
18
|
+
loader.inflector.inflect 'version' => 'VERSION'
|
|
19
|
+
loader.ignore(File.expand_path('graphiti-activegraph.rb', __dir__))
|
|
20
|
+
loader.setup
|
|
21
|
+
|
|
22
|
+
Graphiti::Scoping::Filterable.prepend Graphiti::ActiveGraph::Scoping::Filterable
|
|
23
|
+
Graphiti::Resource::Persistence.prepend Graphiti::ActiveGraph::Resources::Persistence
|
|
24
|
+
Graphiti::Resource::Interface::ClassMethods.prepend Graphiti::ActiveGraph::Resources::Interface::ClassMethods
|
|
25
|
+
require 'graphiti'
|
|
26
|
+
Graphiti::Scoping::Filter.prepend Graphiti::ActiveGraph::Scoping::Filter
|
|
27
|
+
Graphiti::Serializer.prepend Graphiti::ActiveGraph::Serializer
|
|
28
|
+
Graphiti::Util::SerializerRelationships.prepend Graphiti::ActiveGraph::Util::SerializerRelationships
|
|
29
|
+
Graphiti::Util::SerializerRelationship.prepend Graphiti::ActiveGraph::Util::SerializerRelationship
|
|
30
|
+
Graphiti::Util::SerializerAttribute.prepend Graphiti::ActiveGraph::Util::SerializerAttribute
|
|
31
|
+
Graphiti::Util::RelationshipPayload.prepend Graphiti::ActiveGraph::Util::RelationshipPayload
|
|
32
|
+
Graphiti::Query.prepend Graphiti::ActiveGraph::Query
|
|
33
|
+
Graphiti::ResourceProxy.prepend Graphiti::ActiveGraph::ResourceProxy
|
|
34
|
+
Graphiti::Runner.prepend Graphiti::ActiveGraph::Runner
|
|
35
|
+
Graphiti::Scope.prepend Graphiti::ActiveGraph::SideloadResolve
|
|
36
|
+
Graphiti::Configuration.include Graphiti::SidepostConfiguration
|
|
37
|
+
Graphiti::RequestValidators::Validator.prepend Graphiti::ActiveGraph::RequestValidators::Validator
|
|
38
|
+
|
|
39
|
+
unless RUBY_PLATFORM == 'java'
|
|
40
|
+
Graphiti.prepend Graphiti::ActiveGraph::Extensions::Context
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# JSONAPI extensions
|
|
44
|
+
JSONAPI::Serializable::Resource.prepend Graphiti::ActiveGraph::JsonapiExt::Serializable::ResourceExt
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: graphiti-activegraph
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Hardik Joshi
|
|
@@ -15,20 +15,20 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 1.
|
|
18
|
+
version: 1.9.0
|
|
19
19
|
- - "<="
|
|
20
20
|
- !ruby/object:Gem::Version
|
|
21
|
-
version: 1.
|
|
21
|
+
version: 1.13.4
|
|
22
22
|
type: :runtime
|
|
23
23
|
prerelease: false
|
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
25
25
|
requirements:
|
|
26
26
|
- - ">="
|
|
27
27
|
- !ruby/object:Gem::Version
|
|
28
|
-
version: 1.
|
|
28
|
+
version: 1.9.0
|
|
29
29
|
- - "<="
|
|
30
30
|
- !ruby/object:Gem::Version
|
|
31
|
-
version: 1.
|
|
31
|
+
version: 1.13.4
|
|
32
32
|
- !ruby/object:Gem::Dependency
|
|
33
33
|
name: activegraph
|
|
34
34
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -274,6 +274,7 @@ files:
|
|
|
274
274
|
- lib/graphiti/active_graph/util/relationship_payload.rb
|
|
275
275
|
- lib/graphiti/active_graph/util/serializer_attribute.rb
|
|
276
276
|
- lib/graphiti/active_graph/util/serializer_relationship.rb
|
|
277
|
+
- lib/graphiti/active_graph/util/serializer_relationships.rb
|
|
277
278
|
- lib/graphiti/active_graph/util/transformers/relation_param.rb
|
|
278
279
|
- lib/graphiti/active_graph/version.rb
|
|
279
280
|
- lib/graphiti/sidepost_configuration.rb
|