Railsでsitemapを自動で生成して定期的にsitemapを自動更新するようにする

勉強もかねて自分の[ブログ](http://tackeyy.com/)をrailsで作って運用しています。
せっかくなのでSEO対策をしようと思い、[sitemap_generator](https://github.com/kjvarga/sitemap_generator)でsitemapを作成して定期的にsitemapを最新にする仕組みを導入してみました。

sitemap_generatorについて記載された記事はいくつもあるのですが、実際に触ってみるとそれらの記事では足りない部分や調べたことが多々あったため、それをまとめてみます。

# この記事で紹介すること

sitemap_generatorを利用して、

- sitemapを作成する方法
- デプロイフローの中でsitemapを自動作成する方法
- 定期的にsitemapを自動で更新する方法

# 動作環境

```
Rails 5.0.2
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin16]
```

# 使用するGems

- [sitemap_generator](https://github.com/kjvarga/sitemap_generator)
  - その名の通りsitemapを生成するためのGemです。

- [whenever](https://github.com/javan/whenever)
  - ActiveJobのような記述でサーバー上のcronの設定を簡単に行えるGemです。今回はsitemap_generatorを定期的に実行するために使用します。

# sitemapを作成する方法

## Gemをインストール

Gemfileに追記して ` bundle install ` します。

```
# Site map
gem 'sitemap_generator'
```

## sitemap.rbを作成

gemのインストールができたら以下のコマンドでsitemap.rbを作成します。

` gem install sitemap_generator `

生成されたsitemap.rbにはこんな感じで自分のサイトの情報を記載してください。
今回の場合は私の[ブログ](http://tackeyy.com/)なので、トップページやカテゴリー、各ポストをsitemapに追加するための設定をします。

```
# Set the host name for URL creation
SitemapGenerator::Sitemap.default_host = Settings.url

SitemapGenerator::Sitemap.create do
  add root_path            # root_pathをsitemapに追加する
  add categories_path 　　　　　　　　　　# categories_pathをsitemapに追加する

  # 各投稿をsitemapに追加する
  Post.shipped.each do |post|
    add blog_path(post.friendly_id), lastmod: post.updated_at
  end
end
```

オプションは以下から確認できます。
https://github.com/kjvarga/sitemap_generator#a-simple-example


## sitemap.rbからsitemapを作成

sitemap.rbを記載したらsitemapがきちんと生成されるかどうかを確認するために以下のコマンドでsitemapを作成します。

` rake sitemap:create `

こんな感じのログがコンソールに表示されればOKです。

```
In '/Users/tackeyy/dev/blog/public/':
+ sitemap.xml.gz                                           1 links /  325 Bytes
Sitemap stats: 1 links / 1 sitemaps / 0m00s
```

### sitemapを作成するコマンド

| コマンド|どういう時に使えば良いか|
| --- | --- |
| rake sitemap:create | sitemapの作成を行いたい時 |
| rake sitemap:refresh | sitemapの作成してサーチエンジンにsitemapを更新したことを通知したい時 |
| rake sitemap:clean |sitemapを削除したい時  |

READMEでは以下にコマンドの説明があります。
https://github.com/kjvarga/sitemap_generator#deployments--capistrano

` rake sitemap:refresh ` には ` no_ping ` というオプションがあります。
` rake sitemap:refresh ` だとサーチエンジンに通知をしてしまいますが、  ` rake sitemap:refresh:no_ping ` を使えば通知を無効にできます。


# デプロイフローの中でsitemapを自動作成する方法

sitemapを作成できても毎回productionで ` rake sitemap:refresh RAILS_ENV=production ` を実行しないといけません。
ちょっとこれはだるいのでデプロイフローでsitemapを作成するようにします。

```
Capfile
+require 'whenever/capistrano'
```

```config/deploy.rb
+after 'deploy:restart', 'deploy:sitemap'

namespace :deploy do
(省略)
 +  desc 'Generate sitemap'
 +  task :sitemap do
 +    on roles(:app) do
 +      within release_path do
 +        execute :bundle, :exec, :rake, 'sitemap:create RAILS_ENV=production'
 +      end
 +    end
 +  end
（省略）
```

deploy.rbを見ないとわかりにくいと思うので、こちらの[コミット](https://github.com/tackeyy/blog/commit/e2fbb1340925b6d7a0baeb63838fc1ec09f87834#diff-6dc906be0643182e5bae6aa1506221e6
)も合わせて見ていただくとわかりやすいと思います。

これでcapistranoでデプロイするとsitemapも作成されるようになります。


# 定期的にsitemapを自動で更新する方法

## wheneverをインストール

Gemfileを記載してbundle installします。

```
 +# Manage crontab
 +gem 'whenever', require: false
```

## config/schedule.rbの設定

config/schedule.rbを作成します。
（wheneverのコマンドもありますが、ファイル作成だけなので手動でOKです）

```config/schedule.rb
 +set :output, 'log/crontab.log'
 +
 +every 1.week , roles: %i(app) do
 +  rake '-s sitemap:refresh'
 +end
```

## cronが設定できているかを確認

productionにデプロイした後にcronの設定を確認してみます。

` crontab -l ` でこのように出力されればOKです。

```
# Begin Whenever generated tasks for: blog_production
0 0 1,8,15,22 * * /bin/bash -l -c 'cd /var/www/blog/releases/20170429160844 && RAILS_ENV=production bundle exec rake -s sitemap:refresh --silent >> log/crontab.log 2>&1'

# End Whenever generated tasks for: blog_production
```

# SearchConsoleがsitemapを認識できているか確認

最後は念のためSearchConsoleでsitemapがちゃんと読み込めているか確認します。

[![https://gyazo.com/a8278ceaba2de06f9d7517b1a29a24f3](https://i.gyazo.com/a8278ceaba2de06f9d7517b1a29a24f3.png)](https://gyazo.com/a8278ceaba2de06f9d7517b1a29a24f3)

サイトマップがちゃんと読み込めているところまで確認できました。

# その他

` cap production deploy ` で ` bash: bundle: command not found ` などが出たりする場合は、
以下の記事を参考にしてみてください。

http://qiita.com/zaru/items/348c126a205a2e48b4d6
http://stackoverflow.com/questions/9482298/rails-cron-whenever-bundle-command-not-found

# 参考

基本的にはこことREADMEを参考にしました。
http://morizyun.github.io/blog/meta-tags-sitemap-generator-rails-seo/
https://github.com/kjvarga/sitemap_generator#sitemapgenerator