dato-rails 0.7.4 → 0.9.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/README.md +86 -36
- data/app/components/dato/base_component.rb +9 -0
- data/app/components/dato/image_block_record.html.erb +1 -0
- data/app/components/dato/image_block_record.rb +2 -0
- data/app/components/dato/link.rb +1 -1
- data/app/components/dato/live_stream.html.erb +26 -0
- data/app/components/dato/live_stream.rb +35 -0
- data/app/components/dato/node.rb +2 -2
- data/app/components/dato/responsive_image.html.erb +1 -1
- data/app/components/dato/responsive_image.rb +3 -2
- data/app/components/dato/wrapper.html.erb +32 -0
- data/app/components/dato/wrapper.rb +38 -0
- data/app/controllers/dato/live_controller.rb +1 -1
- data/app/controllers/dato/publish_controller.rb +1 -1
- data/app/views/dato/live/create.turbo_stream.erb +7 -0
- data/config/routes.rb +1 -1
- data/lib/dato/cache.rb +4 -0
- data/lib/dato/client.rb +11 -1
- data/lib/dato/config.rb +4 -3
- data/lib/dato/current_request.rb +5 -0
- data/lib/dato/engine.rb +19 -0
- data/lib/dato/fragments/meta_tags.rb +5 -0
- data/lib/dato/railties/controller_runtime.rb +28 -0
- data/lib/dato/uploads.rb +1 -4
- data/lib/dato/version.rb +1 -1
- data/lib/tasks/dato/rails_tasks.rake +7 -4
- metadata +16 -11
- data/app/components/dato/live.html.erb +0 -22
- data/app/components/dato/live.rb +0 -40
- data/app/views/dato/live/show.html.erb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: efcf217eb4b7350ff1b1a431add8314ce1353c01c9ce2d5ffef606a0d91aa3e9
|
4
|
+
data.tar.gz: 1006e161f158eff58e2449f43ec8392bd1a6812efe07dfe75b6596af1774f932
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 40bf39ed3afb39b32d4f3516c4bd795649b4f79eab307b9d9699e262dd91fef7ffc35ced8cf75a2bcf8c2312766d7ef63a00fe8d58235b1c6f942c441a5e4961
|
7
|
+
data.tar.gz: 574dcb125c6539385851c4f0db6aefae191b8d03f7d5695394c4c92f0a7f6a0d86b581e909474c35a7bb4ba5952a0f86f0fe1103811568fffe65eca0d1705511
|
data/README.md
CHANGED
@@ -5,6 +5,7 @@ Use [DatoCMS](https://www.datocms.com/) in your Rails application.
|
|
5
5
|
This gem allows you to fetch data using Dato GraphQL APIs and render the content in your Rails app.
|
6
6
|
|
7
7
|
👉 See [this simple tutorial to get started on dev.to](https://dev.to/coorasse/datocms-with-ruby-on-rails-3ae5). 👈
|
8
|
+
👉 See also [this second tutorial to build a Blog](https://dev.to/coorasse/rails-blog-with-datocms-264j-temp-slug-4336490). 👈
|
8
9
|
|
9
10
|
## Installation
|
10
11
|
|
@@ -31,7 +32,9 @@ queries to the GraphQL endpoint.
|
|
31
32
|
Look at GQLi documentation for more information about the syntax of queries.
|
32
33
|
You can also find some examples in specs of this library.
|
33
34
|
|
34
|
-
Set your api token as `DATO_API_TOKEN` environment variable
|
35
|
+
Set your api token as `DATO_API_TOKEN` environment variable or as
|
36
|
+
`Rails.application.credentials.dig(:dato, :api_token)`.
|
37
|
+
ENV variable will have precedence.
|
35
38
|
|
36
39
|
```ruby
|
37
40
|
client = Dato::Client.new # you can also pass the api token here.
|
@@ -57,7 +60,7 @@ GQLi::DSL.query {
|
|
57
60
|
__typename
|
58
61
|
id
|
59
62
|
image {
|
60
|
-
responsiveImage(imgixParams: {fm: __enum("png")}) {
|
63
|
+
responsiveImage(imgixParams: { fm: __enum("png") }) {
|
61
64
|
___ Dato::Fragments::ResponsiveImage
|
62
65
|
}
|
63
66
|
}
|
@@ -86,7 +89,8 @@ If you have a responsive image, you can render it with:
|
|
86
89
|
render Dato::ResponsiveImage.new(node.image.responsiveImage)
|
87
90
|
```
|
88
91
|
|
89
|
-
To define a custom node, you can create a new `Dato::CustomNode` view component in your application and it will be
|
92
|
+
To define a custom node, you can create a new `Dato::CustomNode` view component in your application and it will be
|
93
|
+
automatically used.
|
90
94
|
|
91
95
|
You can also customize how each node type is rendered by specifying the mapping on the single render:
|
92
96
|
|
@@ -106,7 +110,9 @@ Dato::Config.overrides = {
|
|
106
110
|
|
107
111
|
## Preview and live
|
108
112
|
|
109
|
-
The `Dato::Client` supports
|
113
|
+
The `Dato::Client` supports
|
114
|
+
both [preview](https://www.datocms.com/docs/pro-tips/how-to-manage-a-live-and-a-preview-site)
|
115
|
+
and [live updates](https://www.datocms.com/docs/real-time-updates-api) features from Dato CMS.
|
110
116
|
|
111
117
|
```ruby
|
112
118
|
Dato::Client.new(preview: true) # to fetch draft versions
|
@@ -123,13 +129,13 @@ you probably have the following:
|
|
123
129
|
|
124
130
|
```ruby
|
125
131
|
result = Dato::Client.new.execute!(my_query)
|
126
|
-
render(MyComponent.new(result))
|
132
|
+
render(MyComponent.new(result.data))
|
127
133
|
```
|
128
134
|
|
129
|
-
you can now wrap everything in a `Dato::
|
135
|
+
you can now wrap everything in a `Dato::Wrapper` component like this:
|
130
136
|
|
131
137
|
```ruby
|
132
|
-
render(Dato::
|
138
|
+
render(Dato::Wrapper.new(MyComponent, my_query, preview: true, live: true))
|
133
139
|
```
|
134
140
|
|
135
141
|
and your component will come to life with live updates 🎉 (requires turbo).
|
@@ -170,21 +176,26 @@ Dato::Client.new.items.destroy(item_id: '123')
|
|
170
176
|
|
171
177
|
## File upload
|
172
178
|
|
173
|
-
Dato Rails also supports file uploads.
|
174
|
-
These can be created either from a local file or from a url.
|
179
|
+
Dato Rails also supports file uploads.
|
180
|
+
These can be created either from a local file or from a url.
|
175
181
|
Basically all file types are supported, as long as they are valid in the CMS.
|
182
|
+
Be aware that dato jobs are not synchronous, so you may need to
|
183
|
+
implement some kind of polling to check if the upload is finished.
|
184
|
+
The create method returns a job id, which can be used to retrieve the upload result.
|
176
185
|
|
177
|
-
> In addition to the binary file, also attributes and metadata can be uploaded.
|
178
|
-
Both metadata and attributes are optional.
|
186
|
+
> In addition to the binary file, also attributes and metadata can be uploaded.
|
187
|
+
> Both metadata and attributes are optional.
|
179
188
|
> Provide attributes according to the [docs](https://www.datocms.com/docs/content-management-api/resources/upload)
|
180
189
|
|
181
190
|
### Upload from Url
|
191
|
+
|
182
192
|
```ruby
|
183
193
|
Dato::Client.new.uploads.create_from_url('https://picsum.photos/seed/picsum/200/300')
|
184
194
|
Dato::Client.new.uploads.create_from_url('https://picsum.photos/seed/picsum/200/300', attributes:)
|
185
195
|
```
|
186
196
|
|
187
197
|
### Upload from Local File
|
198
|
+
|
188
199
|
```ruby
|
189
200
|
file = File.open('image.png')
|
190
201
|
|
@@ -200,10 +211,21 @@ attributes = { author: 'Dato Rails', default_field_metadata: meta }
|
|
200
211
|
```
|
201
212
|
|
202
213
|
### Optional: Filename
|
214
|
+
|
203
215
|
```ruby
|
204
216
|
Dato::Client.new.uploads.create_from_url('https://picsum.photos/seed/picsum/200/300', filename: 'test.png')
|
205
217
|
Dato::Client.new.uploads.create_from_file(file.path, filename: 'test.png')
|
218
|
+
```
|
206
219
|
|
220
|
+
### Getting the upload id
|
221
|
+
|
222
|
+
As the file upload is asynchronous, you may need to implement some kind of polling to check if the upload is finished.
|
223
|
+
With the retrieve_job_result method you can retrieve the upload id from the job result.
|
224
|
+
|
225
|
+
```ruby
|
226
|
+
job_id = client.uploads.create_from_file(file.path) # get back a job id
|
227
|
+
response = client.uploads.retrieve_job_result(job_id).parse # check the status
|
228
|
+
upload_id = response.dig('data', 'attributes', 'payload', 'data', 'id') # if nil, it's not done yet
|
207
229
|
```
|
208
230
|
|
209
231
|
## Configuration
|
@@ -218,15 +240,17 @@ Dato::Config.configure do |config|
|
|
218
240
|
config.blocks = {} # default: {}
|
219
241
|
config.cache = false # default: false
|
220
242
|
config.cache_namespace = 'dato-rails' # default: 'dato-rails'
|
221
|
-
config.
|
222
|
-
config.
|
243
|
+
config.api_token = ENV['DATO_PUBLISH_KEY'] # default: ENV.fetch("DATO_API_TOKEN", Rails.application.credentials.dig(:dato, :api_token))
|
244
|
+
config.publish_key = ENV['DATO_PUBLISH_KEY'] # default: ENV.fetch("DATO_PUBLISH_KEY", Rails.application.credentials.dig(:dato, :publish_key))
|
245
|
+
config.build_trigger_id = ENV['DATO_BUILD_TRIGGER_ID'] # default: ENV.fetch("DATO_BUILD_TRIGGER_ID", Rails.application.credentials.dig(:dato, :build_trigger_id))
|
246
|
+
config.mount_path = '/dato' # default: '/dato'
|
223
247
|
end
|
224
248
|
```
|
225
249
|
|
226
250
|
## Caching
|
227
251
|
|
228
252
|
The library supports caching of the rendered components.
|
229
|
-
If you enable caching, the components rendered using `Dato::
|
253
|
+
If you enable caching, the components rendered using `Dato::Wrapper`, will be cached.
|
230
254
|
|
231
255
|
To enable caching, you need to set the `cache` option in the configuration.
|
232
256
|
|
@@ -241,66 +265,92 @@ end
|
|
241
265
|
Now a call to
|
242
266
|
|
243
267
|
```ruby
|
244
|
-
render(Dato::
|
268
|
+
render(Dato::Wrapper.new(MyComponent, my_query))
|
245
269
|
```
|
246
270
|
|
247
|
-
will be cached for 1 day.
|
271
|
+
will be cached for 1 day.
|
248
272
|
|
249
|
-
This means that for the next 24 hours, the graphQL endpoint will not be invoked and the whole component rendering will
|
273
|
+
This means that for the next 24 hours, the graphQL endpoint will not be invoked and the whole component rendering will
|
274
|
+
also be skipped.
|
250
275
|
|
251
276
|
**We will cache the entire HTML result of the component, not only the graphQL response.**
|
252
277
|
|
253
278
|
If you want to expire the cache you have two options:
|
254
279
|
|
255
|
-
###
|
280
|
+
### manual
|
256
281
|
|
257
|
-
executing `
|
282
|
+
executing `Dato::Cache.clear!` or running `bin/rails dato:cache:clear`.
|
258
283
|
|
259
284
|
### publish endpoint
|
260
285
|
|
261
286
|
You can take advantage of the publish mechanism of Dato CMS to expire the cache.
|
262
|
-
|
263
|
-
* Set the `DATO_PUBLISH_KEY` environment variable
|
287
|
+
|
288
|
+
* Set the `DATO_PUBLISH_KEY` environment variable or in Rails Credentials.
|
264
289
|
* Create a build trigger with a custom webhook on your Dato CMS project setting.
|
265
290
|
* Define the Trigger URL as `https://yourapp.com/dato/publish`
|
266
291
|
* Set the `DATO_PUBLISH_KEY` as the Authorization header
|
267
292
|
* Copy the build trigger id and set it as `DATO_BUILD_TRIGGER_ID` environment variable.
|
268
293
|
|
294
|
+
### Caching of graphQL response / Controller helpers
|
295
|
+
|
296
|
+
If you are not using ViewComponents or you need to cache a single GraphQL query, you can still do it using the
|
297
|
+
`Dato::Cache` helper.
|
298
|
+
|
299
|
+
In your controllers you already have a helper method `execute_dato_query`.
|
300
|
+
You can use it in your controller action and queries results will be automatically cached if:
|
301
|
+
|
302
|
+
* You have `Dato` cache enabled
|
303
|
+
* You have Rails cache enabled (check your environment configuration)
|
304
|
+
* you are not displaying a preview
|
305
|
+
|
306
|
+
```ruby
|
307
|
+
response = execute_dato_query(blog_post_query(params[:slug]), preview: params[:preview])
|
308
|
+
@data = response.data
|
309
|
+
```
|
310
|
+
|
311
|
+
by using this helper, subsequent calls towards Dato will be cached.
|
312
|
+
|
313
|
+
## Logs instrumentation
|
314
|
+
|
315
|
+
In the logs you will see the time taken to fetch the data from Dato CMS.
|
316
|
+
For example:
|
317
|
+
|
318
|
+
```
|
319
|
+
Completed 200 OK in 365ms (Views: 109.5ms | ActiveRecord: 0.7ms (4 queries, 0 cached) | Dato: 254.3ms | GC: 0.0ms)`
|
320
|
+
```
|
321
|
+
|
322
|
+
this is useful to identify if the bottleneck is in the fetching of the data from Dato CMS.
|
269
323
|
|
270
324
|
|
271
325
|
## Development
|
272
326
|
|
273
|
-
After checking out the repo, run `bundle install` to install dependencies.
|
327
|
+
After checking out the repo, run `bundle install` to install dependencies.
|
274
328
|
|
275
329
|
You can now clone the dato-rails project
|
276
330
|
|
277
331
|
[](https://dashboard.datocms.com/clone?projectId=57262&name=dato-rails
|
278
332
|
)
|
279
333
|
|
280
|
-
|
281
334
|
You then need to set a `DATO_API_TOKEN=abcd123x` in the `.env` file on the root of your project
|
282
|
-
to consume data from your project.
|
335
|
+
to consume data from your project. For testing purposes, set `TEST_MODEL_TYPE_ID=1234` in the `.env` file
|
336
|
+
with the id of the author model type in your project.
|
283
337
|
|
284
|
-
Then, run `bundle exec rspec` to run the tests.
|
338
|
+
Then, run `bundle exec rspec` to run the tests.
|
285
339
|
|
286
340
|
You can also run `rails console` for an interactive prompt that will allow you to experiment.
|
287
341
|
|
288
|
-
To install this gem onto your local machine, run `bundle exec rake install`.
|
289
|
-
To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`,
|
290
|
-
which will create a git tag for the version, push git commits and the created tag,
|
342
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
343
|
+
To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`,
|
344
|
+
which will create a git tag for the version, push git commits and the created tag,
|
291
345
|
and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
292
346
|
|
293
347
|
## Contributing
|
294
348
|
|
295
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/renuo/dato-rails.
|
296
|
-
This project is intended to be a safe, welcoming space for collaboration
|
297
|
-
|
349
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/renuo/dato-rails.
|
350
|
+
This project is intended to be a safe, welcoming space for collaboration.
|
351
|
+
|
352
|
+
Try to be a decent human being while interacting with other people.
|
298
353
|
|
299
354
|
## License
|
300
355
|
|
301
356
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
302
|
-
|
303
|
-
## Code of Conduct
|
304
|
-
|
305
|
-
Everyone interacting in the Dato::Rails project's codebases, issue trackers, chat rooms and mailing lists is
|
306
|
-
expected to follow the [code of conduct](https://github.com/renuo/dato-rails/blob/master/CODE_OF_CONDUCT.md).
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render Dato::ResponsiveImage.new(@node.image.responsiveImage) %>
|
data/app/components/dato/link.rb
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
<script type="text/javascript">
|
2
|
+
const eventSourceUrl = '<%= data.url %>';
|
3
|
+
const componentKlass = '<%= component_klass %>';
|
4
|
+
const frameId = '<%= frame_id %>';
|
5
|
+
const path = '<%= Dato::Engine.routes.url_helpers.live_path %>';
|
6
|
+
const eventSource = new EventSource(eventSourceUrl);
|
7
|
+
const csrfToken = document.querySelector('meta[name="csrf-token"]').content
|
8
|
+
eventSource.addEventListener("update", (event) => {
|
9
|
+
fetch(path, {
|
10
|
+
method: "POST",
|
11
|
+
headers: {
|
12
|
+
'X-CSRF-Token': csrfToken,
|
13
|
+
'Content-Type': 'application/json',
|
14
|
+
"Accept": "text/vnd.turbo-stream.html"
|
15
|
+
},
|
16
|
+
body: JSON.stringify({
|
17
|
+
component: componentKlass,
|
18
|
+
data: event.data,
|
19
|
+
frame_id: frameId
|
20
|
+
})
|
21
|
+
}).then(response => response.text())
|
22
|
+
.then(html => Turbo.renderStreamMessage(html));
|
23
|
+
});
|
24
|
+
</script>
|
25
|
+
|
26
|
+
<div id=<%= frame_id %>></div>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# This component can bring to life your dato components allowing previews and live updates.
|
2
|
+
# Given that you have a ViewComponent "MyComponent" that renders your page, you can render your page with:
|
3
|
+
# render(MyComponent.new(data_result_from_dato_query))
|
4
|
+
# you can now use this wrapper component to do:
|
5
|
+
# render(Dato::LiveStream.new(MyComponent, query, preview: true)
|
6
|
+
module Dato
|
7
|
+
class LiveStream < ViewComponent::Base
|
8
|
+
delegate :turbo_frame_tag, to: :helpers
|
9
|
+
|
10
|
+
attr_reader :component_klass, :query, :preview
|
11
|
+
|
12
|
+
def initialize(component_klass, query, preview: false)
|
13
|
+
super()
|
14
|
+
@component_klass = component_klass
|
15
|
+
@query = query
|
16
|
+
@preview = preview
|
17
|
+
end
|
18
|
+
|
19
|
+
def data
|
20
|
+
@data ||= dato_fetch(query, preview: preview)
|
21
|
+
end
|
22
|
+
|
23
|
+
def frame_id
|
24
|
+
@frame_id ||= SecureRandom.hex(10)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def dato_fetch(query, preview: false)
|
30
|
+
client = Dato::Client.new(preview: preview, live: true)
|
31
|
+
response = client.live!(query)
|
32
|
+
response.data
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/app/components/dato/node.rb
CHANGED
@@ -28,7 +28,7 @@ module Dato
|
|
28
28
|
private
|
29
29
|
|
30
30
|
def class_for_block(block)
|
31
|
-
class_name =
|
31
|
+
class_name = overrides[block.__typename] || Dato::Config.overrides[block.__typename]
|
32
32
|
if class_name.is_a?(String)
|
33
33
|
class_name = class_name.constantize
|
34
34
|
end
|
@@ -40,7 +40,7 @@ module Dato
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def class_for_node(node)
|
43
|
-
class_name =
|
43
|
+
class_name = overrides[node.type] || Dato::Config.overrides[node.type]
|
44
44
|
if class_name.is_a?(String)
|
45
45
|
class_name = class_name.constantize
|
46
46
|
end
|
@@ -4,7 +4,7 @@
|
|
4
4
|
<picture style="position: absolute; left: 0; top: 0; width: 100%">
|
5
5
|
<source srcset="<%= @node.webpSrcSet %>" type="image/webp">
|
6
6
|
<source srcset="<%= @node.srcSet %>">
|
7
|
-
<img src="<%= @node.src %>" alt="<%= @node.alt %>" title="<%= @node.title %>" loading="lazy" width="100%">
|
7
|
+
<img src="<%= @node.src %>" alt="<%= @node.alt %>" title="<%= @node.title %>" loading="lazy" width="100%" class="<%= @custom_img_css_classes %>">
|
8
8
|
</picture>
|
9
9
|
</div>
|
10
10
|
</div>
|
@@ -1,8 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Dato::ResponsiveImage < Dato::Node
|
4
|
-
def initialize(node, root = nil, custom_css_classes: [])
|
4
|
+
def initialize(node, root = nil, custom_css_classes: [], custom_img_css_classes: [])
|
5
5
|
super(node, root)
|
6
|
-
@custom_css_classes = custom_css_classes
|
6
|
+
@custom_css_classes = custom_css_classes.is_a?(Array) ? custom_css_classes.join(" ") : custom_css_classes
|
7
|
+
@custom_img_css_classes = custom_img_css_classes.is_a?(Array) ? custom_img_css_classes.join(" ") : custom_img_css_classes
|
7
8
|
end
|
8
9
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
<% if live? %>
|
2
|
+
<script type="text/javascript">
|
3
|
+
const eventSourceUrl = '<%= data.url %>';
|
4
|
+
const componentKlass = '<%= component_klass %>';
|
5
|
+
const frameId = '<%= frame_id %>';
|
6
|
+
const path = '<%= Dato::Engine.routes.url_helpers.live_path %>';
|
7
|
+
const eventSource = new EventSource(eventSourceUrl);
|
8
|
+
const csrfToken = document.querySelector('meta[name="csrf-token"]').content
|
9
|
+
eventSource.addEventListener("update", (event) => {
|
10
|
+
fetch(path, {
|
11
|
+
method: "POST",
|
12
|
+
headers: {
|
13
|
+
'X-CSRF-Token': csrfToken,
|
14
|
+
'Content-Type': 'application/json',
|
15
|
+
"Accept": "text/vnd.turbo-stream.html"
|
16
|
+
},
|
17
|
+
body: JSON.stringify({
|
18
|
+
component: componentKlass,
|
19
|
+
data: event.data,
|
20
|
+
frame_id: frameId
|
21
|
+
})
|
22
|
+
}).then(response => response.text())
|
23
|
+
.then(html => Turbo.renderStreamMessage(html));
|
24
|
+
});
|
25
|
+
</script>
|
26
|
+
|
27
|
+
<div id=<%= frame_id %>></div>
|
28
|
+
<% else %>
|
29
|
+
<%= Dato::Cache.fetch(cache_key) do %>
|
30
|
+
<% render(component_klass.new(data)) %>
|
31
|
+
<% end %>
|
32
|
+
<% end %>
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Dato
|
2
|
+
class Wrapper < ViewComponent::Base
|
3
|
+
attr_reader :component_klass, :query, :preview, :live
|
4
|
+
|
5
|
+
def initialize(component_klass, query, preview: false, live: false)
|
6
|
+
@component_klass = component_klass
|
7
|
+
@query = query
|
8
|
+
@preview = preview
|
9
|
+
@live = live
|
10
|
+
end
|
11
|
+
|
12
|
+
def live? = @live
|
13
|
+
|
14
|
+
def render_in(view_context)
|
15
|
+
if live?
|
16
|
+
LiveStream.new(component_klass, query, preview: preview).render_in(view_context)
|
17
|
+
else
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def data
|
23
|
+
@data ||= dato_fetch(query, preview: preview)
|
24
|
+
end
|
25
|
+
|
26
|
+
def cache_key
|
27
|
+
@cache_key ||= Digest::MD5.hexdigest(query.to_gql)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def dato_fetch(query, preview: false)
|
33
|
+
client = Dato::Client.new(preview: preview)
|
34
|
+
response = client.execute!(query)
|
35
|
+
response.data
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/config/routes.rb
CHANGED
data/lib/dato/cache.rb
CHANGED
data/lib/dato/client.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Dato
|
2
2
|
class Client
|
3
|
-
delegate :live!,
|
3
|
+
delegate :live!, to: :@gql
|
4
4
|
attr_reader :items, :uploads, :gql
|
5
5
|
|
6
6
|
def initialize(api_token = Dato::Config.api_token, validate_query: false, preview: false, live: false)
|
@@ -9,5 +9,15 @@ module Dato
|
|
9
9
|
@items = Dato::Items.new(api_token)
|
10
10
|
@uploads = Dato::Uploads.new(api_token)
|
11
11
|
end
|
12
|
+
|
13
|
+
def execute!(query)
|
14
|
+
ActiveSupport::Notifications.instrument("dato.query_execution") do
|
15
|
+
@gql.execute!(query)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def execute(query)
|
20
|
+
@gql.execute(query)
|
21
|
+
end
|
12
22
|
end
|
13
23
|
end
|
data/lib/dato/config.rb
CHANGED
@@ -6,8 +6,9 @@ module Dato
|
|
6
6
|
config_accessor(:blocks) { {} }
|
7
7
|
config_accessor(:cache) { false }
|
8
8
|
config_accessor(:cache_namespace) { "dato-rails" }
|
9
|
-
config_accessor(:api_token) { ENV
|
10
|
-
config_accessor(:publish_key) { ENV
|
11
|
-
config_accessor(:build_trigger_id) { ENV
|
9
|
+
config_accessor(:api_token) { ENV.fetch("DATO_API_TOKEN", Rails.application.credentials.dig(:dato, :api_token)) }
|
10
|
+
config_accessor(:publish_key) { ENV.fetch("DATO_PUBLISH_KEY", Rails.application.credentials.dig(:dato, :publish_key)) }
|
11
|
+
config_accessor(:build_trigger_id) { ENV.fetch("DATO_BUILD_TRIGGER_ID", Rails.application.credentials.dig(:dato, :build_trigger_id)) }
|
12
|
+
config_accessor(:mount_path) { "/dato" }
|
12
13
|
end
|
13
14
|
end
|
data/lib/dato/engine.rb
CHANGED
@@ -1,5 +1,24 @@
|
|
1
1
|
module Dato
|
2
2
|
class Engine < ::Rails::Engine
|
3
3
|
isolate_namespace Dato
|
4
|
+
|
5
|
+
initializer "dato_rails.action_controller" do
|
6
|
+
ActiveSupport.on_load(:action_controller) do
|
7
|
+
include Dato::Railties::ControllerRuntime
|
8
|
+
end
|
9
|
+
|
10
|
+
ActiveSupport::Notifications.subscribe("dato.query_execution") do |_, start, finish, _, _payload|
|
11
|
+
Dato::CurrentRequest.dato_runtime ||= 0
|
12
|
+
Dato::CurrentRequest.dato_runtime += (finish - start) * 1000
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
initializer "dato_rails.configuration" do |app|
|
17
|
+
if Dato::Config.mount_path
|
18
|
+
app.routes.append do
|
19
|
+
mount Dato::Engine => Dato::Config.mount_path
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
4
23
|
end
|
5
24
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Dato
|
2
|
+
module Railties
|
3
|
+
module ControllerRuntime
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
def execute_dato_query(query, preview: false)
|
7
|
+
client = Dato::Client.new(preview: preview)
|
8
|
+
if preview
|
9
|
+
return client.execute!(query)
|
10
|
+
end
|
11
|
+
|
12
|
+
key = "#{Digest::MD5.hexdigest(query.to_gql)}-query-#{preview}"
|
13
|
+
Dato::Cache.fetch(key) do
|
14
|
+
client.execute!(query)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module ClassMethods # :nodoc:
|
19
|
+
def log_process_action(payload)
|
20
|
+
messages = super
|
21
|
+
Dato::CurrentRequest.dato_runtime ||= 0
|
22
|
+
messages << ("Dato: %.1fms" % Dato::CurrentRequest.dato_runtime)
|
23
|
+
messages
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/dato/uploads.rb
CHANGED
@@ -30,10 +30,7 @@ module Dato
|
|
30
30
|
|
31
31
|
upload_file_to_bucket(url: upload_url, path: path_to_file)
|
32
32
|
|
33
|
-
|
34
|
-
upload_id = retrieve_job_result(job_id).parse["data"]["attributes"]["payload"]["data"]["id"]
|
35
|
-
|
36
|
-
{upload_id:}
|
33
|
+
upload_file_to_dato(upload_id:, attributes:)
|
37
34
|
end
|
38
35
|
|
39
36
|
def retrieve_job_result(job_id)
|
data/lib/dato/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dato-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alessandro Rodi
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-01-25 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: rspec-rails
|
@@ -114,14 +113,14 @@ dependencies:
|
|
114
113
|
requirements:
|
115
114
|
- - ">="
|
116
115
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
116
|
+
version: '6'
|
118
117
|
type: :runtime
|
119
118
|
prerelease: false
|
120
119
|
version_requirements: !ruby/object:Gem::Requirement
|
121
120
|
requirements:
|
122
121
|
- - ">="
|
123
122
|
- !ruby/object:Gem::Version
|
124
|
-
version: '
|
123
|
+
version: '6'
|
125
124
|
- !ruby/object:Gem::Dependency
|
126
125
|
name: turbo-rails
|
127
126
|
requirement: !ruby/object:Gem::Requirement
|
@@ -175,6 +174,7 @@ files:
|
|
175
174
|
- README.md
|
176
175
|
- Rakefile
|
177
176
|
- app/assets/config/dato_rails_manifest.js
|
177
|
+
- app/components/dato/base_component.rb
|
178
178
|
- app/components/dato/block.html.erb
|
179
179
|
- app/components/dato/block.rb
|
180
180
|
- app/components/dato/blockquote.html.erb
|
@@ -184,12 +184,14 @@ files:
|
|
184
184
|
- app/components/dato/dast_node.html.erb
|
185
185
|
- app/components/dato/dast_node.rb
|
186
186
|
- app/components/dato/heading.rb
|
187
|
+
- app/components/dato/image_block_record.html.erb
|
188
|
+
- app/components/dato/image_block_record.rb
|
187
189
|
- app/components/dato/link.html.erb
|
188
190
|
- app/components/dato/link.rb
|
189
191
|
- app/components/dato/list.rb
|
190
192
|
- app/components/dato/list_item.rb
|
191
|
-
- app/components/dato/
|
192
|
-
- app/components/dato/
|
193
|
+
- app/components/dato/live_stream.html.erb
|
194
|
+
- app/components/dato/live_stream.rb
|
193
195
|
- app/components/dato/node.rb
|
194
196
|
- app/components/dato/not_rendered.rb
|
195
197
|
- app/components/dato/paragraph.rb
|
@@ -204,18 +206,23 @@ files:
|
|
204
206
|
- app/components/dato/unknown_block.rb
|
205
207
|
- app/components/dato/unknown_node.html.erb
|
206
208
|
- app/components/dato/unknown_node.rb
|
209
|
+
- app/components/dato/wrapper.html.erb
|
210
|
+
- app/components/dato/wrapper.rb
|
207
211
|
- app/controllers/dato/live_controller.rb
|
208
212
|
- app/controllers/dato/publish_controller.rb
|
209
|
-
- app/views/dato/live/
|
213
|
+
- app/views/dato/live/create.turbo_stream.erb
|
210
214
|
- config/routes.rb
|
211
215
|
- lib/dato.rb
|
212
216
|
- lib/dato/cache.rb
|
213
217
|
- lib/dato/client.rb
|
214
218
|
- lib/dato/config.rb
|
219
|
+
- lib/dato/current_request.rb
|
215
220
|
- lib/dato/engine.rb
|
221
|
+
- lib/dato/fragments/meta_tags.rb
|
216
222
|
- lib/dato/fragments/responsive_image.rb
|
217
223
|
- lib/dato/gql.rb
|
218
224
|
- lib/dato/items.rb
|
225
|
+
- lib/dato/railties/controller_runtime.rb
|
219
226
|
- lib/dato/uploads.rb
|
220
227
|
- lib/dato/version.rb
|
221
228
|
- lib/tasks/dato/rails_tasks.rake
|
@@ -225,7 +232,6 @@ metadata:
|
|
225
232
|
homepage_uri: https://github.com/renuo/dato-rails
|
226
233
|
source_code_uri: https://github.com/renuo/dato-rails
|
227
234
|
changelog_uri: https://github.com/renuo/dato-rails/blob/main/CHANGELOG.md
|
228
|
-
post_install_message:
|
229
235
|
rdoc_options: []
|
230
236
|
require_paths:
|
231
237
|
- lib
|
@@ -240,8 +246,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
240
246
|
- !ruby/object:Gem::Version
|
241
247
|
version: '0'
|
242
248
|
requirements: []
|
243
|
-
rubygems_version: 3.
|
244
|
-
signing_key:
|
249
|
+
rubygems_version: 3.6.2
|
245
250
|
specification_version: 4
|
246
251
|
summary: Use Dato CMS in your Rails application.
|
247
252
|
test_files: []
|
@@ -1,22 +0,0 @@
|
|
1
|
-
<% if live %>
|
2
|
-
<script type="text/javascript">
|
3
|
-
const eventSourceUrl = '<%=data.url %>';
|
4
|
-
const componentKlass = '<%=component_klass%>';
|
5
|
-
const frameId = '<%=frame_id%>';
|
6
|
-
const eventSource = new EventSource(eventSourceUrl);
|
7
|
-
eventSource.addEventListener("update", (event) => {
|
8
|
-
const params = new URLSearchParams({
|
9
|
-
component: componentKlass,
|
10
|
-
data: event.data,
|
11
|
-
frame_id: frameId
|
12
|
-
});
|
13
|
-
document.getElementById(frameId).src = `/dato/live?${params.toString()}`;
|
14
|
-
});
|
15
|
-
</script>
|
16
|
-
|
17
|
-
<%= turbo_frame_tag frame_id %>
|
18
|
-
<% else %>
|
19
|
-
<%= Dato::Cache.fetch(cache_key) do %>
|
20
|
-
<% render(component_klass.new(data)) %>
|
21
|
-
<% end %>
|
22
|
-
<% end %>
|
data/app/components/dato/live.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
# This component can bring to life your dato components allowing peviews and live updates.
|
2
|
-
# Given that you have a component MyComponent that renders your page, you can would render your page with:
|
3
|
-
# render(MyComponent.new(@data_result_from_dato_query))
|
4
|
-
# you can now use this wrapper component to do:
|
5
|
-
# render(Dato::Live.new(MyComponent, query, preview: true, live: true)
|
6
|
-
module Dato
|
7
|
-
class Live < ViewComponent::Base
|
8
|
-
delegate :turbo_frame_tag, to: :helpers
|
9
|
-
|
10
|
-
attr_reader :component_klass, :query, :preview, :live
|
11
|
-
|
12
|
-
def initialize(component_klass, query, preview: false, live: false)
|
13
|
-
super()
|
14
|
-
@component_klass = component_klass
|
15
|
-
@query = query
|
16
|
-
@preview = preview
|
17
|
-
@live = live
|
18
|
-
end
|
19
|
-
|
20
|
-
def cache_key
|
21
|
-
@cache_key ||= Digest::MD5.hexdigest(query.to_gql)
|
22
|
-
end
|
23
|
-
|
24
|
-
def data
|
25
|
-
@data ||= dato_fetch(query, preview: preview, live: live)
|
26
|
-
end
|
27
|
-
|
28
|
-
def frame_id
|
29
|
-
@frame_id ||= SecureRandom.hex(10)
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def dato_fetch(query, preview: false, live: false)
|
35
|
-
client = Dato::Client.new(preview: preview, live: live)
|
36
|
-
response = live ? client.live!(query) : client.execute!(query)
|
37
|
-
response.data
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|