Skip to content

rails4 getting started

Takashi Hayasaka edited this page Aug 14, 2013 · 16 revisions

Ruby on Railsは、Rubyで書かれたポピュラーなフレームワークです。Rails 4.0のベータ版が、2013年1月25日にリリースされました。以前のバージョンのRailsをHeroku上でお使いになる場合は、Getting Started with Rails 3.x on Herokuを参照して下さい。

この記事は、Rails 4を使い始めるに辺り、深く掘り下げた記事となります。既に、HerokuとRailsに慣れ親しんでいる場合は、シンプルなRails 4のHerokuガイドを参照して下さい。

Rails 4をHeroku上で動作させるには、以下のものが必要となります。:

ローカル端末のセットアップ方法

まずは、ローカル端末にHeroku Toolbeltをインストールして下さい。インストールすることで、HerokuのCLI、Foreman、Gitのリビジョン管理システムへのアクセスが可能となります。また、RubyとRailsがインストールされている必要があります。

一度、インストールをしてしまえば、シェルからherokuコマンドを実行出来るようになります。Herokuのアカウント作成時に使用したemailアドレスとパスワードを使い、以下のようにログインして下さい。:

コマンドの前に付加された`$`は、適切な権限を持った上で、コマンドライン、プロンプト、またはターミナル上で実行されるべきコマンドであることを示しています。
:::term
$ heroku login
Enter your Heroku credentials.
Email: [email protected]
Password:
Could not find an existing public key.
Would you like to generate one? [Yn]
Generating new SSH public key.
Uploading ssh public key /Users/adam/.ssh/id_rsa.pub

既存のsshキーをアップロードするか、新たにsshキーを作成しますので、エンターを押下して下さい。sshキーは、この先、コードをHerokuにプッシュする際に使用されます。

アプリの作成

既存のアプリから作業を始めることもあるでしょう。その場合、まずは、Rails 4へのアップグレードをお願いします。そうでない場合、一般的なRails 4のアプリがサンプルとしては最適でしょう。以下のように作業を進めます。新規のアプリを作成する前に、$ rails -vコマンドを実行し、開発時にRails 4.xを使用していることを確認して下さい。また、Railsの新バージョンを入手するには下記のコマンドを実行します。

:::term
$ gem install rails --version 4.0.0

その後で、新規アプリを作成してみましょう。:

:::term
$ rails new myapp --database=postgresql
$ cd myapp

Herokuのgem

Herokuの統合環境は、以前、Railsのプラグインを使用することに依存していましたが、Rails 4では、それらの依存関係を削除しました。静的なアセットをHeroku上に提供することやログを取る機能を使用可能にするには、以下のgemをGemfileへ追加して下さい。:

:::ruby
gem 'rails_12factor', group: :production

その後で、下記を実行して下さい。:

:::term
$ bundle install

ここまでが、Herokuと統合する際の必要最小限の作業となります。

Postgresの使用

我々は、開発環境でのPostgreSQLの使用を強く推奨します。開発環境とデプロイ環境の同等性を保つことは、環境の違いにより発生する些細なバグを防ぐことになります。

アプリ作成時、--database=postgresqlのパラメータを指定し、postgresqlの使用を明示していないのであれば、pgというgemをRailsプロジェクトに追加する必要があります。Gemfile内の該当箇所を下記のように変更して下さい。:

:::ruby
gem 'sqlite3'

上記箇所をこちらに変更します。:

:::ruby
gem 'pg'

依存しているgemの再インストールをして下さい。(新規のGemfile.lockを生成するためです。):

:::term
$ bundle install

なぜこの変更が必要か、また、postgresをローカル環境で実行させるアプリの設定方法に関しては、より多くの情報を得ることが可能です。こちらを参照して下さい。HerokuでSqlite3が使用出来ない理由

アプリで使うRubyのバージョンの明示

Rails 4では、Ruby 1.9.3、またはそれ以降のRubyを必要とします。Herokuは、直近のバージョンのRubyをインストールしますが、Gemfileに以下のように追記することで、バージョンを明示することも可能です。:

:::ruby
ruby "1.9.3"

または、

:::ruby
ruby "2.0.0"

ローカルでも、同一のバージョンのRubyを使うべきです。$ ruby -vコマンドを実行することで、どのバージョンを使っているかを確認することが出来ます。より詳細な情報はこちらHerokuで使用するRubyのバージョンを明示するを参照して下さい。

Gitへアプリを保存

Herokuは、プロジェクトのデプロイをする際、gitのシステムに依存しています。gitとは、分散型バージョン管理システムのことです。プロジェクトが未だgitに保存されていない場合、まずは、システム内にgitがインストールされているかを確認して下さい。

:::term
$ git --help
usage: git [--version] [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
           [-p|--paginate|--no-pager] [--no-replace-objects] [--bare]
           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
           [-c name=value] [--help]
           <command> [<args>]
# ...

上記のコマンドを実行しても、アウトプットが得られない場合や、command not foundのエラーが返ってきた場合、gitをシステム内にインストールする必要があります。Heroku toolbeltがインストールされていることを確認して下さい。

gitが機能していることが分かれば、次にRailsアプリのディレクトリに移動して下さい。その後で、Railsアプリのディレクトリで、下記の3つのコマンドを実行して下さい。このコマンドは、gitの初期化とコードをgitへコミットするためのものです。:

:::term
$ git init
$ git add .
$ git commit -m "init"

さて、あなたのアプリケーションがgitへコミットされました。これで、Herokuへのデプロイが可能となります。

アプリケーションをHerokuへデプロイ

Railsアプリが格納されているディレクトリにいることを確認して下さい。その後で、Herokuへアプリをクリエイトします。:

:::term
$ heroku create
Creating calm-brook-1268... done, stack is cedar
http://calm-brook-1268.herokuapp.com/ | [email protected]:calm-brook-1268.git
Git remote heroku added

下記のコマンドを実行することで、プロジェクトがリモートに追加されたことを確認して下さい。

:::term
$ git config -e

fatal: not in a git directoryというエラーが出なければ、Herokuへのデプロイが安全に行える状態です。デプロイ後、データベースのマイグレートが必要となります。適切にスケールされていることを確認して下さい。また、今後発生し得る問題をデバグするには、ログを使用して下さい。

コードのデプロイ:

:::term
$ git push heroku master
Counting objects: 112, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (77/77), done.
Writing objects: 100% (112/112), 27.01 KiB, done.
Total 112 (delta 20), reused 112 (delta 20)
-----> Ruby/Rails app detected
-----> Using Ruby version: ruby-2.0.0
-----> Installing dependencies using Bundler version 1.3.0.pre.5
       Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin --deployment
       Fetching gem metadata from https://rubygems.org/.........
       Fetching gem metadata from https://rubygems.org/..
       Fetching git://github.com/heroku/rails3_serve_static_assets.git
       Fetching git://github.com/heroku/rails_log_stdout.git
       Installing rake (10.0.3)
       Installing i18n (0.6.2)
       Installing minitest (4.6.1)
       Installing multi_json (1.6.1)
       Installing atomic (1.0.1)
       Installing thread_safe (0.1.0)
       Installing tzinfo (0.3.35)
       Installing activesupport (4.0.0)
       Installing builder (3.1.4)
       Installing erubis (2.7.0)
       Installing rack (1.5.2)
       Installing rack-test (0.6.2)
       Installing actionpack (4.0.0)
       Installing mime-types (1.21)
       Installing polyglot (0.3.3)
       Installing treetop (1.4.12)
       Installing mail (2.5.3)
       Installing actionmailer (4.0.0)
       Installing activemodel (4.0.0)
       Installing activerecord-deprecated_finders (0.0.3)
       Installing arel (4.0.0)
       Installing activerecord (4.0.0)
       Installing coffee-script-source (1.5.0)
       Installing execjs (1.4.0)
       Installing coffee-script (2.2.0)
       Using json (1.7.7)
       Installing rdoc (3.12.2)
       Installing thor (0.17.0)
       Installing railties (4.0.0)
       Installing coffee-rails (4.0.0)
       Installing hike (1.2.1)
       Installing jbuilder (1.0.2)
       Installing jquery-rails (2.2.1)
       Installing pg (0.14.1)
       Using bundler (1.3.0)
       Installing tilt (1.3.3)
       Installing sprockets (2.9.0)
       Installing sprockets-rails (2.0.0.rc3)
       Installing rails (4.0.0)
       Using rails3_serve_static_assets (0.0.1) from git://github.com/heroku/rails3_serve_static_assets.git (at master)
       Using rails_log_stdout (0.0.1) from git://github.com/heroku/rails_log_stdout.git (at master)
       Installing sass (3.2.6)
       Installing sass-rails (4.0.0)
       Installing turbolinks (1.0.0)
       Installing uglifier (1.3.0)
       Your bundle is complete! It was installed into ./vendor/bundle
       Post-install message from rdoc:
       Depending on your version of ruby, you may need to install ruby rdoc/ri data:
       <= 1.8.6 : unsupported
       = 1.8.7 : gem install rdoc-data; rdoc-data --install
       = 1.9.1 : gem install rdoc-data; rdoc-data --install
       >= 1.9.2 : nothing to do! Yay!
       Cleaning up the bundler cache.
-----> Preparing app for Rails asset pipeline
       Running: rake assets:precompile
       I, [2013-02-25T15:15:26.999810 #1771]  INFO -- : Writing /tmp/build_8twtg5uo0zrj/public/assets/rails-a48208150b2c0da4f80797a999919b58.png
       I, [2013-02-25T15:15:29.993217 #1771]  INFO -- : Writing /tmp/build_8twtg5uo0zrj/public/assets/application-e4bf17ac068b4157db532671a5294743.js
       I, [2013-02-25T15:15:30.065780 #1771]  INFO -- : Writing /tmp/build_8twtg5uo0zrj/public/assets/application-a543268ce31a2798b68675fbfcb1bcdc.css
       Asset precompilation completed (6.24s)
-----> Rails plugin injection
-----> Discovering process types
       Procfile declares types      -> (none)
       Default types for Ruby/Rails -> console, rake, web, worker

-----> Compiled slug size: 33.1MB
-----> Launching... done, v6
       http://calm-brook-1268.herokuapp.com deployed to Heroku

To [email protected]:calm-brook-1268.git
 * [new branch]      master -> master

注意:Rails 4では、本番環境に静的インデックスのページを管理しなくなりました。新規のアプリを作成した場合、ルートとなるページは存在しないこととなるでしょう。

データベースのマイグレート

アプリケーションにデータベースをお使いでしたら、下記のコマンドを実行することで、手動でデータベースをマイグレートする必要があります。:

:::term
$ heroku run rake db:migrate

heroku runの後に付加されたコマンドは全てHerokuのdyno上で実行されます。

アプリケーションへの訪問

Herokuへのコードのデプロイは完了しましたので、Herokuへプロセスタイプを実行するよう指示を送ることが出来ます。Herokuでは、dyno上で関連するコマンドを実行することにより、これを実現しています。dynoとは、Herokuの構成における基本単位のことで、軽量なコンテナとなります。

webプロセスタイプとして、1dynoが実行中であることを確認してみましょう。:

:::term
$ heroku ps:scale web=1

アプリのdynoの状態を確認することが可能です。heroku psコマンドは、アプリケーションで実行されているdynoをリスト化します。:

:::term
$ heroku ps
=== web: `rails server -p $PORT -e $RAILS_ENV`
web.1: up for 5s

1dynoが実行されていることを確認しました。

heroku openを実行することで、ブラウザ上でアプリを訪問することが可能です。

:::term
$ heroku open
Opening calm-brook-1268... done

開発中、Herokuはデフォルトでアプリ名を提供してくれます。アプリをスケールする準備が整い、本番環境でHerokuを使用する際、カスタムドメインを名称として追加することが可能です。

ログの参照

アプリが正常に動作するよう開発を行っている際、何かしらの問題に遭遇したなら、まずは、ログを確認する必要があります。

Herokuでは、時系列のイベントのストリームとしてログを扱います。ログは、アプリケーションのコンポーネントを実行する全dynoから収集されます。HerokuのLogplexは、これらの全イベントへのチャンネルとなります。

稼働中のアプリの情報を参照するには、heroku logsというログ用コマンドを実行することで可能となります。:

:::term
$ heroku logs
2013-02-26T01:47:32+00:00 heroku[web.1]: State changed from created to starting
2013-02-26T01:47:33+00:00 heroku[web.1]: Starting process with command `rails server -p 16142 -e $RAILS_ENV`
2013-02-26T01:47:35+00:00 app[web.1]: [2013-02-26 01:47:35] INFO  WEBrick 1.3.1
2013-02-26T01:47:35+00:00 app[web.1]: [2013-02-26 01:47:35] INFO  WEBrick::HTTPServer#start: pid=2 port=16142
2013-02-26T01:47:35+00:00 app[web.1]: [2013-02-26 01:47:35] INFO  ruby 2.0.0 (2013-02-24) [x86_64-linux]
2013-02-26T01:47:36+00:00 heroku[web.1]: State changed from starting to up

以下のように--tailフラグをコマンドに付加することで、全ストリームのログを取得することが可能です。:

:::term
$ heroku logs --tail

Dynoのスリープとスケール

web dynoを1つだけ使用しているアプリでは、1時間アイドル状態が続いた場合、dynoがスリープ状態となります。このことは、スリープ状態となってから最初のリクエストを受け付けた際に、アプリの起動が遅くなる原因となります。継続的にリクエストが発生する場合は、遅延なく通常通り動作します。

これを避けるために、下記の例のように、web dynoを1つ以上にスケールすることが可能です。:

:::term
$ heroku ps:scale web=2

Herokuは、アプリ毎に750時間フリーのdynoを提供しています。2つのdynoでアプリを実行している場合は、この制限を越えてしまうでしょう。そのため、以下のようにスケールを元に戻しましょう。:

:::term
$ heroku ps:scale web=1

コンソール

Herokuは、heroku runコマンドを使用することで、one-off dynoの仕組み内において、コマンドの実行を許可しています。one-off dynoとは、必要な時にのみ実行されるスクリプトとアプリケーションのことです。このone-off dynoをRailsのコンソールプロセスを起動させるのに使ってみて下さい。実際のアプリの環境で試験することが可能です。:

:::term
$ heroku run rails console
Running `rails console` attached to terminal... up, run.2591
Loading production environment (Rails 4.0.0)
irb(main):001:0>

Rake

Rakeはコンソールと同様に付加プロセスとして実行することが出来ます。:

:::term
$ heroku run rake db:migrate

Webサーバー

デフォルトで、rails serverコマンドで使用されるWebサーバーは、Webrickとなります。これはテスト環境では良いかもしれません。ですが、本番環境ではもっと堅牢なWebサーバーへ切り替えたくなるかもしれません。Cedar上では、UnicornをWebサーバーとして使用することを推奨します。あなたが選択するWebサーバーがどれであれ、本番環境のアプリでは、常にProcfileへ、はっきりと使用するWebサーバーを明示するべきです。

まず最初に、アプリのGemfileへUnicornを追加して下さい。:

gem 'unicorn'

$ bundle installを実行して下さい。実行することで、Unicornを使用するよう、アプリを設定する準備が整います。

config/unicorn.rbにUnicorn用の設定ファイルを作成して下さい。:

$ touch config/unicorn.rb

現在、HerokuではUnicornに関する詳細な設定オプションを追加中です。詳細は、HerokuのUnicornに関するドキュメントに記載しています。:

# config/unicorn.rb
worker_processes 3
timeout 30
preload_app true

before_fork do |server, worker|

  Signal.trap 'TERM' do
    puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
    Process.kill 'QUIT', Process.pid
  end

  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.connection.disconnect!
end

after_fork do |server, worker|

  Signal.trap 'TERM' do
    puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to sent QUIT'
  end

  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.establish_connection
end

このデフォルト設定は、Active Recordを使用するスタンダードなRailsアプリで使われることを前提としています。オフィシャルのUnicornに関するドキュメントにある異なるオプションに関しても、精通しておくべきでしょう。

最後に、アプリケーションのルートディレクトリ上にProcfileを作成することで、あなたのRailsアプリがどのように動作するかをHerokuへ伝える必要があります。

Procfile

Procfileというファイルを作成することで、webプロセスを起動するのに使用されるコマンドを下記のように変更して下さい。:

web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb

注意: Procfileという名称は繊細です。名称の1文字目は必ず大文字にして下さい。

Foremanを使って、Procfileをローカル環境でテストしてみましょう。:

:::term
$ foreman start
18:24:56 web.1  | I, [2013-03-13T18:24:56.885046 #18793]  INFO -- : listening on addr=0.0.0.0:5000 fd=7
18:24:56 web.1  | I, [2013-03-13T18:24:56.885140 #18793]  INFO -- : worker=0 spawning...
18:24:56 web.1  | I, [2013-03-13T18:24:56.885680 #18793]  INFO -- : master process ready
18:24:56 web.1  | I, [2013-03-13T18:24:56.886145 #18795]  INFO -- : worker=0 spawned pid=18795
18:24:56 web.1  | I, [2013-03-13T18:24:56.886272 #18795]  INFO -- : Refreshing Gem list
18:24:57 web.1  | I, [2013-03-13T18:24:57.647574 #18795]  INFO -- : worker=0 ready

問題が無さそうです。Ctrl-Cを押し、Foremanを終了させて下さい。変更箇所をHerokuへデプロイして下さい。:

:::term
$ git add .
$ git commit -m "use unicorn via procfile"
$ git push heroku

psコマンドを打ってみて下さい。webプロセスがUnicornをwebサーバーとして使用していることを確認することが出来ます。

:::term
$ heroku ps
Process State Command
------------ ------------------ ------------------------------
web.1 starting for 3s unicorn -p $..

Unicornを使用していることは、ログにも反映されます。:

:::term
$ heroku logs
2013-03-14T01:57:55+00:00 heroku[web.1]: State changed from up to starting
2013-03-14T01:57:59+00:00 heroku[web.1]: Starting process with command `unicorn -p 26253 -E $RACK_ENV`
2013-03-14T01:58:00+00:00 app[web.1]: => Rails 4.0.0 application starting in production on http://0.0.0.0:27993
2013-03-14T01:58:00+00:00 app[web.1]: I, [2013-03-14T01:58:00.253906 #2]  INFO -- : listening on addr=0.0.0.0:26253 fd=7
2013-03-14T01:58:00+00:00 app[web.1]: I, [2013-03-14T01:58:00.254256 #2]  INFO -- : worker=0 spawning...
2013-03-14T01:58:00+00:00 app[web.1]: I, [2013-03-14T01:58:00.257455 #2]  INFO -- : master process ready
2013-03-14T01:58:00+00:00 app[web.1]: I, [2013-03-14T01:58:00.258541 #4]  INFO -- : Refreshing Gem list
2013-03-14T01:58:00+00:00 app[web.1]: I, [2013-03-14T01:58:00.258293 #4]  INFO -- : worker=0 spawned pid=4
2013-03-14T01:58:01+00:00 app[web.1]: I, [2013-03-14T01:58:01.347337 #4]  INFO -- : worker=0 ready
2013-03-14T01:58:01+00:00 heroku[web.1]: State changed from starting to up

Railsのアセットパイプライン

Herokuへディプロイする際、Railsのアセットパイプラインの呼び出しには、いくつかのオプションがあります。詳細は、Rails 3.1+ Asset Pipeline on Heroku Cedarを参照して下さい。

Rails 4ではconfig.assets.initialize_on_precompileオプションはリムーブされ、必要無くなりました。また、アセットのコンパイル時のエラーは、プッシュ時のエラーの原因ともなります。

トラブルシューティング

アプリをプッシュ時に、クラッシュ(heroku psコマンドがcrashedというステートを返します)した場合は、何が問題であったかをログで確認して下さい。一般的な問題をいくつかご紹介します。

開発環境とテスト環境のgemにおけるランタイムの依存関係

ディプロイ時にgemが見つからない状態となっているのであれば、Bundlerのグループを確認してみて下さい。Herokuでは、開発環境やテスト環境のグループを無視して、アプリを構築します。あなたのアプリが、これらのグループのgemに依存しているのであれば、そのgemをこれらのグループの外に記述してみて下さい。

Rakefile内のRSpecタスクを使った一般的な例を挙げてみます。Herokuへのディプロイ時に下記のエラーを見ることがあるなら:

:::term
$ heroku run rake -T
Running `bundle exec rake -T` attached to terminal... up, ps.3
rake aborted!
no such file to load -- rspec/core/rake_task

次にこの問題にも遭遇するでしょう。最初に、以下のようにローカルでも同様の現象を発生させて下さい。:

:::term
$ bundle install --without development:test
…
$ bundle exec rake -T
rake aborted!
no such file to load -- rspec/core/rake_task

gemロード時に、これらのRakeタスクを条件付きにすることで、この問題をフィックス出来ます。例えば以下のような感じです。:

Rakefile

:::ruby
begin
  require "rspec/core/rake_task"

  desc "Run all examples"

  RSpec::Core::RakeTask.new(:spec) do |t|
    t.rspec_opts = %w[--color]
    t.pattern = 'spec/*_spec.rb'
  end
rescue LoadError
end

ローカルで動作することを確認した上で、Herokuへプッシュして下さい。

Clone this wiki locally