dato-rails 0.7.4 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cd0388aa8f2f5230feb9b58e501d0d2b32d9a276eccf4029864061ea4fb42745
4
- data.tar.gz: c084383123cfa44fe5834c8eb61e247d8b5482f4ce983bd9f712044e36fe1f5e
3
+ metadata.gz: efcf217eb4b7350ff1b1a431add8314ce1353c01c9ce2d5ffef606a0d91aa3e9
4
+ data.tar.gz: 1006e161f158eff58e2449f43ec8392bd1a6812efe07dfe75b6596af1774f932
5
5
  SHA512:
6
- metadata.gz: 6cde762f15270f855bc106c523e6d428fca9763005b380177852fa990627ccd35445ba6abe8913d76f9899f6c7a30a132a829ef6ac00be2bda9d672faff99299
7
- data.tar.gz: e54d6ac310cc81b0c62f65470e4a2c9ab0333e7ff71e9ca652a83f0ee1e3b9699c4889140cf3a6f8aaae421a3785433deb4eed48b01878ff9cfc5973afb7bbbd
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 automatically used.
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 both [preview](https://www.datocms.com/docs/pro-tips/how-to-manage-a-live-and-a-preview-site) and [live updates](https://www.datocms.com/docs/real-time-updates-api) features from Dato CMS.
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::Live` component like this:
135
+ you can now wrap everything in a `Dato::Wrapper` component like this:
130
136
 
131
137
  ```ruby
132
- render(Dato::Live.new(MyComponent, my_query, preview: true, live: true))
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.publish_key = ENV['DATO_PUBLISH_KEY'] # default: ENV['DATO_PUBLISH_KEY']
222
- config.build_trigger_id = ENV['DATO_BUILD_TRIGGER_ID'] # default: ENV['DATO_BUILD_TRIGGER_ID']
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::Live`, will be cached.
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::Live.new(MyComponent, my_query))
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 also be skipped.
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
- ### manually
280
+ ### manual
256
281
 
257
- executing `Rails.cache.clear(namespace: Dato::Config.cache_namespace)`
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
- * Mount the `dato-rails` engine in your Rails routes file.
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
  [![Clone DatoCMS project](https://dashboard.datocms.com/clone/button.svg)](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, and contributors are expected to
297
- adhere to the [code of conduct](https://github.com/renuo/dato-rails/blob/master/CODE_OF_CONDUCT.md).
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,9 @@
1
+ module Dato
2
+ class BaseComponent < ViewComponent::Base
3
+ attr_reader :data
4
+
5
+ def initialize(data)
6
+ @data = data
7
+ end
8
+ end
9
+ end
@@ -0,0 +1 @@
1
+ <%= render Dato::ResponsiveImage.new(@node.image.responsiveImage) %>
@@ -0,0 +1,2 @@
1
+ class Dato::ImageBlockRecord < Dato::Node
2
+ end
@@ -12,7 +12,7 @@ class Dato::Link < Dato::DastNode
12
12
  def link_attributes
13
13
  attr = {
14
14
  "href" => @node.url,
15
- "class" => "dato-cms-#{@node.type}",
15
+ "class" => "dato-cms-#{@node.type}"
16
16
  }
17
17
  %w[rel target].each { |type| attr[type] = extract_meta(type) }
18
18
  attr
@@ -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
@@ -28,7 +28,7 @@ module Dato
28
28
  private
29
29
 
30
30
  def class_for_block(block)
31
- class_name = (overrides[block.__typename] || Dato::Config.overrides[block.__typename])
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 = (overrides[node.type] || Dato::Config.overrides[node.type])
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
@@ -1,6 +1,6 @@
1
1
  module Dato
2
2
  class LiveController < ActionController::Base
3
- def show
3
+ def create
4
4
  @data = Hashie::Mash.new(JSON.parse(params[:data], symbolize_names: true).dig(:response, :data))
5
5
  end
6
6
  end
@@ -7,7 +7,7 @@ module Dato
7
7
  before_action :check, only: :create
8
8
 
9
9
  def create
10
- Rails.cache.clear(namespace: Dato::Config.cache_namespace)
10
+ Dato::Cache.clear!
11
11
 
12
12
  notify_success
13
13
 
@@ -0,0 +1,7 @@
1
+ <turbo-stream target="<%= params[:frame_id] %>" action="replace" method="morph">
2
+ <template>
3
+ <div id=<%= params[:frame_id] %>>
4
+ <%= render params[:component].constantize.new(@data) %>
5
+ </div>
6
+ </template>
7
+ </turbo-stream>
data/config/routes.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  Dato::Engine.routes.draw do
2
- get "live", to: "live#show"
2
+ post "live", to: "live#create"
3
3
  post "publish", to: "publish#create"
4
4
  end
data/lib/dato/cache.rb CHANGED
@@ -21,5 +21,9 @@ module Dato
21
21
  def self.namespace
22
22
  Dato::Config.cache_namespace
23
23
  end
24
+
25
+ def self.clear!
26
+ Rails.cache.clear(namespace: namespace)
27
+ end
24
28
  end
25
29
  end
data/lib/dato/client.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Dato
2
2
  class Client
3
- delegate :live!, :execute!, :execute, to: :@gql
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["DATO_API_TOKEN"] }
10
- config_accessor(:publish_key) { ENV["DATO_PUBLISH_KEY"] }
11
- config_accessor(:build_trigger_id) { ENV["DATO_BUILD_TRIGGER_ID"] }
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
@@ -0,0 +1,5 @@
1
+ module Dato
2
+ class CurrentRequest < ActiveSupport::CurrentAttributes
3
+ attribute :dato_runtime
4
+ end
5
+ 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,5 @@
1
+ Dato::Fragments::MetaTags = GQLi::DSL.fragment("metaTagsFragment", "Tag") {
2
+ attributes
3
+ content
4
+ tag
5
+ }
@@ -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
- job_id = upload_file_to_dato(upload_id:, attributes:)
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
@@ -1,3 +1,3 @@
1
1
  module Dato
2
- VERSION = "0.7.4"
2
+ VERSION = "0.9.0"
3
3
  end
@@ -1,4 +1,7 @@
1
- # desc "Explaining what the task does"
2
- # task :dato_rails do
3
- # # Task goes here
4
- # end
1
+ namespace :dato do
2
+ namespace :cache do
3
+ task clear: :environment do
4
+ Dato::Cache.clear!
5
+ end
6
+ end
7
+ end
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.7.4
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: 2023-08-16 00:00:00.000000000 Z
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: '4'
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: '4'
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/live.html.erb
192
- - app/components/dato/live.rb
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/show.html.erb
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.3.26
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 %>
@@ -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
@@ -1,3 +0,0 @@
1
- <%= turbo_frame_tag params[:frame_id] do %>
2
- <%= render params[:component].constantize.new(@data) %>
3
- <% end %>