RailsアプリケーションでSEO(検索エンジン最適化)やってますか?

  • railsで作ったWebサイトやWebサービスを作ってもサイト訪問者が増えない
  • railsで作ったWebサイトやWebサービスが検索エンジンにヒットしない

これらの課題に対応することをSearch Engine Optimization(略してSEO)といいます。

SEOの手法としてページ毎に見出しタグ(h*)をしっかり書いて構造を明確にしたり、メタタグをきっちり書いたり色々あるのですが、今回はRailsアプリケーションに簡単にメタタグを追加できるプラグインである『meta-tags』を紹介します。

meta-tags

インストール

bundlerで入るのでGemfileに追記します。

Gemfile
1
2
3
4
# SEO
#  - meta-tags
#    - See https://github.com/kpumuk/meta-tags
gem 'meta-tags'

インストールします。

1
bundle install

基本的なメタタグの記述

app/views/layouts/applicatio.html.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  <%= display_meta_tags({
    # title and site are attached, and it's indicated as a title tag.
    #   - site + separator + title
    :separator   => "",
    # title and site are attached reversely.
    #   - title + separator + site
    #   - true/false
    :reverse     => "",
    # page title
    :title       =>  ('SITE TITLE'),
    :site        => "",
    # called meta tags as they are not displayed by the browsers as that of titles.
    #   - Important for SEO
    :description => 'site description',
    # not important for seo, because search engine have not referances keyword meta tags
    :keyword     => '',
    # CSS Device Adaptation
    :viewport    => "width=device-width, 
                     maximum-scale=1.0, 
                     minimum-scale=0.5, 
                     user-scalable=yes, 
                     initial-scale=1.0"
  }) %>

インストール

1
2
3
4
5
cd /tmp
git clone https://github.com/github/hub.git
cd hub/
./script/build
cp hub /usr/local/bin/

gitコマンドをhubコマンドのエイリアスとする

  • いつものgitコマンドをhubコマンドに置き換える
1
2
3
4
5
cat << EOT >> ~/.bash_profile
eval "$(hub alias -s)"
EOT

source ~/.bash_profile

動作確認

which gitを実行するとgitコマンドの実体は/usr/local/bin/hubであることが分かります。

1
2
3
# which git
alias git='hub'
        /usr/local/bin/hub

gitと実行した時にgithub関連のサブコマンドが追加されてます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# git

 .
 .
 .

GitHub Commands:
   pull-request   Open a pull request on GitHub
   fork           Make a fork of a remote repository on GitHub and add as remote
   create         Create this repository on GitHub and add GitHub as origin
   browse         Open a GitHub page in the default browser
   compare        Open a compare page on GitHub
   release        List or create releases (beta)
   issue          List or create issues (beta)
   ci-status      Show the CI status of a commit

See 'git help <command>' for more information on a specific command.

bash-completion用のシェルスクリプトを配置

1
wget -O /etc/bash_completion.d/hub https://raw.githubusercontent.com/github/hub/master/etc/hub.bash_completion.sh

インストール

1
2
3
cd /tmp
wget https://storage.googleapis.com/golang/go1.4.linux-amd64.tar.gz --no-check-certificate
tar -C /usr/local -xzf  go1.4.linux-amd64.tar.gz

環境変数PATHにgoコマンドのパスを通す

1
2
3
cat << EOT >> ~/.bash_profile
export PATH=$PATH:/usr/local/go/bin
EOT

goコマンドのヘルプ

  • goと実行し、以下のように表示されればインストール成功です
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# go
Go is a tool for managing Go source code.

Usage:

        go command [arguments]

The commands are:

    build       compile packages and dependencies
    clean       remove object files
    env         print Go environment information
    fix         run go tool fix on packages
    fmt         run gofmt on package sources
    generate    generate Go files by processing source
    get         download and install packages and dependencies
    install     compile and install packages and dependencies
    list        list packages
    run         compile and run Go program
    test        test packages
    tool        run specified go tool
    version     print Go version
    vet         run go tool vet on packages

Use "go help [command]" for more information about a command.

Additional help topics:

    c           calling between Go and C
    filetype    file types
    gopath      GOPATH environment variable
    importpath  import path syntax
    packages    description of package lists
    testflag    description of testing flags
    testfunc    description of testing functions

Use "go help [topic]" for more information about

ボックス

VagrantではOSを1からインストールしなくて済むようにベースイメージを利用することができます。Vagrantではこのベースイメージのことはボックスと呼びます。ボックスはOSのスナップショットイメージを固めたtarボールです。

ボックスの恩恵

  • 概して30分は要するOSのインストールを省略できる
  • vagrant destroyからvagrant upを繰り返すことが容易(やり直しが容易)にできる
  • OS環境を容易に合わせることができる
  • vagrant packageでオリジナルのボックスを作成できる
    • vagrant upで毎回インストールするミドルウェアなどをインストール済みのボックスを用意することで構築時間を短縮できる

ボックスのダウンロード

1
vagrant box add centos7-x86_64-minimal https://f0fff3908f081cb6461b407be80daf97f07ac418.googledrive.com/host/0BwtuV7VyVTSkUG1PM3pCeDJ4dVE/centos7.box

ボックスの管理

ダウンロード済みのボックスの確認

1
vagrant box list

Vagrantではボックスをユーザ毎にグローバルに管理します。デフォルトでは、~/.vagrant.d/boxes以下にボックスごとに保存されています。

1
2
$ ls  ~/.vagrant.d/boxes/
CentOS-6.5-x86_64 centos7-x86_64-minimal

ボックスの保存先はVAGRANT_HOME環境変数をセットすることで変更可能です。

ボックスの削除

  • 特定のボックスを削除
1
vagrant box remove centos7-x86_64-minimal
  • 特定のプロバイダー用のボックスを削除
1
vagrant box remove --provider virtualbox

コマンド利用するのに補完機能は欠かせない

lsとかcdでタブキーをトントンッと2回叩くとカレントディレクトリ以下のディレクトリやファイル名がリストされますよね。これが補完です。

bashの補完機能はcomplete組み込みコマンドで実現

bashの補完機能は組み込みコマンドのcompleteコマンドで実現しています。completeコマンドはオプションが豊富なので基本的なオプションの使い方のみご紹介します。

  • 全設定の表示
1
2
3
4
5
6
7
8
9
10
11
# complete -p | head
complete -F _kill kill
complete -F _renice renice
complete -F _pgrep pidof
complete -F _postconf postconf
complete -F _java java
complete -F _stream stream
complete -F _update_alternatives alternatives
complete -F _filedir_xspec oodraw
complete -F _filedir_xspec elinks
complete -F _filedir_xspec freeamp
  • lsコマンドの設定のみ表示
1
2
# complete -p ls
complete -o default -F _longopt ls

man completeを見ると情報量が多いので詳細はまた今度確認することにしますが、上記lsコマンドの補完設定の概要は、-o defaultでオプションを指定し、-F _longoptで実行するシェル関数を指定しているようです。_longopt関数に関して興味があればtype -a _longoptを実行してみましょう。

bash-completionをインストールする

bash補完を更に便利にするためにbash-completionをインストールします。

See: https://github.com/GArik/bash-completion
See: https://alioth.debian.org/projects/bash-completion/

RHEL系

1
yum -y install bash-completion

MacOSX

  • Macのbrewで入れたパッケージのインストールプレフィックスは/usr/local
  • デフォルトでは/usr/local/etc/bash_completion設定ファイルが読み込まれないので~/.bash_profileへ追記
1
2
3
4
5
6
7
8
9
10
brew install bash-completion

cat << EOT >> ~/.bash_profile
# bash-completion
if [ -f $(brew --prefix)/etc/bash_completion ]; then
  . $(brew --prefix)/etc/bash_completion
fi
EOT

source ~/.bash_profile

bash-completionだけでは補完されないコマンドの補完

bash-completionでは補完機能を拡張することができます。Macでは/usr/local/etc/bash_completion.dに、RHEL系では/etc/bash_completion.dに拡張ファイルを置き、ログインし直すか~/.bash_profileを再読み込みすることで有効になります。

gitコマンド補完

1
2
wget -O /usr/local/etc/bash_completion.d/git https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash
source ~/.bash_profile

vagrantコマンド補完

1
2
wget -O /usr/local/etc/bash_completion.d/vagrant https://raw.githubusercontent.com/kura/vagrant-bash-completion/master/etc/bash_completion.d/vagrant
source ~/.bash_profile

これは本当に便利!!

Rails4で2つの日時情報を開始日時終了日時という範囲指定をおこなうように実装した時の備忘録です。

bootstrap-datetimepicker-railsのインストール

日時を指定するためのカレンダーをbootstrap3で実装しようと思い、調べたらTrevorS/bootstrap3-datetimepicker-railsというgemライブラリが存在しました。

Gemライブラリのインストール

TrevorS/bootstrap3-datetimepicker-railsをインストールします。

Gemfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# jQuery plugin for drop-in fix binded events problem caused by Turbolinks
gem 'jquery-turbolinks'

# See https://github.com/sstephenson/execjs#readme for more supported runtimes
gem 'therubyracer',  platforms: :ruby

# Install Twitter Bootstrap3
# https://github.com/twbs/bootstrap-sass
gem 'bootstrap-sass', '~> 3.2.0'

# -webkit-border-radius みたいなブラウザベンダープレフィックスをよしなに管理してくれる
# Parse CSS and add vendor prefixes to rules by Can I Use 
# https://twitter.com/autoprefixer
gem 'autoprefixer-rails'

# Istall of bootstrap3-datetimepicker-rails
# See https://github.com/TrevorS/bootstrap3-datetimepicker-rails
gem 'momentjs-rails', '>= 2.8.1'
gem 'bootstrap3-datetimepicker-rails', '~> 3.1.3'

ライブラリをインストールします。

1
bundle install

javascriptライブラリのinclude

app/assets/javascripts/application.jsに以下を追記します。

app/assets/javascripts/application.js
1
2
3
4
5
6
7
8
//= require jquery
//= require jquery.turbolinks
//= require jquery_ujs
//= require bootstrap-sprockets
//= require moment
//= require bootstrap-datetimepicker
//= require turbolinks
//= require_tree .

スタイルシートの読み込み

app/assets/stylesheets/application.css.scssに以下を追記します。

app/assets/stylesheets/application.css.scss
1
2
3
@import "bootstrap-sprockets";
@import "bootstrap";
@import 'bootstrap-datetimepicker';

2つの期間を指定するdatetimepickerを実装

Entryリソースの生成

今回は2つの期間を指定したエントリを保存するためのEntryリソースをscaffoldで生成します。 開始日時をdatetime型start_atアトリビュート、終了日時をdatetime型end_atアトリビュートとして定義しています。

1
2
3
4
5
6
7
8
9
bundle exec rails g scaffold Entry name:string start_at:datetime end_at:datetime description:string
bundle exec rake db:migrate

cat << EOT > config/routes.rb
Rails.application.routes.draw do
  root 'entries#index'
  resources :entries
end
EOT

javascriptの記述

http://eonasdan.github.io/bootstrap-datetimepicker/#example9を参考にしました。

app/views/entries/_form.html.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<script type="text/javascript">
  $(function(){

    // bootstrap-datetimepicker-rails configurations
    //   - references
    //     1. http://eonasdan.github.io/bootstrap-datetimepicker/#options
    //     2. http://shibuso.github.io/datetimepicker_test/datetimepicker_02.html


    // .datepicker_start へのdatetimepicker設定
    $('.datepicker_start').datetimepicker({

      // カレンダー表示言語
      // bootstrap-datetimepicker.ja.js が必要
      //language: 'ja',

      // 月日ピッカーと時間ピッカーを隣に表示する
      //sideBySide: true,

      // 日時フォーマット
      format: 'YYYY-MM-DD HH:mm',

      // 分の選択可能間隔
      minuteStepping: 5,

    });

    // .datepicker_end へのdatetimepicker設定
    $('.datepicker_end').datetimepicker({

      // カレンダー表示言語
      // bootstrap-datetimepicker.ja.js が必要
      //language: 'ja',

      // 月日ピッカーと時間ピッカーを隣に表示する
      //sideBySide: true,

      // 日時フォーマット
      format: 'YYYY-MM-DD HH:mm',

      // 分の選択可能間隔
      minuteStepping: 5,

    });

    // set a minimum date of start_at
    $('.datepicker_start').on("dp.change",function (e) {
      $('.datepicker_end').data("DateTimePicker").setMinDate(e.date);
    });

    // set a maximum date of end_at
    $('.datepicker_end').on("dp.change",function (e) {
      $('.datepicker_start').data("DateTimePicker").setMaxDate(e.date);
    });

  });
</script>

viewの記述(ERB)

app/views/entries/_form.html.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<%= form_for ( @entry ) do |f| %>
  <% if @entry.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@entry.errors.count, "error") %> prohibited this entry from being saved:</h2>

      <ul>
      <% @entry.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="col-sm-8 col-md-8">
    <div class="form-group">
      <%= f.label :name, '名前' %><br>
      <%= f.text_field :name, :class => 'form-control', :placeholder => "エントリーの名前を入力してください..." %>
    </div>
  </div>

  <div class="col-sm-8 col-md-8">
    <div class="form-group">
      <%= f.label :start_at, '開始日時' %><br>
      <div class='input-group datepicker_start'>
        <%= f.text_field :start_at, :class => 'form-control', :readonly => 'true', :placeholder => "開始日時を選択してください..." %>
        <span class="input-group-addon">
          <span class="glyphicon glyphicon-calendar"></span>
        </span>
      </div>
    </div>
  </div>

  <div class="col-sm-8 col-md-8">
    <div class="form-group">
      <%= f.label :end_at, '終了日時' %><br>
      <div class='input-group datepicker_end'>
        <%= f.text_field :end_at, :class => 'form-control', :readonly => 'true', :placeholder => "終了日時を選択してください..." %>
        <span class="input-group-addon">
          <span class="glyphicon glyphicon-calendar"></span>
        </span>
      </div>
    </div>
  </div>

  <div class="col-sm-8 col-md-8">
    <div class="form-group">
      <%= f.label :description, '説明' %><br>
      <%= f.text_field :description, :class => 'form-control', :placeholder => "エントリーの説明を入力してください..." %>
    </div>
  </div>

  <div class="col-sm-8 col-md-8">
    <div class="actions">
      <%= f.submit 'エントリーを作成', :class => 'btn btn-primary' %>
    </div>
  </div>

<% end %>

参考にさせて頂いた情報

http://qiita.com/kidachi_/items/9f76a27890d96b9f5838
http://www.workabroad.jp/posts/974
http://eonasdan.github.io/bootstrap-datetimepicker/#example9

エントリー期間内に複数のイベントを定義できるように実装する

定義したエントリーの中には複数のイベントを持つことができるようにEventリソースを生成します。イベントは食事などのカテゴリーを持つようにしたいのでCategoryリソースを先に生成します。

イベントに付けるカテゴリーのリストを生成する

1
bundle exec rails g scaffold category name:string icon_name:string

イベント用のEventリソースを生成する

1
bundle exec rails g scaffold event entry:references name:string start_at:datetime end_at:datetime description:string category:references
1
bundle exec rake db:migrate

モデルのアソシエーションを記述する

app/models/entry.rb
1
2
3
class Entry < ActiveRecord::Base
  has_many :events
end
app/models/event.rb
1
2
3
4
class Event < ActiveRecord::Base
  belongs_to :entry
  belongs_to :category
end
app/models/category.rb
1
2
3
class Category < ActiveRecord::Base
  has_many :events
end

エントリーの編集ページにイベント作成ページへのリンクを設置

イベントは特定のエントリーに属するのでエントリーの編集画面から追加できるようにします。

1
<%= link_to "#{@entry.name} にイベントを追加", "/events/#{@entry.id}/new" %>

リンクURLがRESTFulなルーティングリソースではないのでconfig/routes.rbにルーティングを追記します。

config/routes.rb
1
2
resources :events
get 'events/:entry_id/new' => 'events#new'

イベント作成ページの`Entry_id`のテキストフィールドにエントリーIDを表示

app/controllers/events_controller.rb
1
2
3
4
5
  # GET /events/:entry_id/new
  def new
    entry_id = params.require(:entry_id)
    @event = Event.new( :entry_id => entry_id )
  end
app/views/events/_form.html.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
<script type="text/javascript">

  $(function(){

    // bootstrap-datetimepicker-rails configurations
    //   - references
    //     1. http://eonasdan.github.io/bootstrap-datetimepicker/#options
    //     2. http://shibuso.github.io/datetimepicker_test/datetimepicker_02.html

    var start_at = new Date( <%= DateTime.parse( @entry.start_at.to_s ).utc.to_i*1000 %> );
    var end_at = new Date( <%= DateTime.parse( @entry.end_at.to_s ).utc.to_i*1000 %> );

    // define datepicker of start_at
    $('.datepicker_start').datetimepicker({

      // カレンダー表示言語
      // bootstrap-datetimepicker.ja.js が必要
      //language: 'ja',

      // 月日ピッカーと時間ピッカーを隣に表示する
      //sideBySide: true,

      // 日時フォーマット
      format: 'YYYY-MM-DD HH:mm',

      // 分の選択可能間隔
      minuteStepping: 5,

      // 選択可能な最小日
      minDate: start_at,

      // 選択可能な最大日
      maxDate: end_at,

    });

    // define datepicker of end_at
    $('.datepicker_end').datetimepicker({

      // カレンダー表示言語
      // bootstrap-datetimepicker.ja.js が必要
      //language: 'ja',

      // 月日ピッカーと時間ピッカーを隣に表示する
      //sideBySide: true,

      // 日時フォーマット
      format: 'YYYY-MM-DD HH:mm',

      // 分の選択可能間隔
      minuteStepping: 5,

      // 選択可能な最小日
      minDate: start_at,

      // 選択可能な最大日
      maxDate: end_at,

    });

  });

</script>

iv class="field">
 |f| %>
  <% if @event.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@event.errors.count, "error") %> prohibited this event from being saved:</h2>

      <ul>
      <% @event.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :entry_id %><br>
    <%= f.text_field :entry_id, :readonly => true %>
  </div>
  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>

  <!-- 開始日時カレンダー -->
  <div class="col-sm-8 col-md-8">
    <div class="form-group">
      <%= f.label :start_at, '開始日時' %><br>
      <div class='input-group datepicker_start'>
        <%= f.text_field :start_at,
                         :value => @entry.start_at,
                         :class => 'form-control',
                         :readonly => 'true',
                         :placeholder => "開始日時を選択してください..." %>

        <!-- glyphicon -->
        <span class="input-group-addon">
          <span class="glyphicon glyphicon-calendar"></span>
        </span>

      </div><!-- /.input-group datepicker_start -->
    </div><!-- /.form-group -->
  </div><!-- /.col-sm .col-md -->

  <!-- 終了日時カレンダー -->
  <div class="col-sm-8 col-md-8">
    <div class="form-group">
      <%= f.label :end_at, '終了日時' %><br>
      <div class='input-group datepicker_end'>
        <%= f.text_field :end_at,
                         :value => @entry.end_at,
                         :class => 'form-control',
                         :readonly => 'true',
                         :placeholder => "終了日時を選択してください..." %>
        <!-- glyphicon -->
        <span class="input-group-addon">
          <span class="glyphicon glyphicon-calendar"></span>
        </span>

      </div><!-- /.input-group datepicker_start -->
    </div><!-- /.form-group -->
  </div><!-- /.col-sm .col-md -->

  <div class="field">
    <%= f.label :description %><br>
    <%= f.text_field :description %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>
<%= f.label :entry_id %><br>
<%= f.text_field :entry_id, :readonly => true %>

“`

変数に値が未セットの場合にのみ任意の文字を代入したい

bashシェルのスクリプトの中で特定の変数に値がセットされていない場合はデフォルト値を代入するということがあります。そこで、変数に値が未セットの場合にのみ特定の値をデフォルト値として代入することができます。

bashには様々な変数の参照方法があるんですが、${変数名:=値}と書くことで、値がセット済みの場合にはその値を返し、未セットの場合には任意の値を返すという動作をします。

1. インタラクティブなシェル上で変数を定義

例えば、$var変数にhelloという値を代入しておき、上記の書き方で値を参照してみます。

1
2
3
4
$ var="hello"

$ echo ${var:="goog morning"}
hello

$var変数を空にしてgoog morningという値を代入してみたいとしましょう。

1
2
3
4
5
6
7
$ var=

$ echo ${var:="goog morning"}
goog morning

$ echo $var
goog morning

${変数名:=値}という書き方をした場合、返り値としてセットした(あるいはセットされている)を返します。その返り値をechoでprintしています。

では、echoさせずに${変数名:=値}だけを実行するとどうでしょう。

1
2
3
4
5
6
7
$ var=

$ ${var:="goog morning"}
-bash: goog morning: コマンドが見つかりません

$ echo $var
goog morning

シェルは返り値をコマンドとして認識するのですが、goog morningなどというコマンドは存在しないのでメッセージが出力されます。しかし、$var変数への値のセットは成功したようです。

echoを使わずに、かつメッセージも出力させないためには以下のように、何もしないというコロン(:)を使う方法があります。

1
2
3
4
5
6
$ var=

$ : ${var:="goog morning"}

$ echo $var
goog morning

2. シェルスクリプト内の変数値にtrue/falseを使用する場合の注意点

シェルスクリプトでset -eを先頭に書いておくことで、スクリプト内のコマンドが失敗を返した場合にはスクリプトを終了させることが出来ます。おまじないのように書いていることがありますが、変数の値ににtrue/falseを使用している場合には注意が必要です。

truefalseはbashシェルの組み込みコマンドとして存在し、その名の通り、trueは真を返し、falseは偽を返します。なので、${var:=false}などと書いているとこの変数定義の行の実行結果は偽を返すことになります。

1
2
3
4
5
6
$ var=

$ ${var:="false"}

$ echo $?
1

シェルスクリプトでset -eとしている場合にはそこでスクリプトが終了してしまい、期待通りに動かない可能性があります。ここでも何もしないというコロン(:)を使用するという方法が有効です。

bash変数を読み込み専用として定義する

bashのビルトインコマンドとしてtypesetdeclareという変数定義に関するコマンドがあります。declareコマンドの-rオプションを使用して定義した変数は読み込み専用となり、以降の変数への値代入が出来なくなります。

試しに、helloという文字列を代入したCONSTANT_VARという変数を読み込み専用として定義してみます。

1
2
3
4
$ declare -r CONSTANT_VAR='hello'

$ echo ${CONSTANT_VAR}
hello

このCONSTANT_VAR変数に新しい値を代入しようと試みたら以下のようなメッセージが出力され変数への代入が失敗します。

1
2
3
4
5
$ CONSTANT_VAR="goot morning"
-bash: CONSTANT_VAR: 読み込みのみの変数

$ echo ${CONSTANT_VAR}
hello

Rails4でアプリケーションを作って、herokuにデプロイした!

もちろんBitbucketでも構わないが、せっかく作ったコードなので公開したい!

でも、config/database.ymlpassword情報やAPIのKey情報なんかをベタ書きしていると他の人に見られてしまう!

そんな時は環境変数を使いましょう!!

見られたくない情報を環境変数に書き換える

http://buf-material-gmap-place-sample.herokuapp.com/なんかでは、Google place APIを利用するためにGoogle API KEYを必要とするコードがあります。その箇所を以下のように書き換えます。

1
@client = GooglePlaces::Client.new( ENV['GOOGLE_API_KEY'] )

ミソはENV['GOOGLE_API_KEY']ですね。こういう感じで環境変数化してしまいます。

herokuに環境変数をセットする

heroku config:setコマンドを使用することでheroku上で環境変数をセットすることが出来ます。

XXXXXXXXXXXXXXXXXXXXXXXXの箇所に実際のKey情報をセットします。また、--app [heroku上のアプリケーション名]も必要です。

1
heroku config:set GOOGLE_API_KEY="XXXXXXXXXXXXXXXXXXXXXXXX" --app buf-material-gmap-place-sample

herokuで複数アカウントを管理し出すとSSH鍵が複数必要です。

herokuに限らずSSH用の鍵を複数使い回す場合は、~/.ssh/configにSSH接続先情報と使用するSSH鍵を紐付ける設定をおこないます。

今回は、herokuにおいて少しハマったので備忘録を残します。

GitHubでも何でも、要は、レポジトリ毎に使用するSSH鍵を変えたい場合に有効かと思います。

SSH鍵を生成

-Cオプションでコメント残して、-fオプションで生成する秘密鍵ファイル名を指定します。公開鍵名は-fオプションで指定したファイル名末尾に.pubが付いたファイル名で生成されます。

1
2
cd ~/.ssh/
ssh-keygen -C "example@example.com" -f id_rsa_heroku_sample_app

SSH接続情報を設定

~/.ssh/configherokuの接続情報を記述します。

~/.ssh/config
1
2
3
4
5
6
Host heroku_sample_app
        HostName heroku.com
        IdentityFile  ~/.ssh/id_rsa_heroku_sample_app
        User git
        IdentitiesOnly yes
        TCPKeepAlive yes

herokuのURL部分を~/.ssh/configと合わせる

gitレポジトリを作成すると.git/configというファイルが作成されます。

heroku apps:createコマンドを実行してherokuアプリケーションを作成した際にherokuというremoteが定義されます。そしてこのherokuというremoteの接続情報が.git/configに書き込まれます。通常、git@heroku.com: レポジトリ名.gitというURLが設定されているはずです。このURLのheroku.comを先ほど~/.ssh/configHostとして付けた名前に書き換えます。

.git/config
1
2
3
4
[remote "heroku"]
        #url = git@heroku.com:heroku_sample_app.git
        url = git@heroku_sample_app:heroku_sample_app.git
        fetch = +refs/heads/*:refs/remotes/heroku/*


これでgit push heroku masterコマンドでherokuへpushする時には~/.ssh/id_rsa_heroku_sample_appというSSH鍵を使用して接続してくれるようになります。