webflow_sync 0.2.5 → 2.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f5541d8efea25526da9e623513853d0b2727c0d473251162cc2db71d729ee3c5
4
- data.tar.gz: 45ffc209e988d291a010618debf173530bdecdb1686caf9a23653214265cd300
3
+ metadata.gz: 3fffb6d06856d3cd1a71f9180fff0753b3cf3396dcfeb1e5ed85d8a01d9ff05e
4
+ data.tar.gz: a18bfeb55b4893dc0f9639d69259760e41d3326cda8096a471fc932534687844
5
5
  SHA512:
6
- metadata.gz: e850f8be00f87fe2ebd9ede70cf0adf9d7cceeb0d02cf4b8afafbdb17472915717017e6d8a632562c80dc5acc460cb0cbcb3c655b08c5046cef323800abe7779
7
- data.tar.gz: 606363c28363aeaf7cd8f3a27859db3a8d5c0db929af486fc0456b27e5ba1ff917d56180e5152a959c337fdc787b016a20335c11dd4ab3ad64c9fec86ef2f800
6
+ metadata.gz: d60c06119a661385dabfff3017fdfe72f3c515b0ba13c208486bff38b2cddc14f40bf5557fe691e5e66215d0f9fe75c7de0a8964e4ca6be725ef61fc3157e626
7
+ data.tar.gz: 981e3169932af0aa8b7a528738d04da9e9a63cb0021c8c2bd6e3386e924384ee7cc3ae4f4840a02a4df95864d2b330755f83eea287d1752547d0124a1c7d192e
data/README.md CHANGED
@@ -36,6 +36,34 @@ Run API token Rails generator and follow instructions:
36
36
  ```bash
37
37
  bundle exec rails generate webflow_sync:api_token_flow
38
38
  ```
39
+ ### Configuration options
40
+
41
+ In `config/initializers/webflow_sync.rb` you can specify configuration options:
42
+
43
+ 1. `api_token`
44
+ 2. `webflow_site_id`
45
+ 3. `skip_webflow_sync` - skip synchronization for different environments
46
+ 4. `sync_webflow_slug` - save slug generated on WebFlow to the Rails database, in the Rails model column.
47
+
48
+ This can be useful if you want to link to WebFlow item directly from your Rails app:
49
+
50
+ ```rb
51
+ link_to('View on site', "https://#{webflow_domain}/articles/#{record.webflow_slug}", target: :blank)
52
+ ```
53
+
54
+ To save slug generated on WebFlow in Rails model, `webflow_slug` column:
55
+
56
+ 1. add `webflow_slug` column on the model table, then
57
+ 2. set the `sync_webflow_slug` option to `true`.
58
+
59
+ Example:
60
+
61
+ ```rb
62
+ WebflowSync.configure do |config|
63
+ config.skip_webflow_sync = ActiveModel::Type::Boolean.new.cast(ENV.fetch('SKIP_WEBFLOW_SYNC'))
64
+ config.sync_webflow_slug = ActiveModel::Type::Boolean.new.cast(ENV.fetch('SYNC_WEBFLOW_SLUG'))
65
+ end
66
+ ```
39
67
 
40
68
  ### Add WebflowSync to models
41
69
 
@@ -8,9 +8,9 @@ module WebflowSync
8
8
  included do
9
9
  attr_accessor :skip_webflow_sync
10
10
 
11
- after_create :create_webflow_item
12
- after_update :update_webflow_item
13
- after_destroy :destroy_webflow_item
11
+ after_commit :create_webflow_item, on: :create
12
+ after_commit :update_webflow_item, on: :update
13
+ after_commit :destroy_webflow_item, on: :destroy
14
14
 
15
15
  def create_webflow_item
16
16
  return if self.skip_webflow_sync || WebflowSync.configuration.skip_webflow_sync
@@ -8,15 +8,41 @@ module WebflowSync
8
8
  @site_id = site_id
9
9
  end
10
10
 
11
- def create_item(record, collection_slug) # rubocop:disable Metrics/MethodLength
11
+ def get_all_items(collection_slug:, page_limit: 100) # rubocop:disable Metrics/MethodLength
12
+ collection_id = find_webflow_collection(collection_slug)['_id']
13
+ max_items_per_page = page_limit # Webflow::Error: 'limit' must be less than or equal to 100
14
+ first_page_number = 1
15
+
16
+ result = make_request(:paginate_items, collection_id, page: first_page_number, per_page: max_items_per_page)
17
+ puts "Get all items from WebFlow for #{collection_slug} page: #{first_page_number}"
18
+
19
+ total_items = result['total']
20
+ total_pages = (total_items.to_f / max_items_per_page).ceil
21
+ items = result['items']
22
+
23
+ (2..total_pages).each do |page_number|
24
+ next_page_items = make_request(:paginate_items, collection_id,
25
+ page: page_number, per_page: max_items_per_page)['items']
26
+ puts "Get all items from WebFlow for #{collection_slug} page: #{page_number}"
27
+
28
+ items.concat next_page_items
29
+ end
30
+
31
+ items
32
+ end
33
+
34
+ def get_item(collection_slug, webflow_item_id)
12
35
  collection = find_webflow_collection(collection_slug)
13
- response = client.create_item(
14
- collection['_id'],
15
- record.as_webflow_json.reverse_merge(_archived: false, _draft: false), live: true
16
- )
17
36
 
18
- # use update_column to skip callbacks to prevent WebflowSync::ItemSync to kick off
19
- if record.update_column(:webflow_item_id, response['_id']) # rubocop:disable Rails/SkipsModelValidations
37
+ make_request(:item, collection['_id'], webflow_item_id)
38
+ end
39
+
40
+ def create_item(record, collection_slug)
41
+ collection = find_webflow_collection(collection_slug)
42
+ response = make_request(:create_item, collection['_id'],
43
+ record.as_webflow_json.reverse_merge(_archived: false, _draft: false), live: true)
44
+
45
+ if update_record_colums(record, response)
20
46
  puts "Created #{record.inspect} in #{collection_slug}"
21
47
  response
22
48
  else
@@ -27,21 +53,31 @@ module WebflowSync
27
53
 
28
54
  def update_item(record, collection_slug)
29
55
  collection = find_webflow_collection(collection_slug)
30
- response = client.update_item(
31
- { '_cid' => collection['_id'], '_id' => record.webflow_item_id },
32
- record.as_webflow_json.reverse_merge(_archived: false, _draft: false), live: true
33
- )
56
+ response = make_request(:update_item, { '_cid' => collection['_id'], '_id' => record.webflow_item_id },
57
+ record.as_webflow_json.reverse_merge(_archived: false, _draft: false), live: true)
58
+
34
59
  puts "Updated #{record.inspect} in #{collection_slug}"
35
60
  response
36
61
  end
37
62
 
38
63
  def delete_item(collection_slug, webflow_item_id)
39
64
  collection = find_webflow_collection(collection_slug)
40
- response = client.delete_item({ '_cid' => collection['_id'], '_id' => webflow_item_id })
65
+ response = make_request(:delete_item, { '_cid' => collection['_id'], '_id' => webflow_item_id })
66
+ # When the item is removed from WebFlow, it's still visible throughout the WebFlow site (probably due to some caching).
67
+ # To remove the item immediately from the WebFlow site, we need to publish the site.
68
+ publish
69
+
41
70
  puts "Deleted #{webflow_item_id} from #{collection_slug}"
42
71
  response
43
72
  end
44
73
 
74
+ def publish
75
+ response = make_request(:publish, site_id, domain_names: domain_names)
76
+
77
+ puts "Publish all domains for Webflow site with id: #{site_id}"
78
+ response
79
+ end
80
+
45
81
  private
46
82
 
47
83
  def client
@@ -52,11 +88,50 @@ module WebflowSync
52
88
  @collections ||= client.collections(site_id)
53
89
  end
54
90
 
91
+ def domain_names
92
+ @domain_names ||= find_domain_names
93
+ end
94
+
95
+ def find_domain_names
96
+ # client.domains request does not return the default domain
97
+ # We need to get default domain name if there are no custom domains set to avoid error:
98
+ # Webflow::Error: Domain not found for site
99
+ site = client.site(site_id)
100
+ default_domain_name = "#{site['shortName']}.webflow.io"
101
+ names = [default_domain_name]
102
+ client.domains(site_id).each { |domain| names << domain['name'] }
103
+
104
+ names
105
+ end
106
+
55
107
  def find_webflow_collection(collection_slug)
56
108
  response = collections.find { |collection| collection['slug'] == collection_slug }
57
109
  raise "Cannot find collection #{collection_slug} for Webflow site #{site_id}" unless response
58
110
 
59
111
  response
60
112
  end
113
+
114
+ def update_record_colums(record, response)
115
+ # use update_column to skip callbacks to prevent WebflowSync::ItemSync to kick off
116
+ if WebflowSync.configuration.sync_webflow_slug
117
+ record.update_columns(webflow_item_id: response['_id'], webflow_slug: response['slug']) # rubocop:disable Rails/SkipsModelValidations
118
+ else
119
+ record.update_column(:webflow_item_id, response['_id']) # rubocop:disable Rails/SkipsModelValidations
120
+ end
121
+ end
122
+
123
+ def make_request(method_name, *args, retries: 0, **kwargs)
124
+ if kwargs.present?
125
+ client.public_send(method_name, *args, **kwargs)
126
+ else
127
+ client.public_send(method_name, *args)
128
+ end
129
+ rescue Webflow::Error => e
130
+ raise if retries >= 8 || e.message.strip != 'Rate limit hit'
131
+
132
+ puts "Sleeping #{2**retries} seconds"
133
+ sleep 2**retries
134
+ make_request(method_name, *args, retries: retries + 1, **kwargs)
135
+ end
61
136
  end
62
137
  end
@@ -4,4 +4,5 @@ WebflowSync.configure do |config|
4
4
  # config.api_token = ENV.fetch('WEBFLOW_API_TOKEN')
5
5
  # config.skip_webflow_sync = Rails.env.test? # default
6
6
  config.webflow_site_id = ENV.fetch('WEBFLOW_SITE_ID')
7
+ config.sync_webflow_slug = ENV.fetch('SYNC_WEBFLOW_SLUG')
7
8
  end
@@ -18,7 +18,7 @@ module WebflowSync
18
18
  end
19
19
 
20
20
  class Configuration
21
- attr_accessor :skip_webflow_sync, :webflow_site_id
21
+ attr_accessor :skip_webflow_sync, :webflow_site_id, :sync_webflow_slug
22
22
  attr_reader :api_token
23
23
 
24
24
  def api_token=(value)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WebflowSync
4
- VERSION = '0.2.5'
4
+ VERSION = '2.0.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: webflow_sync
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Viktor
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-22 00:00:00.000000000 Z
11
+ date: 2021-06-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -173,7 +173,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
173
173
  - !ruby/object:Gem::Version
174
174
  version: '0'
175
175
  requirements: []
176
- rubygems_version: 3.2.3
176
+ rubygems_version: 3.0.9
177
177
  signing_key:
178
178
  specification_version: 4
179
179
  summary: Keep Rails models in sync with WebFlow.