PostgreSQLを使ったRoRをGitHubからJenkinsを通してHerokuまで

参考をそのまま試した備忘ログ のCentOS and PostgreSQLを使用版

JenkinsもVPS上にやってるので最終的にはHerokuへの自動デプロイまでやったことの流れ (ついでに勉強したことのノート)

環境

  • CentOS 6.5
  • ruby 2.0.0dev
  • rails 4.0.2
  • postgreSQL 9.3

以上の環境が既に整ってることが前提

1. アプリの作成

1.1 rails new

1
$ rails new my_circle --database=postgresql --skip-test-unit --skip-bundle

Note : --database=postgresql == -d postgresql

—database=postgresqlオプションを入れた時と入れない時の違いは結構あるので注意

rails new project -d postgresql を指定した時に変更される部位

Note : --skip-test-unit == -T

標準だとTest::Unitというテスティングフレームワークが使用される(RSpecを使用したい)

Note : --skip-bundle

bundle installを行わない

どうせあとでちょっといじってまたbundle installする

そのままだと ‘autodetect’: Could not find a JavaScript runtime. See https://github.com/sstephenson/execjs for a list of available runtimes. (ExecJS::RuntimeUnavailable) と出る

1
2
3
4
5
6
7
8
9
$ vim Gemfile

Before
#gem 'therubyracer', :platforms => :ruby

After
gem 'therubyracer', :platforms => :ruby

$ bundle install

1.1 postgresの方でuserとDBの作成

1
2
$ createuser my_circle -s
$ createdb my_circle_development -O my_circle

createuser の -s/-Sオプション

スーパーユーザとして追加される

createdb の -Oオプション

新しいDBの所有者となるDBUserを指定

1.2 userメンテ画面をscaffold機能を使用して作成

1
$ rails g scaffold user name:string age:integer

1.3 DBの作成 & テスト用DBの作成

1
2
$ rake db:migrate
$ rake db:test:clone

1.4 確認

1
$ rails s

localhost:3000/users

  • rails s -pXXXX でポート番号を指定可能

2. RSpecのセットアップ

1
2
3
4
5
6
$ vim Gemfile

# 以下を追記
group :development, :test do
  gem 'rspec-rails', '~> 2.0'
end
1
2
$ bundle install
$ rails generate rspec:install

rails generate rspec:install

RSpecをセットアップするためのコマンド

これで、プロジェクトディレクトリの下にspecディレクトリができたのが確認可能(他には.spec等)

2.1 RSpecの出力フォーマットをドキュメント形式に変更

1
2
3
4
5
6
7
$ vim .rspec

Before
--color

After
--color --format documentation

3. アプリケーションの修正とユニットテストの作成

3.1 Userモデルに対してバリデーションの追加

1
2
3
4
5
6
7
8
9
10
11
$ vim app/models/user.rb

# 必須入力 && 最大文字数が20
  validates :name,
    :presence => true,
    :length => {:maximum => 20}
# 必須入力 && 入力値が0 - 1000の間
  validates :age,
    :presence => true,
    :numericality => {:greater_than_or_equal_to => 0,
    :less_than_or_equal_to => 1000}

3.2 バリデーションをテストするコード

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
$ mkdir spec/models
$ vim spec/models/user_spec.rb

# -*- coding: utf-8 -*-
require 'spec_helper'

describe User do
  context '何も入力しなかった場合' do
    subject{User.new}
    it { should_not be_valid }
    it { should have(1).errors_on(:name) }
    it { should have(2).errors_on(:age) }
  end

  context '名前が文字数をオーバーしている場合' do
    subject{User.new(name: 'aaaaaaaaaabbbbbbbbbbc',age: 10)}
    it { should_not be_valid }
    it { should have(1).errors_on(:name) }
    it { should have(0).errors_on(:age) }
  end

  context '年齢が範囲を超えている場合' do
    subject{User.new(name: 'taro',age: 1001)}
    it {should_not be_valid}
    it{ should have(0).errors_on(:name) }
    it{ should have(1).errors_on(:age) }
  end

  context '正常なデータがセットされた場合' do
    subject{User.new(name: 'taro',age: 20)}
    it {should be_valid}
  end
end

ブラウザでも確認可能

  • 何も入力しないでuserを追加しようとすると怒られる

3.3 テストの実行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ bundle exec rspec
(以下のような結果がでるはず)

User
  正常なデータがセットされた場合
    should be valid
  名前が文字数をオーバーしている場合
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
    should not be valid
    should have 1 errors on :name
    should have 0 errors on :age
  年齢が範囲を超えている場合
    should not be valid
    should have 0 errors on :name
    should have 1 errors on :age
  何も入力しなかった場合
    should not be valid
    should have 1 errors on :name
    should have 2 errors on :age

Finished in 0.1475 seconds
10 examples, 0 failures

Randomized with seed 15644

4. インテグレーションテストの作成

4.1 GemfileにRSpecをGherkin(ガーキン)記法で書けるようなgemを記述(turnip)

1
2
3
4
5
6
7
8
$ vim Gefile

...
group :development, :test do
  gem 'rspec-rails', '~> 2.0'
  gem 'capybara'
  gem 'turnip'
end

capybara

仮想的なwebブラウザでテストを行うために必要

turnip

gherkin記法でRSpecを書くことが可能なフレームワーク

1
2
3
4
5
6
7
8
$ bundle install
$ vim .rspec

Before
--color --format documentation

After
-r turnip/rspec --color --format documentation

4.2 Turnipを実行できるようにする

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ vim spec/spec_helper.rb

...
require 'rspec/autorun'#(この行の下辺りに)

#記述
Dir.glob("spec/**/*steps.rb") { |f| load f, true}

require 'capybara/dsl'
require 'capybara/rspec'
require 'turnip'
require 'turnip/capybara'

...

4.3 featureファイルとstepファイルの記述

users.feature

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ mkdir spec/feature
$ vim spec/feature/users.feature

# encoding: utf-8
# language: ja
機能: ユーザー管理
  ユーザー管理を行いたい。なぜならサークル活動に参加するメンバーを管理する必要があるからだ。

  シナリオ: 一覧画面から新規登録画面に移動する
    前提 ユーザー管理の一覧画面を開く
    もし "New User" リンクをクリックする
    ならば ユーザー管理の新規登録画面が表示される

  シナリオ: 登録画面で登録すると詳細画面に移動する
    前提 ユーザー管理の新規登録画面を開く
    もし "Name" に "アリス" と入力する
    かつ "Age" に "16" と入力する
    かつ "Create User" ボタンをクリックする
    ならば ユーザー管理の詳細画面が表示される

users_steps.rb

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
$ mkdir spec/steps/
$ vim spec/steps/users_steps.rb

# encoding: utf-8

step 'ユーザー管理の一覧画面を開く' do
  visit '/users'
end

step '画面を目視' do
  save_and_open_page
end

step ':name リンクをクリックする' do |name|
  first(:link, name).click
end

step ':name ボタンをクリックする' do |name|
  first(:button, name).click
end

step 'ユーザー管理の新規登録画面が表示される' do
  current_path = URI.parse(current_url).path
  current_path.should == '/users/new'
end

step 'ユーザー管理の詳細画面が表示される' do
  current_path = URI.parse(current_url).path
  current_path.should == '/users/1'
end

step 'ユーザー管理の新規登録画面を開く' do
  visit '/users/new'
end

step ':field に :value と入力する' do |field, value|
  fill_in(field, :with => value)
end

4.4 テストの実行

1
2
$ bundle exec rspec
成功するはず

注意

$ rake db:test:cloneをしないと失敗する可能性がある

複数回連続では出来ない。多分DBに要素が残りっぱなし

5. Jenkinsでnew Jobを作成

ここらへんは、前回の記事と一緒

参考をそのまま試した備忘ログ

ネットワーク設定あたりの注意点

localではつながるが、vps上では色々やらないといけなかった nginxで動かすので yum install nginx等やって

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ vim /etc/nginx/nginx.com

##-- (ry

http {
  ##-- (ry

      listen 80;
    server_name <ホスト名>; 
    location {
      proxy_pass http://localhost:80; 
    }  
  }
}

ssh hoge@<ホスト名>

1
$ sudo service nginx restart

6. いざ実行しようとしたら、PostgreSQLの認証で怒られた

こんな感じ怒られる

1
FATAL: Peer authentication failed for user "postgres"

6.1 解決方法

  • pg_hba.confをいじる

PostgreSQL 9.3 でやってるので自分の環境では

1
2
3
4
5
6
7
8
9
$sudo vim /var/lib/pgsql/9.3/data/pg_hba.conf

## 変更前
# "local" is for Unix domain socket connections only
local   all             all                                     peer

## 変更後
# "local" is for Unix domain socket connections only
local   all             all                                     trust
1
$ sudo service postgresql-9.3 restart
  • md5では失敗したorz

7. Jenkinsでのjob中にてrspecでsyntaxエラー

3つのテストに分ける段階での、integration_testの方で

1
2
3
4
bundle install --path vendor/bundle
bundle exec rake db:migrate
bundle exec rake db:test:clone
bundle exec rspec spec/*/*.feature

ここで以下の様なエラー

1
2
3
4
$ bundle exec rspec spec/*/*.feature          
syntax error, unexpected ':', expecting end-of-input (SyntaxError)
機能: ユーザー管理
        ^

7.1 GitHub上に.rpsecファイルがないのが問題

ローカルなリポジトリにて

1
2
3
4
5
6
$ vim .gitignore
.rspecを消す

$ git stage .gitignore
$ git commit -m "Fix .gitignore"
$ git push

.rpsecの中身

1
-r turnip/rspec --color --format documentation

8 Herokuへpushしようとすると激おこ

原因:Jenkinsが頭よくて、masterを汚さないよう一時branchでやってる

8.1 解決方法

1
2
3
4
git checkout -b temp
git push heroku temp:master
git checkout master
git branch -D temp

という風にやる

やっと全部できた

参考