para-seo_tools 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a34f864ccd5b3365f87eff521544ce23fe555c6a
4
- data.tar.gz: 98b4747257ce0acd81643e9c0b101e9706fbadb5
3
+ metadata.gz: f4b8959221c49d287170b758d7dbe9a0e2bb291b
4
+ data.tar.gz: 2c9f4d8e455c31bf0f47c7c1cdb1dffdd54a571f
5
5
  SHA512:
6
- metadata.gz: bf073b75a0b537fef122a1cec5614505b1e6e0ca0288f417a917bf68ffe015fd663de442fcde4fdda9d7de28791524e8be8acea01a5f9e0b098f318a5a9a9883
7
- data.tar.gz: 6660839f153d03a48b1957aef6dc1118e8456957d3fc00e8fb729ad015ac921074eaa7c0633fdb6bd9bdd78505e39f5994dec455033bfe38e554150aad3683f3
6
+ metadata.gz: dd129c962571f25f126aeafed737ef17e86fb2e2ef73351bf1b416a4372c4a917f80b41017a614506001a2a2fe26ba829b7108e2675df715fe99015bea4ddc73
7
+ data.tar.gz: 0880f858c0a6db534a542182e456f46f126a2ce4271bef67fc19a7e62297fb1b1330b297b4278db6f435866bc564e280f631fcd71b61816ab1278e75989b1c07
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source 'https://rubygems.org'
1
+ source 'http://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in seo_tools-para.gemspec
4
4
  gemspec
data/README.md CHANGED
@@ -87,6 +87,166 @@ by default.
87
87
  page :posts, priority: 1, change_frequency: 'weekly'
88
88
  ```
89
89
 
90
+ #### Default meta tag values
91
+
92
+ The `page` method allows to define default data for seo_tools to use as default
93
+ values for the title and description meta tags.
94
+
95
+ For example, using your post title as default meta title and its excerpt as the
96
+ default description meta tag value is as easy as :
97
+
98
+ ```ruby
99
+ Posts.find_each do |post|
100
+ page :post, resource: post, defaults: { title: post.title, description: post.excerpt }
101
+ end
102
+ ```
103
+
104
+ #### Arbitrary scoping of pages
105
+
106
+ SeoTools ensures your page identifiers are unique. This avoids duplicating pages
107
+ and unwanted side effects. This identifier is generated with the first argument
108
+ of the `#page` method (`:post` in our examples), and the id of the resource
109
+ passed in the `:resource` argument, when present.
110
+
111
+ For a `:post` with id `25`, this results in an identifier containing :
112
+ `"post:25"`.
113
+
114
+ Sometimes you'll need to have multiple pages that allows accessing a single
115
+ resource, and your identifier would be duplicated. In this case, you can use
116
+ the `:scope` argument, which will allow to create multiple identifiers with
117
+ the same value, scoped to the given arguments.
118
+
119
+ As an example, you can this of posts belonging to multiple categories, which
120
+ would result in a structure where a post could appear under multiple categories.
121
+
122
+ To handle this case, we would write :
123
+
124
+ ```ruby
125
+ Categories.each do |category|
126
+ category.posts.each do |post|
127
+ page :post, resource: post, path: category_post_path(category, post), scope: :category_id, category_id: post.category_id
128
+ end
129
+ end
130
+ ```
131
+
132
+ As a side effect, you can find all "sibling" pages of a given page, allowing
133
+ you to handle canonical URLs or HREFLANG meta tags with ease.
134
+
135
+ #### Batch scoping and params forwarding
136
+
137
+ When you have many pages scoped with the same parameters, you may want to DRY
138
+ out scope params passing to the `#page` method calls.
139
+
140
+ This can be accomplished with the `#with_params` helper method. When used,
141
+ every call to the `#page` method would automatically fetch params passed to the
142
+ `#with_params` method as default params to build or update the underlying page
143
+ object.
144
+
145
+ Below's an example of a situation where you would have a multi-store shop, and
146
+ want to scope all product categories and products pages depending on their
147
+ belonging store, given that some products and categories could exist in multiple
148
+ stores, requiring you to scope them.
149
+
150
+ ```ruby
151
+ Stores.each do |store|
152
+ with_params store_id: store.id, scope: :store_id do
153
+ store.product_categories.each do |product_category|
154
+ page :product_category, resource: product_category
155
+
156
+ product_category.products.each do |product|
157
+ page :product, resource: product
158
+ end
159
+ end
160
+ end
161
+ end
162
+ ```
163
+
164
+ Global skeleton-wide default params can also be passed to the
165
+ `Para::SeoTools::Skeleton.draw` call at the top of the skeleton file :
166
+
167
+ ```ruby
168
+ Para::SeoTools::Skeleton.draw(scope: :store_id) do
169
+ # You code scoped by store_id here
170
+ end
171
+ ```
172
+
173
+ #### Locales support
174
+
175
+ SeoTools comes with multi-locale support built-in. By default, each call to the
176
+ `page` method assigns the current `I18n.locale` to the created page resource.
177
+
178
+ Localized page path handling is dependent on your app logic, but you can easily
179
+ generate pages for each locale.
180
+
181
+ If routing to a specific locale only needs a `:locale` argument passed to your
182
+ URL helpers, and you want to create a page for each available locale, here how
183
+ you'd do it :
184
+
185
+ ```ruby
186
+ Para::SeoTools::Skeleton.draw(scope: :locale) do
187
+ I18n.available_locales.each do |locale|
188
+ I18n.with_locale(locale) do
189
+ Posts.find_each do |post|
190
+ page :post, resource: post, path: post_path(post, locale: locale)
191
+ end
192
+ end
193
+ end
194
+ ```
195
+
196
+ By using `I18n.with_locale`, we force the current locale in the block, and
197
+ SeoTools automatically assigns the locale to the page resource.
198
+
199
+ #### Lazy skeleton building.
200
+
201
+ On large applications, building the skeleton with all its pages at application
202
+ boot time is not an option. You can opt out from this strategy and choose to
203
+ build it yourself from a rake task by using the `Para::SeoTools::Skeleton.draw`
204
+ `:lazy` param and calling the rake task from a CRON or similar job.
205
+
206
+ ```ruby
207
+ Para::SeoTools::Skeleton.draw(lazy: true) do
208
+ # ...
209
+ end
210
+ ```
211
+
212
+ Then use the following rake task :
213
+
214
+ ```bash
215
+ rake seo_tools:skeleton:build
216
+ ```
217
+
218
+ #### Domain and subdomains handling
219
+
220
+ By default, SeoTools doesn't handle specifically domains and subdomains, since
221
+ it stores the page paths with a leading `/`.
222
+
223
+ You can tell it to take those parameters into account when building the
224
+ skeleton, and when fetching data during the request.
225
+
226
+ The first step is to activate one or both of domain and subdomain handling, use
227
+ the `#handle_domain` and `#handle_subdomain` in the para initializer file :
228
+
229
+ ```ruby
230
+ Para.config do |config|
231
+ config.seo_tools do |seo_tools|
232
+ seo_tools.handle_domain = true
233
+ seo_tools.handle_subdomain = true
234
+ end
235
+ end
236
+ ```
237
+
238
+ Then, you need to pass the domain and subdomain as parameters of the `#page`
239
+ call of your skeleton.rb, or with batch params assignation as described above
240
+ [Batch scoping and params forwarding](#batch-scoping-and-params-forwarding)
241
+
242
+ ```ruby
243
+ page :post, resource: post, subdomain: 'blog', domain: 'example.com'
244
+ ```
245
+
246
+ Now, when the page data is fetched during the request, the `request.subdomain`
247
+ and `request.domain` will be used.
248
+
249
+
90
250
  ### 2. Display the meta tags admin panel
91
251
 
92
252
  For the admin panel to display, all you'll need to do is create the component
@@ -103,7 +263,7 @@ section :your_section do
103
263
  end
104
264
  ```
105
265
 
106
- The go to the admin panel, and click the **Sitemap** menu link.
266
+ Then go to the admin panel, and click the **Sitemap** menu link.
107
267
 
108
268
  ### 3. Generate a sitemap.xml
109
269
 
@@ -3,9 +3,16 @@ module Para
3
3
  class Page < ActiveRecord::Base
4
4
  META_TAGS = :title, :description, :keywords, :image, :canonical
5
5
 
6
+ store_accessor :config, :scope
7
+
6
8
  has_attached_file :image, styles: { thumb: '200x200#' }
7
9
  validates_attachment :image, content_type: { content_type: /\Aimage\/.*\Z/ }
8
10
 
11
+ validate :identifier_uniqueness
12
+
13
+ scope :with_subdomain, ->(subdomain) { where("config->>'subdomain' = ?", subdomain) }
14
+ scope :with_domain, ->(domain) { where("config->>'domain' = ?", domain) }
15
+
9
16
  def meta_tag(name)
10
17
  if (value = send(name).presence) && (meta = process(name, value)).present?
11
18
  return meta
@@ -44,6 +51,29 @@ module Para
44
51
  Arel::Nodes::SqlLiteral.new(expr.to_sql)
45
52
  end
46
53
 
54
+ def scope_attributes
55
+ scope.each_with_object({}) do |attribute, hash|
56
+ hash[attribute] = if self.class.column_names.include?(attribute.to_s)
57
+ send(attribute)
58
+ else
59
+ config[attribute.to_s]
60
+ end
61
+ end
62
+ end
63
+
64
+ def sitemap_host
65
+ host = []
66
+ host << config['subdomain'] if Para::SeoTools.handle_subdomain
67
+
68
+ if Para::SeoTools.handle_domain
69
+ host << config['domain']
70
+ else
71
+ host << Para::SeoTools.host
72
+ end
73
+
74
+ host.join('.')
75
+ end
76
+
47
77
  private
48
78
 
49
79
  def process(name, value)
@@ -53,6 +83,23 @@ module Para
53
83
  value
54
84
  end
55
85
  end
86
+
87
+ def identifier_uniqueness
88
+ conditions = PageScoping.new(self).uniqueness_scope_conditions
89
+ conditions = conditions.where.not(id: id) if persisted?
90
+
91
+ if conditions.where(identifier: identifier).exists?
92
+ errors.add(:identifier, :taken)
93
+ end
94
+ end
95
+
96
+ def method_missing(method_name, *args, &block)
97
+ if config.key?(method_name.to_s)
98
+ config[method_name.to_s]
99
+ else
100
+ super
101
+ end
102
+ end
56
103
  end
57
104
  end
58
105
  end
@@ -0,0 +1,5 @@
1
+ class AddConfigToSeoToolsPages < ActiveRecord::Migration
2
+ def change
3
+ add_column :seo_tools_pages, :config, :jsonb
4
+ end
5
+ end
@@ -12,6 +12,7 @@ module Para
12
12
  autoload :Routes
13
13
  autoload :Skeleton
14
14
  autoload :Sitemap
15
+ autoload :PageScoping
15
16
 
16
17
  autoload :MetaTaggable
17
18
  autoload :MetaTaggableMacro
@@ -20,6 +21,12 @@ module Para
20
21
  mattr_writer :host
21
22
  @@host = ENV['APP_DOMAIN']
22
23
 
24
+ mattr_accessor :handle_domain
25
+ @@handle_domain = false
26
+
27
+ mattr_accessor :handle_subdomain
28
+ @@handle_subdomain = false
29
+
23
30
  mattr_accessor :title_methods
24
31
  @@title_methods = %w(title name)
25
32
 
@@ -37,7 +37,11 @@ module Para
37
37
  end
38
38
 
39
39
  def fetch_meta_tags_page
40
- if (page = Para::SeoTools::Page.find_by_path(request.path))
40
+ page_conditions = Para::SeoTools::Page.where(path: request.path)
41
+ page_conditions = page_conditions.with_subdomain(request.subdomain) if Para::SeoTools.handle_subdomain
42
+ page_conditions = page_conditions.with_domain(request.domain) if Para::SeoTools.handle_domain
43
+
44
+ if (page = page_conditions.first)
41
45
  set_meta_tags_from_page(page)
42
46
  end
43
47
  end
@@ -0,0 +1,39 @@
1
+ # Common class used by the Page model and PageBuilder to build and handle
2
+ # pages scoping and building their unique identifiers
3
+ #
4
+ module Para
5
+ module SeoTools
6
+ class PageScoping
7
+ attr_reader :resource
8
+
9
+ def initialize(resource)
10
+ @resource = resource
11
+ end
12
+
13
+ def scoped?
14
+ resource.scope.present?
15
+ end
16
+
17
+ def column?(attribute)
18
+ resource.class.column_names.include?(attribute.to_s)
19
+ end
20
+
21
+ def uniqueness_scope_conditions
22
+ return resource.class unless scoped?
23
+
24
+ resource.scope_attributes.reduce(resource.class) do |query, (attribute, value)|
25
+ if column?(attribute)
26
+ query.where(attribute => value)
27
+ else
28
+ query.where("config->>'#{ attribute }' = ?", value)
29
+ end
30
+ end
31
+ end
32
+
33
+ def unique_identifier
34
+ return resource.identifier unless scoped?
35
+ resource.scope_attributes.merge(identifier: resource.identifier).to_json
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,10 +1,33 @@
1
1
  module Para
2
2
  module SeoTools
3
3
  class Sitemap
4
+ def self.generate!
5
+ puts " * GENERATE SITEMAP ..."
6
+
7
+ build
8
+
9
+ puts " * BUILD ..."
10
+
11
+ ::Sitemap::Generator.instance.build!
12
+
13
+ puts " * SAVE ..."
14
+
15
+ ::Sitemap::Generator.instance.save(path)
16
+
17
+ puts " * SAVED !"
18
+ end
19
+
20
+ def self.path
21
+ @path ||= begin
22
+ root = ::Sitemap.configuration.save_path || ENV["LOCATION"] || Rails.public_path
23
+ File.join(root, "sitemap.xml")
24
+ end
25
+ end
26
+
4
27
  def self.build
5
- ::Sitemap::Generator.instance.load host: Para::SeoTools.host do
28
+ ::Sitemap::Generator.instance.load do
6
29
  Para::SeoTools::Page.find_each do |page|
7
- literal page.path
30
+ literal page.path, host: page.sitemap_host
8
31
  end
9
32
  end
10
33
  end
@@ -4,10 +4,10 @@ module Para
4
4
  extend ActiveSupport::Autoload
5
5
 
6
6
  autoload :Site
7
- autoload :Page
7
+ autoload :PageBuilder
8
8
  autoload :Worker
9
9
 
10
- mattr_accessor :site, :config, :enable_logging
10
+ mattr_accessor :site, :config, :options, :enable_logging
11
11
 
12
12
  def self.with_logging(&block)
13
13
  self.enable_logging = true
@@ -25,18 +25,23 @@ module Para
25
25
  require skeleton_path if File.exists?(skeleton_path)
26
26
  end
27
27
 
28
- def self.draw(lazy: false, &block)
28
+ def self.draw(lazy: false, **options, &block)
29
29
  self.config = block
30
+ self.options = options
30
31
  build unless lazy
31
32
  end
32
33
 
33
- def self.build
34
+ def self.build(load_skeleton: false)
34
35
  return if migrating?
35
36
  return unless ActiveRecord::Base.connection.table_exists?(Para::SeoTools::Page.table_name)
36
37
 
38
+ load if load_skeleton
39
+
37
40
  log " * Building app skeleton pages ..."
38
41
 
39
- self.site = Skeleton::Site.new(enable_logging: enable_logging)
42
+ site_options = options.merge(enable_logging: enable_logging)
43
+ self.site = Skeleton::Site.new(site_options)
44
+
40
45
  # Evaluate the configuration block
41
46
  site.instance_exec(&config)
42
47
 
@@ -1,27 +1,50 @@
1
1
  module Para
2
2
  module SeoTools
3
3
  module Skeleton
4
- class Page
4
+ class ScopeAttributeUndefined < StandardError; end
5
+
6
+ class PageBuilder
5
7
  include Rails.application.routes.url_helpers
6
8
 
7
- attr_reader :name, :resource, :options, :locale
9
+ attr_reader :name, :resource, :locale, :defaults, :config
8
10
 
9
11
  def initialize(name, path: nil, resource: nil, **options)
10
12
  @name = name
11
13
  @path = path
12
14
  @resource = resource
13
- @options = options
14
15
 
15
16
  # Fetch locale on page build to allow calling the `page` skeleton
16
17
  # method inside a `I18n.with_locale` block
17
18
  #
18
- @locale = options.fetch(:locale, I18n.locale)
19
+ @locale = options.delete(:locale) || I18n.locale
20
+ @defaults = options.delete(:defaults) || {}
21
+
22
+ # Remaining options will be stored as config in a JSONB attribute
23
+ @config = options
19
24
  end
20
25
 
21
26
  def identifier
22
27
  @identifier ||= [name, resource.try(:id)].compact.join(':')
23
28
  end
24
29
 
30
+ def scope
31
+ @scope ||= config[:scope]
32
+ end
33
+
34
+ def scope_attributes
35
+ scope.each_with_object({}) do |attribute, hash|
36
+ hash[attribute] = if (value = config[attribute])
37
+ value
38
+ elsif respond_to?(attribute)
39
+ send(attribute)
40
+ else
41
+ raise ScopeAttributeUndefined, "Your Skeleton page is scoped " +
42
+ "with the '#{ attribute }' attribute but you did not pass it " +
43
+ "as a parameter of the #page : #{ inspect }"
44
+ end
45
+ end
46
+ end
47
+
25
48
  def display_name
26
49
  @display_name ||= [name, resource.try(:id)].compact.join(' #').humanize
27
50
  end
@@ -31,18 +54,13 @@ module Para
31
54
  end
32
55
 
33
56
  def model
34
- @model ||= self.class.model_for(identifier).tap do |page|
57
+ @model ||= self.class.model_for(self).tap do |page|
35
58
  # Override path (i.e.: slug changed)
36
59
  page.path = path if path.to_s != page.path
37
60
  page.locale = locale
38
61
  # Do not override meta tags if already present
39
- page.defaults = options[:defaults] || {}
40
- end
41
- end
42
-
43
- def sitemap_options
44
- [:priority, :change_frequency].each_with_object({}) do |param, hash|
45
- hash[param] = options[param] if options.key?(param)
62
+ page.defaults = defaults
63
+ page.config = config
46
64
  end
47
65
  end
48
66
 
@@ -56,15 +74,21 @@ module Para
56
74
  end
57
75
  end
58
76
 
59
- def self.model_for(identifier)
60
- models[identifier] ||= ::Para::SeoTools::Page.new(identifier: identifier)
77
+ def self.model_for(page)
78
+ models[unique_identifier_for(page)] ||= ::Para::SeoTools::Page.new(
79
+ identifier: page.identifier
80
+ )
61
81
  end
62
82
 
63
83
  def self.models
64
84
  @models ||= Para::SeoTools::Page.all.each_with_object({}) do |page, hash|
65
- hash[page.identifier] = page
85
+ hash[unique_identifier_for(page)] = page
66
86
  end
67
87
  end
88
+
89
+ def self.unique_identifier_for(page)
90
+ Para::SeoTools::PageScoping.new(page).unique_identifier
91
+ end
68
92
  end
69
93
  end
70
94
  end
@@ -3,19 +3,29 @@ module Para
3
3
  module Skeleton
4
4
  class Site
5
5
  include Rails.application.routes.url_helpers
6
- attr_reader :enable_logging
6
+ attr_reader :enable_logging, :default_page_options
7
7
 
8
8
  def initialize(options = {})
9
- @enable_logging = options[:enable_logging]
9
+ @enable_logging = options.delete(:enable_logging)
10
+ @default_page_options = options
10
11
  end
11
12
 
12
13
  def page(name, options = {} , &block)
13
- Skeleton::Page.new(name, options).tap do |page|
14
+ options.reverse_merge!(default_page_options)
15
+
16
+ Skeleton::PageBuilder.new(name, options).tap do |page|
14
17
  pages << page
15
18
  save if pages.length == max_pages_before_save
16
19
  end
17
20
  end
18
21
 
22
+ def with_params(params = {}, &block)
23
+ previous_default_page_options = default_page_options
24
+ @default_page_options = default_page_options.dup.merge(params)
25
+ block.call
26
+ @default_page_options = previous_default_page_options
27
+ end
28
+
19
29
  def pages
20
30
  @pages ||= []
21
31
  end
@@ -1,5 +1,5 @@
1
1
  module Para
2
2
  module SeoTools
3
- VERSION = "0.3.0"
3
+ VERSION = "0.4.0"
4
4
  end
5
5
  end
@@ -0,0 +1,22 @@
1
+ namespace :para do
2
+ namespace :seo_tools do
3
+ namespace :skeleton do
4
+ desc "Builds or refreshes the app skeleton."
5
+ task build: :environment do
6
+ Para::SeoTools::Skeleton.build(load_skeleton: true)
7
+ end
8
+ end
9
+
10
+ namespace :sitemap do
11
+ desc "Generates a new sitemap."
12
+ task generate: :environment do
13
+ Para::SeoTools::Sitemap.generate!
14
+ end
15
+
16
+ desc "Ping engines."
17
+ task ping: :environment do
18
+ ::Sitemap::Ping.send_request(Para::SeoTools::Sitemap.path)
19
+ end
20
+ end
21
+ end
22
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: para-seo_tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Valentin Ballestrino
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-27 00:00:00.000000000 Z
11
+ date: 2016-10-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -118,6 +118,7 @@ files:
118
118
  - db/migrate/20150601085253_create_seo_tools_pages.rb
119
119
  - db/migrate/20160610094032_add_meta_tags_to_seo_tools_pages.rb
120
120
  - db/migrate/20160614081242_add_locale_and_remove_meta_tags_list_to_seo_tools_pages.rb
121
+ - db/migrate/20160930064950_add_config_to_seo_tools_pages.rb
121
122
  - lib/generators/para/seo_tools/install/install_generator.rb
122
123
  - lib/generators/para/seo_tools/install/templates/initializer.rb
123
124
  - lib/generators/para/seo_tools/install/templates/skeleton.rb
@@ -138,17 +139,17 @@ files:
138
139
  - lib/para/seo_tools/meta_tags/vendors/base.rb
139
140
  - lib/para/seo_tools/meta_tags/vendors/open_graph.rb
140
141
  - lib/para/seo_tools/meta_tags/vendors/twitter.rb
142
+ - lib/para/seo_tools/page_scoping.rb
141
143
  - lib/para/seo_tools/routes.rb
142
144
  - lib/para/seo_tools/sitemap.rb
143
145
  - lib/para/seo_tools/skeleton.rb
144
- - lib/para/seo_tools/skeleton/page.rb
146
+ - lib/para/seo_tools/skeleton/page_builder.rb
145
147
  - lib/para/seo_tools/skeleton/site.rb
146
148
  - lib/para/seo_tools/skeleton/worker.rb
147
149
  - lib/para/seo_tools/version.rb
148
150
  - lib/para/seo_tools/view_helpers.rb
149
151
  - lib/tasks/migration.rake
150
- - lib/tasks/sitemap.rake
151
- - lib/tasks/skeleton.rake
152
+ - lib/tasks/para_seo_tools_tasks.rake
152
153
  - para-seo_tools.gemspec
153
154
  - test/fixtures/seo_tools/pages.yml
154
155
  - test/models/seo_tools/page_test.rb
@@ -1,17 +0,0 @@
1
- namespace :seo_tools do
2
- namespace :sitemap do
3
- desc "Generates a new sitemap."
4
- task generate: :environment do
5
- Para::SeoTools::Sitemap.build
6
- root = ::Sitemap.configuration.save_path || ENV["LOCATION"] || Rails.public_path
7
- path = File.join(root, "sitemap.xml")
8
- ::Sitemap::Generator.instance.build!
9
- ::Sitemap::Generator.instance.save(path)
10
- end
11
-
12
- desc "Ping engines."
13
- task ping: :environment do
14
- ::Sitemap::Ping.send_request(ENV["LOCATION"])
15
- end
16
- end
17
- end
@@ -1,9 +0,0 @@
1
- namespace :seo_tools do
2
- namespace :skeleton do
3
- desc "Builds or refreshes the app skeleton."
4
- task build: :environment do
5
- Para::SeoTools::Skeleton.load
6
- Para::SeoTools::Skeleton::Worker.perform
7
- end
8
- end
9
- end