graphiti 2.0.0.beta.2 → 2.0.0.beta.4
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/ci.yml +30 -86
- data/.github/workflows/docs.yml +60 -0
- data/.github/workflows/release.yml +8 -8
- data/.gitignore +7 -0
- data/.npmrc +9 -0
- data/.standard.yml +4 -1
- data/Appraisals +33 -32
- data/CHANGELOG.md +41 -0
- data/README.md +13 -2
- data/UPGRADING.md +2 -68
- data/docs/concepts/backends-and-models.md +122 -0
- data/docs/concepts/endpoints.md +183 -0
- data/docs/concepts/links.md +212 -0
- data/docs/concepts/overview.md +80 -0
- data/docs/concepts/persisting.md +376 -0
- data/docs/concepts/relationships.md +527 -0
- data/docs/concepts/resources.md +677 -0
- data/docs/getting-started/first-api.md +289 -0
- data/docs/getting-started/installation.md +185 -0
- data/docs/intro.md +307 -0
- data/docs/js/authentication.md +63 -0
- data/docs/js/ddau.md +20 -0
- data/docs/js/extra-params.md +41 -0
- data/docs/js/index.md +112 -0
- data/docs/js/installation.md +120 -0
- data/docs/js/middleware.md +72 -0
- data/docs/js/models.md +202 -0
- data/docs/js/reads.md +494 -0
- data/docs/js/state-syncing.md +100 -0
- data/docs/js/writes.md +373 -0
- data/docs/reference/vandal.md +63 -0
- data/docs/reference/why.md +13 -0
- data/docs/topics/authorization.md +155 -0
- data/docs/topics/caching.md +55 -0
- data/docs/topics/customizing-sideloads.md +156 -0
- data/docs/topics/debugging.md +216 -0
- data/docs/topics/error-handling.md +210 -0
- data/docs/topics/etags.md +46 -0
- data/docs/topics/hopping-relationships.md +149 -0
- data/docs/topics/json-attributes.md +77 -0
- data/docs/topics/openstruct-models.md +50 -0
- data/docs/topics/remote-resources.md +291 -0
- data/docs/topics/testing.md +894 -0
- data/docs/topics/without-activerecord.md +324 -0
- data/docs/tutorial/index.md +58 -0
- data/docs/tutorial/step_0.md +107 -0
- data/docs/tutorial/step_1.md +199 -0
- data/docs/tutorial/step_2.md +312 -0
- data/docs/tutorial/step_3.md +142 -0
- data/docs/tutorial/step_4.md +135 -0
- data/docs/tutorial/step_5.md +69 -0
- data/docs/tutorial/step_6.md +82 -0
- data/docs/tutorial/step_7.md +205 -0
- data/docs/tutorial/step_8.md +128 -0
- data/docs/tutorial/step_9.md +171 -0
- data/docs/upgrading.md +265 -0
- data/gemfiles/rails_7_1.gemfile +4 -3
- data/gemfiles/{rails_7_2_graphiti_rails.gemfile → rails_7_2.gemfile} +3 -3
- data/gemfiles/{rails_8_1_graphiti_rails.gemfile → rails_8_0.gemfile} +3 -3
- data/gemfiles/{rails_8_0_graphiti_rails.gemfile → rails_8_1.gemfile} +3 -3
- data/graphiti.gemspec +7 -5
- data/{deprecated_generators → lib/generators}/graphiti/api_test_generator.rb +7 -1
- data/{deprecated_generators → lib/generators}/graphiti/generator_mixin.rb +14 -1
- data/{deprecated_generators → lib/generators}/graphiti/install_generator.rb +19 -13
- data/{deprecated_generators → lib/generators}/graphiti/resource_generator.rb +43 -6
- data/{deprecated_generators → lib/generators}/graphiti/templates/index_request_spec.rb.erb +1 -1
- data/{deprecated_generators → lib/generators}/graphiti/templates/resource_reads_spec.rb.erb +6 -6
- data/{deprecated_generators → lib/generators}/graphiti/templates/show_request_spec.rb.erb +1 -1
- data/lib/graphiti/configuration.rb +2 -2
- data/lib/graphiti/error_serializers/conflict_request.rb +19 -0
- data/lib/graphiti/error_serializers/deprecated_constants.rb +48 -0
- data/lib/graphiti/error_serializers/invalid_request.rb +56 -0
- data/lib/graphiti/error_serializers/validation.rb +143 -0
- data/lib/graphiti/errors.rb +4 -23
- data/lib/graphiti/query.rb +1 -1
- data/lib/graphiti/rails/context.rb +33 -0
- data/lib/graphiti/rails/controller.rb +41 -0
- data/lib/graphiti/rails/debugging.rb +18 -0
- data/lib/graphiti/rails/exception_handlers.rb +77 -0
- data/lib/graphiti/rails/railtie.rb +139 -0
- data/lib/graphiti/rails/responders.rb +21 -0
- data/lib/graphiti/rails/test_helpers.rb +22 -0
- data/lib/graphiti/rails.rb +47 -29
- data/lib/graphiti/resource/configuration.rb +1 -0
- data/lib/graphiti/resource/interface.rb +2 -2
- data/lib/graphiti/resource/persistence.rb +14 -2
- data/lib/graphiti/resource/remote.rb +2 -2
- data/lib/graphiti/resource/sideloading.rb +1 -1
- data/lib/graphiti/resource.rb +13 -1
- data/lib/graphiti/responders.rb +7 -20
- data/lib/graphiti/schema.rb +5 -1
- data/lib/graphiti/schema_diff.rb +4 -0
- data/lib/graphiti/scope.rb +45 -37
- data/lib/graphiti/serializer.rb +6 -0
- data/lib/graphiti/sideload/belongs_to.rb +38 -5
- data/lib/graphiti/sideload/polymorphic_belongs_to.rb +27 -23
- data/lib/graphiti/sideload.rb +54 -35
- data/lib/graphiti/spec_helpers/errors.rb +73 -0
- data/lib/graphiti/spec_helpers/errors_proxy.rb +75 -0
- data/lib/graphiti/spec_helpers/helpers.rb +107 -0
- data/lib/graphiti/spec_helpers/node.rb +88 -0
- data/lib/graphiti/spec_helpers/rspec.rb +147 -0
- data/lib/graphiti/spec_helpers.rb +53 -0
- data/lib/graphiti/util/include_params.rb +2 -2
- data/lib/graphiti/util/persistence.rb +10 -11
- data/lib/graphiti/util/serializer_relationships.rb +41 -5
- data/lib/graphiti/version.rb +1 -1
- data/lib/graphiti-rails.rb +11 -0
- data/lib/graphiti.rb +34 -10
- data/lib/graphiti_errors.rb +11 -0
- data/lib/graphiti_spec_helpers/rspec.rb +3 -0
- data/lib/graphiti_spec_helpers.rb +11 -0
- data/lib/{graphiti/deprecated_tasks.rb → tasks/graphiti.rake} +6 -1
- data/package-lock.json +6199 -0
- data/package.json +5 -4
- data/website/.gitignore +20 -0
- data/website/README.md +43 -0
- data/website/docusaurus.config.js +141 -0
- data/website/package-lock.json +19474 -0
- data/website/package.json +46 -0
- data/website/sidebars.js +82 -0
- data/website/src/css/custom.css +58 -0
- data/website/src/pages/markdown-page.mdx +7 -0
- data/website/static/.nojekyll +0 -0
- data/website/static/1.13/2019/03/31/graphiti-1-0.html +205 -0
- data/website/static/1.13/2019/05/08/graphiti-1-1.html +212 -0
- data/website/static/1.13/2019/05/20/graphiti-1-2.html +214 -0
- data/website/static/1.13/2019/10/14/tutorial.html +198 -0
- data/website/static/1.13/CNAME +1 -0
- data/website/static/1.13/README.md +16 -0
- data/website/static/1.13/assets/css/syntax.css +60 -0
- data/website/static/1.13/assets/favicons/android-chrome-192x192.png +0 -0
- data/website/static/1.13/assets/favicons/android-chrome-256x256.png +0 -0
- data/website/static/1.13/assets/favicons/apple-touch-icon.png +0 -0
- data/website/static/1.13/assets/favicons/browserconfig.xml +9 -0
- data/website/static/1.13/assets/favicons/favicon-16x16.png +0 -0
- data/website/static/1.13/assets/favicons/favicon-32x32.png +0 -0
- data/website/static/1.13/assets/favicons/favicon.ico +0 -0
- data/website/static/1.13/assets/favicons/mstile-150x150.png +0 -0
- data/website/static/1.13/assets/favicons/safari-pinned-tab.svg +1 -0
- data/website/static/1.13/assets/favicons/site.webmanifest +19 -0
- data/website/static/1.13/assets/img/backend.gif +0 -0
- data/website/static/1.13/assets/img/conformity.png +0 -0
- data/website/static/1.13/assets/img/error_payload.png +0 -0
- data/website/static/1.13/assets/img/gh.png +0 -0
- data/website/static/1.13/assets/img/lifecycle.gif +0 -0
- data/website/static/1.13/assets/img/logo-500.png +0 -0
- data/website/static/1.13/assets/img/logo.png +0 -0
- data/website/static/1.13/assets/img/love-graffiti.jpg +0 -0
- data/website/static/1.13/assets/img/meta_total_count.png +0 -0
- data/website/static/1.13/assets/img/persist.jpg +0 -0
- data/website/static/1.13/assets/img/resource.gif +0 -0
- data/website/static/1.13/assets/img/rest-graffiti.jpg +0 -0
- data/website/static/1.13/assets/img/rest1.gif +0 -0
- data/website/static/1.13/assets/img/rest2.gif +0 -0
- data/website/static/1.13/assets/img/rest3.gif +0 -0
- data/website/static/1.13/assets/img/rethink-rest-graffiti.jpg +0 -0
- data/website/static/1.13/assets/img/why.png +0 -0
- data/website/static/1.13/assets/js/highlight.pack.js +2 -0
- data/website/static/1.13/assets/main.css +15518 -0
- data/website/static/1.13/assets/main.css.map +1 -0
- data/website/static/1.13/bin/bundle +109 -0
- data/website/static/1.13/bin/jekyll +27 -0
- data/website/static/1.13/bin/kramdown +27 -0
- data/website/static/1.13/bin/listen +27 -0
- data/website/static/1.13/bin/rake +27 -0
- data/website/static/1.13/bin/rougify +27 -0
- data/website/static/1.13/bin/safe_yaml +27 -0
- data/website/static/1.13/bin/sass +27 -0
- data/website/static/1.13/bin/sass-convert +27 -0
- data/website/static/1.13/bin/scss +27 -0
- data/website/static/1.13/blog.html +259 -0
- data/website/static/1.13/cheatsheet.html +316 -0
- data/website/static/1.13/cookbooks/authorization.md +0 -0
- data/website/static/1.13/cookbooks/caching.md +0 -0
- data/website/static/1.13/cookbooks/customizing-sideloads.html +325 -0
- data/website/static/1.13/cookbooks/etags.md +0 -0
- data/website/static/1.13/cookbooks/hopping-relationships.html +324 -0
- data/website/static/1.13/cookbooks/json_attributes.md +0 -0
- data/website/static/1.13/cookbooks/openstruct-models.md +0 -0
- data/website/static/1.13/cookbooks/remote-resources.md +0 -0
- data/website/static/1.13/cookbooks/without-activerecord.html +510 -0
- data/website/static/1.13/features.html +249 -0
- data/website/static/1.13/feed.xml +106 -0
- data/website/static/1.13/guides/concepts/backends-and-models.html +467 -0
- data/website/static/1.13/guides/concepts/debugging.html +440 -0
- data/website/static/1.13/guides/concepts/endpoints.html +432 -0
- data/website/static/1.13/guides/concepts/error-handling.html +396 -0
- data/website/static/1.13/guides/concepts/links.html +501 -0
- data/website/static/1.13/guides/concepts/remote-resources.html +536 -0
- data/website/static/1.13/guides/concepts/resources.html +2176 -0
- data/website/static/1.13/guides/concepts/testing.html +1469 -0
- data/website/static/1.13/guides/getting-started/installation.html +420 -0
- data/website/static/1.13/guides/graphiti-rails-migration.html +242 -0
- data/website/static/1.13/guides/index.html +269 -0
- data/website/static/1.13/guides/overview.html +325 -0
- data/website/static/1.13/guides/upgrading-2-0.html +193 -0
- data/website/static/1.13/guides/upgrading.html +314 -0
- data/website/static/1.13/guides/vandal.html +282 -0
- data/website/static/1.13/guides/why.html +1121 -0
- data/website/static/1.13/index.html +72 -0
- data/website/static/1.13/js/authentication.html +295 -0
- data/website/static/1.13/js/ddau.html +238 -0
- data/website/static/1.13/js/extra-params.html +270 -0
- data/website/static/1.13/js/index.html +321 -0
- data/website/static/1.13/js/installation.html +637 -0
- data/website/static/1.13/js/introduction.html +257 -0
- data/website/static/1.13/js/middleware.html +318 -0
- data/website/static/1.13/js/reads/fieldsets.html +271 -0
- data/website/static/1.13/js/reads/filtering.html +289 -0
- data/website/static/1.13/js/reads/includes.html +260 -0
- data/website/static/1.13/js/reads/index.html +497 -0
- data/website/static/1.13/js/reads/nested-queries.html +353 -0
- data/website/static/1.13/js/reads/pagination.html +260 -0
- data/website/static/1.13/js/reads/sorting.html +265 -0
- data/website/static/1.13/js/reads/statistics.html +289 -0
- data/website/static/1.13/js/state-syncing.html +340 -0
- data/website/static/1.13/js/writes/deferred.html +296 -0
- data/website/static/1.13/js/writes/dirty-tracking.html +399 -0
- data/website/static/1.13/js/writes/index.html +391 -0
- data/website/static/1.13/js/writes/nested.html +330 -0
- data/website/static/1.13/js/writes/validations.html +272 -0
- data/website/static/1.13/quickstart.html +660 -0
- data/website/static/1.13/template +161 -0
- data/website/static/1.13/tutorial/index.html +250 -0
- data/website/static/1.13/tutorial/step_0.html +292 -0
- data/website/static/1.13/tutorial/step_1.html +517 -0
- data/website/static/1.13/tutorial/step_2.html +481 -0
- data/website/static/1.13/tutorial/step_3.html +323 -0
- data/website/static/1.13/tutorial/step_4.html +318 -0
- data/website/static/1.13/tutorial/step_5.html +265 -0
- data/website/static/1.13/tutorial/step_6.html +276 -0
- data/website/static/1.13/tutorial/step_7.html +390 -0
- data/website/static/1.13/tutorial/step_8.html +316 -0
- data/website/static/1.13/tutorial/step_9.html +365 -0
- data/website/static/assets/img/error_payload.png +0 -0
- data/website/static/assets/img/legacy/legacy-0378a3bb39.png +0 -0
- data/website/static/assets/img/legacy/legacy-05bbd3e5fd.png +0 -0
- data/website/static/assets/img/legacy/legacy-07aa104495.png +0 -0
- data/website/static/assets/img/legacy/legacy-0c75a16b3a.gif +0 -0
- data/website/static/assets/img/legacy/legacy-3076df6209.png +0 -0
- data/website/static/assets/img/legacy/legacy-7f6889bc89.png +0 -0
- data/website/static/assets/img/legacy/legacy-a2cc4363c3.png +0 -0
- data/website/static/assets/img/legacy/legacy-f67cfa89ab.png +0 -0
- data/website/static/assets/img/meta_total_count.png +0 -0
- data/website/static/img/docusaurus-social-card.jpg +0 -0
- data/website/static/img/docusaurus.png +0 -0
- data/website/static/img/favicon.ico +0 -0
- data/website/static/img/logo.png +0 -0
- data/website/static/img/logo.svg +1 -0
- data/website/static/img/undraw_docusaurus_mountain.svg +171 -0
- data/website/static/img/undraw_docusaurus_react.svg +170 -0
- data/website/static/img/undraw_docusaurus_tree.svg +40 -0
- metadata +245 -46
- data/gemfiles/rails_6.gemfile +0 -18
- data/gemfiles/rails_6_graphiti_rails.gemfile +0 -19
- data/gemfiles/rails_7.gemfile +0 -18
- data/gemfiles/rails_7_1_graphiti_rails.gemfile +0 -19
- data/gemfiles/rails_7_graphiti_rails.gemfile +0 -19
- data/lib/graphiti/railtie.rb +0 -121
- /data/{deprecated_generators → lib/generators}/graphiti/resource_test_generator.rb +0 -0
- /data/{deprecated_generators → lib/generators}/graphiti/templates/application_resource.rb.erb +0 -0
- /data/{deprecated_generators → lib/generators}/graphiti/templates/controller.rb.erb +0 -0
- /data/{deprecated_generators → lib/generators}/graphiti/templates/create_request_spec.rb.erb +0 -0
- /data/{deprecated_generators → lib/generators}/graphiti/templates/destroy_request_spec.rb.erb +0 -0
- /data/{deprecated_generators → lib/generators}/graphiti/templates/resource.rb.erb +0 -0
- /data/{deprecated_generators → lib/generators}/graphiti/templates/resource_writes_spec.rb.erb +0 -0
- /data/{deprecated_generators → lib/generators}/graphiti/templates/update_request_spec.rb.erb +0 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
8
|
+
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
|
|
9
|
+
<link href="https://fonts.googleapis.com/css?family=Boogaloo" rel="stylesheet">
|
|
10
|
+
|
|
11
|
+
<link rel="apple-touch-icon" sizes="180x180" href="/1.13/assets/favicons/apple-touch-icon.png">
|
|
12
|
+
<link rel="icon" type="image/png" sizes="32x32" href="/1.13/assets/favicons/favicon-32x32.png">
|
|
13
|
+
<link rel="icon" type="image/png" sizes="16x16" href="/1.13/assets/favicons/favicon-16x16.png">
|
|
14
|
+
<link rel="manifest" href="/1.13/assets/favicons/site.webmanifest">
|
|
15
|
+
<link rel="mask-icon" href="/1.13/assets/favicons/safari-pinned-tab.svg" color="#F86DA7">
|
|
16
|
+
<link rel="shortcut icon" href="/1.13/assets/favicons/favicon.ico">
|
|
17
|
+
<meta name="msapplication-TileColor" content="#F86DA7">
|
|
18
|
+
<meta name="msapplication-config" content="/1.13/assets/favicons/browserconfig.xml">
|
|
19
|
+
<meta name="theme-color" content="#F86DA7">
|
|
20
|
+
|
|
21
|
+
<title>Graphiti</title>
|
|
22
|
+
<meta name="description" content="Stylish Graph APIs">
|
|
23
|
+
|
|
24
|
+
<link rel="stylesheet" href="/1.13/assets/main.css?ref=wh4t3v45">
|
|
25
|
+
<link rel="alternate" type="application/rss+xml" title="Graphiti" href="/1.13/feed.xml">
|
|
26
|
+
|
|
27
|
+
<!-- Global site tag (gtag.js) - Google Analytics -->
|
|
28
|
+
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-127904727-1"></script>
|
|
29
|
+
<script>
|
|
30
|
+
window.dataLayer = window.dataLayer || [];
|
|
31
|
+
function gtag(){dataLayer.push(arguments);}
|
|
32
|
+
gtag('js', new Date());
|
|
33
|
+
|
|
34
|
+
gtag('config', 'UA-127904727-1');
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<!-- javascript -->
|
|
38
|
+
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
|
39
|
+
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
</head>
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
<body>
|
|
46
|
+
<main class="page-content" aria-label="Content">
|
|
47
|
+
<div class="wrapper">
|
|
48
|
+
<header class="navbar navbar-inverse normal" role="banner">
|
|
49
|
+
<div class="container">
|
|
50
|
+
<div class="navbar-header">
|
|
51
|
+
<a href="/1.13/1.13" class="navbar-brand">
|
|
52
|
+
<img alt="logo" src="/1.13/assets/img/logo.png">
|
|
53
|
+
</a>
|
|
54
|
+
</div>
|
|
55
|
+
<nav class="" role="navigation">
|
|
56
|
+
<ul class="nav navbar-nav nav-links">
|
|
57
|
+
<li>
|
|
58
|
+
<a class="quickstart nav-link" href="/1.13/quickstart">Quickstart</a>
|
|
59
|
+
</li>
|
|
60
|
+
<li>
|
|
61
|
+
<a class="guides nav-link" href="/1.13/guides">Guides</a>
|
|
62
|
+
</li>
|
|
63
|
+
<li>
|
|
64
|
+
<a class="tutorial nav-link" href="/1.13/tutorial">Tutorial</a>
|
|
65
|
+
</li>
|
|
66
|
+
<li>
|
|
67
|
+
<a class="spraypaint nav-link" href="/1.13/js">Spraypaint</a>
|
|
68
|
+
</li>
|
|
69
|
+
</ul>
|
|
70
|
+
<ul class="nav gh navbar-nav navbar-right visible-lg visible-md">
|
|
71
|
+
<li>
|
|
72
|
+
<span class="star">⭐</span>
|
|
73
|
+
<a href="https://github.com/graphiti-api/graphiti">
|
|
74
|
+
<img alt="github-star" style="margin-right: 65px;margin-top: -20px" src="/1.13/assets/img/gh.png">
|
|
75
|
+
</a>
|
|
76
|
+
</li>
|
|
77
|
+
</ul>
|
|
78
|
+
</nav>
|
|
79
|
+
</div>
|
|
80
|
+
</header>
|
|
81
|
+
|
|
82
|
+
<div class="container">
|
|
83
|
+
<div class="toc col-md-3">
|
|
84
|
+
<h1 id="tutorial">Tutorial</h1>
|
|
85
|
+
|
|
86
|
+
<ul>
|
|
87
|
+
<li><a href="/1.13/tutorial/step_0">Step 0: Bootstrapping</a></li>
|
|
88
|
+
<li><a href="/1.13/tutorial/step_1">Step 1: Initial Resource</a></li>
|
|
89
|
+
<li><a href="/1.13/tutorial/step_2">Step 2: Has Many</a></li>
|
|
90
|
+
<li><a href="/1.13/tutorial/step_3">Step 3: Belongs To</a></li>
|
|
91
|
+
<li><a href="/1.13/tutorial/step_4">Step 4: Customizing Queries</a></li>
|
|
92
|
+
<li><a href="/1.13/tutorial/step_5">Step 5: Has One</a></li>
|
|
93
|
+
<li><a href="/1.13/tutorial/step_6">Step 6: Customizing Writes</a></li>
|
|
94
|
+
<li><a href="/1.13/tutorial/step_7">Step 7: Many-to-Many</a></li>
|
|
95
|
+
<li><a href="/1.13/tutorial/step_8">Step 8: Polymorphic Relationships</a></li>
|
|
96
|
+
<li><a href="/1.13/tutorial/step_9">Step 9: Polymorphic Resources</a></li>
|
|
97
|
+
</ul>
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
<div class="col-md-8">
|
|
101
|
+
|
|
102
|
+
<h3 id="step-8-polymorphic-relationships">Step 8: Polymorphic Relationships</h3>
|
|
103
|
+
|
|
104
|
+
<blockquote>
|
|
105
|
+
<p><a href="https://github.com/graphiti-api/employee_directory/compare/step_7_many_to_many...step_8_polymorphic_belongs_to">View the Diff</a></p>
|
|
106
|
+
</blockquote>
|
|
107
|
+
|
|
108
|
+
<p>Let’s introduce the concept of a Note. A Note can belong to a
|
|
109
|
+
Department, an Employee, or a Team. For this, we’ll need to introduce
|
|
110
|
+
the concept of <a href="https://guides.rubyonrails.org/v5.2/association_basics.html#polymorphic-associations">polymorphism</a>.</p>
|
|
111
|
+
|
|
112
|
+
<table class="table table-small text-center">
|
|
113
|
+
<thead>
|
|
114
|
+
<tr>
|
|
115
|
+
<th class="text-center">id</th>
|
|
116
|
+
<th class="text-center">notable_id</th>
|
|
117
|
+
<th class="text-center">notable_type</th>
|
|
118
|
+
<th class="text-center">body</th>
|
|
119
|
+
</tr>
|
|
120
|
+
</thead>
|
|
121
|
+
<tbody>
|
|
122
|
+
<tr>
|
|
123
|
+
<td>1</td>
|
|
124
|
+
<td>1</td>
|
|
125
|
+
<td>Employee</td>
|
|
126
|
+
<td>A Sample Note!</td>
|
|
127
|
+
</tr>
|
|
128
|
+
<tr>
|
|
129
|
+
<td>2</td>
|
|
130
|
+
<td>1</td>
|
|
131
|
+
<td>Department</td>
|
|
132
|
+
<td>Another Sample Note!</td>
|
|
133
|
+
</tr>
|
|
134
|
+
<tr>
|
|
135
|
+
<td>3</td>
|
|
136
|
+
<td>1</td>
|
|
137
|
+
<td>Team</td>
|
|
138
|
+
<td>A Third Sample Note!</td>
|
|
139
|
+
</tr>
|
|
140
|
+
</tbody>
|
|
141
|
+
</table>
|
|
142
|
+
|
|
143
|
+
<h3 id="the-rails-stuff-">The Rails Stuff 🚂</h3>
|
|
144
|
+
|
|
145
|
+
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>rails generate model Note notable:references<span class="o">{</span>polymorphic<span class="o">}</span>:index
|
|
146
|
+
<span class="nv">$ </span>bin/rails db:migrate</code></pre></figure>
|
|
147
|
+
|
|
148
|
+
<p>Make sure to add the corresponding model relationships:</p>
|
|
149
|
+
|
|
150
|
+
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1"># app/models/employee.rb</span>
|
|
151
|
+
<span class="n">has_many</span> <span class="ss">:notes</span><span class="p">,</span> <span class="ss">as: :notable</span>
|
|
152
|
+
<span class="c1"># app/models/team.rb</span>
|
|
153
|
+
<span class="n">has_many</span> <span class="ss">:notes</span><span class="p">,</span> <span class="ss">as: :notable</span>
|
|
154
|
+
<span class="c1"># app/models/department.rb</span>
|
|
155
|
+
<span class="n">has_many</span> <span class="ss">:notes</span><span class="p">,</span> <span class="ss">as: :notable</span>
|
|
156
|
+
|
|
157
|
+
<span class="c1"># app/models/note.rb</span>
|
|
158
|
+
<span class="n">belongs_to</span> <span class="ss">:notable</span><span class="p">,</span> <span class="ss">polymorphic: </span><span class="kp">true</span></code></pre></figure>
|
|
159
|
+
|
|
160
|
+
<p>Finally, make sure to edit your seed file - check out the <a href="https://github.com/graphiti-api/employee_directory/compare/step_7_many_to_many...step_8_polymorphic_belongs_to">diff</a> to see the necessary adjustments.</p>
|
|
161
|
+
|
|
162
|
+
<h3 id="the-graphiti-stuff-">The Graphiti Stuff 🎨</h3>
|
|
163
|
+
|
|
164
|
+
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>bin/rails g graphiti:resource Note body:string</code></pre></figure>
|
|
165
|
+
|
|
166
|
+
<p>Let’s create our <code class="language-plaintext highlighter-rouge">NoteResource</code>:</p>
|
|
167
|
+
|
|
168
|
+
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">NoteResource</span> <span class="o"><</span> <span class="no">ApplicationResource</span>
|
|
169
|
+
<span class="n">attribute</span> <span class="ss">:body</span><span class="p">,</span> <span class="ss">:string</span>
|
|
170
|
+
|
|
171
|
+
<span class="n">filter</span> <span class="ss">:notable_id</span><span class="p">,</span> <span class="ss">:integer</span>
|
|
172
|
+
<span class="n">filter</span> <span class="ss">:notable_type</span><span class="p">,</span> <span class="ss">:string</span><span class="p">,</span> <span class="ss">allow: </span><span class="sx">%w(Employee Department Team)</span>
|
|
173
|
+
|
|
174
|
+
<span class="n">polymorphic_belongs_to</span> <span class="ss">:notable</span> <span class="k">do</span>
|
|
175
|
+
<span class="n">group_by</span><span class="p">(</span><span class="ss">:notable_type</span><span class="p">)</span> <span class="k">do</span>
|
|
176
|
+
<span class="n">on</span><span class="p">(</span><span class="ss">:Employee</span><span class="p">)</span>
|
|
177
|
+
<span class="n">on</span><span class="p">(</span><span class="ss">:Team</span><span class="p">)</span>
|
|
178
|
+
<span class="n">on</span><span class="p">(</span><span class="ss">:Department</span><span class="p">)</span>
|
|
179
|
+
<span class="k">end</span>
|
|
180
|
+
<span class="k">end</span>
|
|
181
|
+
<span class="k">end</span></code></pre></figure>
|
|
182
|
+
|
|
183
|
+
<p>And corresponding associations:</p>
|
|
184
|
+
|
|
185
|
+
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1"># app/resources/employee_resource.rb</span>
|
|
186
|
+
<span class="n">polymorphic_has_many</span> <span class="ss">:notes</span><span class="p">,</span> <span class="ss">as: :notable</span>
|
|
187
|
+
<span class="c1"># app/resources/team_resource.rb</span>
|
|
188
|
+
<span class="n">polymorphic_has_many</span> <span class="ss">:notes</span><span class="p">,</span> <span class="ss">as: :notable</span>
|
|
189
|
+
<span class="c1"># app/resources/department_resource.rb</span>
|
|
190
|
+
<span class="n">polymorphic_has_many</span> <span class="ss">:notes</span><span class="p">,</span> <span class="ss">as: :notable</span></code></pre></figure>
|
|
191
|
+
|
|
192
|
+
<h4 id="digging-deeper-">Digging Deeper 🧐</h4>
|
|
193
|
+
|
|
194
|
+
<p>When defining a polymorphic relationship for our API, we’re saying “grab
|
|
195
|
+
all the parent records, group them by a <code class="language-plaintext highlighter-rouge">type</code> column, and execute
|
|
196
|
+
different queries for each type”. This way records with <code class="language-plaintext highlighter-rouge">notable_type ==
|
|
197
|
+
'Employee'</code> can hit the <code class="language-plaintext highlighter-rouge">employees</code> table, but records with
|
|
198
|
+
<code class="language-plaintext highlighter-rouge">notable_type == 'Department'</code> could in theory load from a different API
|
|
199
|
+
altogether.</p>
|
|
200
|
+
|
|
201
|
+
<p>Each of the <code class="language-plaintext highlighter-rouge">on</code> lines defines a new <code class="language-plaintext highlighter-rouge">belongs_to</code> association. That
|
|
202
|
+
means you can customize just like always:</p>
|
|
203
|
+
|
|
204
|
+
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">on</span><span class="p">(</span><span class="ss">:Team</span><span class="p">).</span><span class="nf">belongs_to</span> <span class="ss">:team</span><span class="p">,</span> <span class="ss">resource: </span><span class="no">SomeCustomTeamResource</span> <span class="k">do</span>
|
|
205
|
+
<span class="c1"># assign {}</span>
|
|
206
|
+
<span class="c1"># link {}</span>
|
|
207
|
+
<span class="c1"># ... etc ...</span>
|
|
208
|
+
<span class="k">end</span></code></pre></figure>
|
|
209
|
+
|
|
210
|
+
</div>
|
|
211
|
+
|
|
212
|
+
<div class="clearfix">
|
|
213
|
+
<h2 id="next">
|
|
214
|
+
<a href="/1.13/tutorial/step_9">
|
|
215
|
+
NEXT -
|
|
216
|
+
<small>Step 9: Polymorphic Resources</small>
|
|
217
|
+
»
|
|
218
|
+
</a>
|
|
219
|
+
</h2>
|
|
220
|
+
</div>
|
|
221
|
+
|
|
222
|
+
</div>
|
|
223
|
+
</div>
|
|
224
|
+
</main>
|
|
225
|
+
<div class="main-footer main-footer--dark">
|
|
226
|
+
<div class="container">
|
|
227
|
+
<div class="row">
|
|
228
|
+
<div class="col-sm-4 menu">
|
|
229
|
+
<h3>Overview</h3>
|
|
230
|
+
<ul>
|
|
231
|
+
<li>
|
|
232
|
+
<a href="/1.13/quickstart">Quickstart</a>
|
|
233
|
+
</li>
|
|
234
|
+
<li>
|
|
235
|
+
<a href="/1.13/tutorial">Tutorial</a>
|
|
236
|
+
</li>
|
|
237
|
+
<li>
|
|
238
|
+
<a href="/1.13/guides">Guides</a>
|
|
239
|
+
</li>
|
|
240
|
+
</ul>
|
|
241
|
+
</div>
|
|
242
|
+
<div class="col-sm-4 menu">
|
|
243
|
+
<h3>Contact</h3>
|
|
244
|
+
<ul>
|
|
245
|
+
<li>
|
|
246
|
+
<a target="_blank" href="https://discord.gg/wgqkMBsSRV">Discord Chat</a>
|
|
247
|
+
</li>
|
|
248
|
+
<li>
|
|
249
|
+
<a href="mailto:richmolj@gmail.com">Email</a>
|
|
250
|
+
</li>
|
|
251
|
+
</ul>
|
|
252
|
+
</div>
|
|
253
|
+
<div class="col-sm-4 menu">
|
|
254
|
+
<h3>Related</h3>
|
|
255
|
+
<ul>
|
|
256
|
+
<li>
|
|
257
|
+
<a target="_blank" href="http://jsonapi.org">JSONAPI Spec</a>
|
|
258
|
+
</li>
|
|
259
|
+
<li>
|
|
260
|
+
<a target="_blank" href="http://jsonapi-rb.org">jsonapi-rb</a>
|
|
261
|
+
</li>
|
|
262
|
+
<li>
|
|
263
|
+
<a target="_blank" href="https://vuejs.org/">VueJS</a>
|
|
264
|
+
</li>
|
|
265
|
+
</ul>
|
|
266
|
+
</div>
|
|
267
|
+
</div>
|
|
268
|
+
</div>
|
|
269
|
+
</div>
|
|
270
|
+
|
|
271
|
+
<script type="text/javascript">
|
|
272
|
+
$(function () {
|
|
273
|
+
|
|
274
|
+
var flipTabs = function() {
|
|
275
|
+
var isTS = true;
|
|
276
|
+
if (localStorage.getItem('js-lang') === 'javascript') {
|
|
277
|
+
isTS = false;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
$('.code-tabs').each(function(index, el) {
|
|
281
|
+
if (isTS) {
|
|
282
|
+
console.log('hiding js');
|
|
283
|
+
$($(el).children()[1]).hide();
|
|
284
|
+
$($(el).children()[0]).show();
|
|
285
|
+
} else {
|
|
286
|
+
console.log('hiding ts');
|
|
287
|
+
$($(el).children()[0]).hide();
|
|
288
|
+
$($(el).children()[1]).show();
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
if (isTS) {
|
|
293
|
+
$('.tab.typescript').addClass('active');
|
|
294
|
+
$('.tab.javascript').removeClass('active');
|
|
295
|
+
} else {
|
|
296
|
+
$('.tab.typescript').removeClass('active');
|
|
297
|
+
$('.tab.javascript').addClass('active');
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
$('.tab').click(function() {
|
|
302
|
+
if ($(this).hasClass('typescript')) {
|
|
303
|
+
localStorage.setItem('js-lang', 'typescript');
|
|
304
|
+
} else {
|
|
305
|
+
localStorage.setItem('js-lang', 'javascript');
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
flipTabs();
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
flipTabs();
|
|
312
|
+
})
|
|
313
|
+
</script>
|
|
314
|
+
|
|
315
|
+
</body>
|
|
316
|
+
</html>
|