Ruby on Rails
Tutorial
1
環境
Ruby 2.0.0
Rails 4.0.0
Bundler 1.3.5
SQLite 3.7.2
2
Rails インストール
% mkdir -p tutorial
% cd tutorial
% bundle init
% vi Gemfile
% bundle install --path vendor/bundle
Gemfile
source "https://rubygems.org"
gem "rails"
3
プロジェクト作成1
% bundle exec rails new . --skip-bundle
conflict Gemfile
Overwrite /path/to/tutorial/Gemfile? (enter "h" for help)
[Ynaqdh] Enter(上書き)
よく使うオプション
オプション 値 説明
-T test/unitを組み込まない
-d
mysql/
postgresql
利用するデータベースを指定。
デフォルトはSQLite。
--skip-bundle bundle initを行わない
4
プロジェクト作成2
% vi Gemfile
% bundle
# See https://github.com/sstephenson/execjs#readme for more
supported runtimes
# 以下をアンコメント
gem 'therubyracer', platforms: :ruby
Gemfile
% export PATH=`pwd`/bin:$PATH
% rails -v
確認
5
ディレクトリ構成
ディレクトリ 説明説明
app
アプリケーションコードアプリケーションコード
app
assets image/stylesheet/javascript
app
controllers コントローラ
app helpers ヘルパーapp
mailers メール
app
models モデル
app
views ビュー
bin bundle/rails/rake等のスクリプトbundle/rails/rake等のスクリプト
config 設定ファイル設定ファイル
db スキーマ/マイグレーションファイル及びSQLite DBスキーマ/マイグレーションファイル及びSQLite DB
lib 独自ライブラリ/Rakeタスク独自ライブラリ/Rakeタスク
log ログファイルログファイル
public Webサーバに設定するDocumentRootWebサーバに設定するDocumentRoot
test テストコード(RSpecを利用する場合はspec)テストコード(RSpecを利用する場合はspec)
tmp TempファイルTempファイル
vendor 外部のライブラリ外部のライブラリ
6
rails/rakeコマンド
コマンド 説明
rails server 開発用のWEBrickサーバを起動
rails console Railsコンソールを起動
rails dbconsole DBのクライアントを起動
rails runner Rails環境でスクリプトを実行
コマンド 説明
rake db:create 対象のデータベースを作成
rake db:migrate マイグレーションファイルを実行
rake db:rollback マイグレーションのロールバックを実行
rake routes ルーティングの設定を確認
rake assets:precompile アセットのコンパイル
7
とりあえず起動してみる
% rails s
8
Scaffold
% rails generate scaffold blog title:string body:text
% rake db:migrate
CRUDが簡単に作れる
model/scaffoldを作成したら
`rake db:migrate`
を実行してDBに反映させる
assets/controller/helper/model/
view及びマイグレーションファイルをま
とめて生成。
9
個別で生成
% rails g model モデル名 カラム名:型 カラム名:型
% rails g controller コントローラ名 メソッド名
% rails g migration タスク名
db/migrate/YYYYmmddHHMMSS_task.rbが作成され、`rake db:migrate`でタスクを実行できる。
主にテーブル作成/スキーマ変更に使う。
マイグレーション
コントローラ
assets/controller/helper/viewを作成する。
メソッド名を指定しない場合は空のコントローラが作成される。
モデル
modelとマイグレーションファイルを作成する。
カラムの型は主にstring/text/integer/float/boolean/date/time/timestampを使う。
実際にDBに作成されるカラムの型はDBによって異なる。
10
マイグレーションファイル
作成されたマイグレーションファイルはdb/migrate/に保存される
`rake db:migrate`でDBに反映する事ができる
反映後に戻したい時は`rake db:rollback`でロールバックできる
どこまで適用されているかはschema_migrationsテーブルで管理されている
class CreateBlogs < ActiveRecord::Migration
def change
create_table :blogs do |t|
t.string :title
t.text :body
t.timestamps
end
end
end
マイグレーションファイルの中身
11
リクエスト処理の流れ
router
(routes.rb)
DB
Server
controllers
(controllers/*.rb)
models
(models/*.rb)
views
(views/*/
*.html.erb)
request routing
sql
response
12
モデル
app/models/blog.rb
class Blog < ActiveRecord::Base
end
本来はバリデーション/アソシエーション/ビジネスロジック等を書くけど、これでもDB操作は可能
% rails c
> blog = Blog.new
> blog.title = "test title"
> blog.body = "test body"
> blog.save # blogsテーブルに新規レコードを作成
> blogs = Blog.all # blogsテーブルの全てのレコードを取得
> blogs.each {|b| puts b.title} # 取得したレコードのtitleカラムを出力
> blog = Blog.find(1) # blogsテーブルからidが1のレコードを取得
> puts blog.title # titleカラムを出力
> blog.destroy # 取得したレコードをblogsテーブルから削除
モデルの操作例
13
ルーティング1
Tutorial::Application.routes.draw do
resources :blogs
end
config/routes.rb
% rake routes
Prefix Verb URI Pattern Controller#Action
blogs GET /blogs(.:format) blogs#index
POST /blogs(.:format) blogs#create
new_blog GET /blogs/new(.:format) blogs#new
edit_blog GET /blogs/:id/edit(.:format) blogs#edit
blog GET /blogs/:id(.:format) blogs#show
PATCH /blogs/:id(.:format) blogs#update
PUT /blogs/:id(.:format) blogs#update
DELETE /blogs/:id(.:format) blogs#destroy
上記のコードで設定されるルーティング
14
ルーティング2
個別にルーティング設定をする場合
Tutorial::Application.routes.draw do
controller :blogs do
# HTTPMethod URI, to: ExecMethod, as: :Prefix
# GET /index => BlogsController#index (index_path)
get :index, to: :index, as: :index
# POST /create => BlogsController#create (create_path)
post :create, to: :create, as: :create
# GET / => BlogsController#root (root_path)
get :root, to: "blogs#root"
end
end
15
コントローラ1
class BlogsController < ApplicationController
before_action :set_blog, only: [:show, :edit, :update, :destroy]
def index
@blogs = Blog.all
end
def new
@blog = Blog.new
end
private
def set_blog
@blog = Blog.find(params[:id])
end
def blog_params
params.require(:blog).permit(:title, :body)
end
end
app/controller/blogs_controller.rb
メソッドが無い又は空の場合はviewがレンダリングされる
16
コントローラ2
メソッド 説明
#index
@blogsにblogsテーブルの全てのレコードを格納してviewをレ
ンダリングする。
#new
@blogにBlogモデルのオブジェクトを生成して格納し、viewを
レンダリングする。
#show
先のページではメソッドが無いが実際は空のメソッドが存在す
る。before_actionが設定されている為、set_blogメソッドを
呼び出してviewをレンダリングする。
#edit
showと同様にメソッドが無いが実際は空のメソッドが存在する。
こちらもbefore_actionが設定されている為、set_blogメソッ
ドを呼び出してviewをレンダリングする。
17
コントローラ3
class BlogsController < ApplicationController
def create
@blog = Blog.new(blog_params)
respond_to do |format|
if @blog.save
format.html { redirect_to @blog, notice: 'Blog was successfully created.' }
format.json { render action: 'show', status: :created, location: @blog }
else
format.html { render action: 'new' }
format.json { render json: @blog.errors, status: :unprocessable_entity }
end
end
end
end
Blogモデルのオブジェクトをstrong parameterを通したパラメータを引数に生
成し、@blogに格納。
@blog.save(DBに保存)して成功すればリダイレクト、失敗すればnewメソッドの
viewをレンダリングする。
18
コントローラ4
class BlogsController < ApplicationController
def update
respond_to do |format|
if @blog.update(blog_params)
format.html { redirect_to @blog, notice: 'Blog was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: @blog.errors, status: :unprocessable_entity }
end
end
end
end
before_actionが設定されている為、set_blogメソッドを呼び出して
@blog.updateでcreateと同様にstrong parameterを通したパラメータを引数
にレコードをアップデートする。
成功した場合はリダイレクトし失敗した場合はeditのviewをレンダリングする。
19
コントローラ5
class BlogsController < ApplicationController
def destroy
@blog.destroy
respond_to do |format|
format.html { redirect_to blogs_url }
format.json { head :no_content }
end
end
end
before_actionが設定されている為、set_blogメソッドを呼び出して
@blog.destroyでレコードを削除。
削除後にリダイレクトされる。
`respond_to {|format| ...}`はformatによってレンダリングする内容を指
定している。
20
ビュー1
<!DOCTYPE html>
<html>
<head>
<title>Tutorial</title>
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track"
=> true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
</head>
<body>
<%= yield %>
</body>
</html>
このファイルがHTMLをレンダリングする時にデフォルトで使用されるlayout。
<%= yield %>の部分に対象のviewファイルで生成されたHTMLが入る。
rubyのコードは<%= %>(出力あり)か<% %>(出力無し)の中に記述する。
app/views/layouts/application.html.erb
21
ビュー2
<h1>Editing blog</h1>
<%= render 'form' %>
<%= link_to 'Show', @blog %> |
<%= link_to 'Back', blogs_path %>
コントローラのメソッド内で`render`や`redirect_to`等が呼ばれない場合、
app/views/コントローラ名/メソッド名.html.erb(formatがhtmlの場合)がレ
ンダリングされる。
また以下のedit.html.erbのように共通で利用する部分を`render`メソッドで
読み込む事も可能。
app/views/blogs/edit.html.erb
22
ログイン認証機能を付ける1
% vi Gemfile
% bundle
ライブラリインストール
# 以下を追記
gem "passwd"
Gemfile
Gemfileにてインストールしたライブラリを自動的に`require`される。
(groupを指定したり、requireオプションをfalseにした場合以外)
2回目以降は.bundle/configにオプションが設定されているのでbundleのみで
問題ない。
23
ログイン認証機能を付ける2
% rails g controller sessions
ログイン/ログアウト用のSessionsコントローラを作成
Tutorial::Application.routes.draw do
resources :blogs
# 以下を追加
controller :sessions do
get :login, to: :new, as: :new_session
post :login, to: :create, as: :create_session
get :logout, to: :destroy, as: :delete_session
end
end
ルーティング設定
config/routes.rb
% rake routes
...
new_session GET /login(.:format) sessions#new
create_session POST /login(.:format) sessions#create
delete_session GET /logout(.:format) sessions#destroy
24
ログイン認証機能を付ける3
<%= form_tag(create_session_path) do %>
<% if flash[:alert] %>
<%= flash[:alert] %>
<% end %>
<%= text_field_tag :email, nil, placeholder: "Email" %>
<%= password_field_tag :password, nil, placeholder: "Password" %>
<%= submit_tag "Send" %>
<% end %>
ログインページ作成(新規作成)
app/views/sessions/new.html.erb
class SessionsController < ApplicationController
def create
render text: "login"
end
def destroy
render text: "logout"
end
end
SessionsControllerにcreate/destroyメソッドを追加しておく
app/controllers/sessions_controller.rb
25
ログイン認証機能を付ける4
% rails g model user email:string salt:string password:string
% rake db:migrate
ユーザモデル作成
class User < ActiveRecord::Base
include Passwd::ActiveRecord
define_column
end
Userモデル編集
app/models/user.rb
ユーザ作成
% rails c
> user = User.new
> user.email = "foo@example.com"
> user.set_password("secret")
> user.save
> puts password
26
ログイン認証機能を付ける5
class SessionsController < ApplicationController
def create
@user = User.authenticate(params[:email], params[:password])
if @user
session[:user] = @user.id
redirect_to blogs_path
else
flash.now[:alert] = "Email or password is incorrect."
render action: :new
end
end
def destroy
session[:user] = nil
redirect_to blogs_path
end
end
ログイン/ログアウト処理
app/controllers/session_controller.rb
27
ブログの作成等を制限する1
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
# 以下を追加
def require_logged_in
if session[:user].present?
begin
@user = User.find(session[:user])
rescue ActiveRecord::RecordNotFound
reset_session
end
end
redirect_to create_session_path unless @user
end
end
ログインチェックのメソッドをApplicationControllerに定義
app/controllers/application_controller.rb
application_controller.rbにメソッドを定義しておくと他のコントローラか
ら利用可能になる。
28
ブログの作成等を制限する2
class BlogsController < ApplicationController
before_action :set_blog, only: [:show, :edit, :update, :destroy]
# 以下を追加
before_action :require_logged_in, only: [:new, :edit, :create, :update, :destroy]
...
end
new/edit/create/update/destroyにログイン制限をかける
before_actionで`require_logged_in`メソッドを呼び出し、ログインしてい
ない場合はログインページにリダイレクトさせる
29

Ruby on Rails Tutorial

  • 1.
  • 2.
  • 3.
    Rails インストール % mkdir-p tutorial % cd tutorial % bundle init % vi Gemfile % bundle install --path vendor/bundle Gemfile source "https://rubygems.org" gem "rails" 3
  • 4.
    プロジェクト作成1 % bundle execrails new . --skip-bundle conflict Gemfile Overwrite /path/to/tutorial/Gemfile? (enter "h" for help) [Ynaqdh] Enter(上書き) よく使うオプション オプション 値 説明 -T test/unitを組み込まない -d mysql/ postgresql 利用するデータベースを指定。 デフォルトはSQLite。 --skip-bundle bundle initを行わない 4
  • 5.
    プロジェクト作成2 % vi Gemfile %bundle # See https://github.com/sstephenson/execjs#readme for more supported runtimes # 以下をアンコメント gem 'therubyracer', platforms: :ruby Gemfile % export PATH=`pwd`/bin:$PATH % rails -v 確認 5
  • 6.
    ディレクトリ構成 ディレクトリ 説明説明 app アプリケーションコードアプリケーションコード app assets image/stylesheet/javascript app controllersコントローラ app helpers ヘルパーapp mailers メール app models モデル app views ビュー bin bundle/rails/rake等のスクリプトbundle/rails/rake等のスクリプト config 設定ファイル設定ファイル db スキーマ/マイグレーションファイル及びSQLite DBスキーマ/マイグレーションファイル及びSQLite DB lib 独自ライブラリ/Rakeタスク独自ライブラリ/Rakeタスク log ログファイルログファイル public Webサーバに設定するDocumentRootWebサーバに設定するDocumentRoot test テストコード(RSpecを利用する場合はspec)テストコード(RSpecを利用する場合はspec) tmp TempファイルTempファイル vendor 外部のライブラリ外部のライブラリ 6
  • 7.
    rails/rakeコマンド コマンド 説明 rails server開発用のWEBrickサーバを起動 rails console Railsコンソールを起動 rails dbconsole DBのクライアントを起動 rails runner Rails環境でスクリプトを実行 コマンド 説明 rake db:create 対象のデータベースを作成 rake db:migrate マイグレーションファイルを実行 rake db:rollback マイグレーションのロールバックを実行 rake routes ルーティングの設定を確認 rake assets:precompile アセットのコンパイル 7
  • 8.
  • 9.
    Scaffold % rails generatescaffold blog title:string body:text % rake db:migrate CRUDが簡単に作れる model/scaffoldを作成したら `rake db:migrate` を実行してDBに反映させる assets/controller/helper/model/ view及びマイグレーションファイルをま とめて生成。 9
  • 10.
    個別で生成 % rails gmodel モデル名 カラム名:型 カラム名:型 % rails g controller コントローラ名 メソッド名 % rails g migration タスク名 db/migrate/YYYYmmddHHMMSS_task.rbが作成され、`rake db:migrate`でタスクを実行できる。 主にテーブル作成/スキーマ変更に使う。 マイグレーション コントローラ assets/controller/helper/viewを作成する。 メソッド名を指定しない場合は空のコントローラが作成される。 モデル modelとマイグレーションファイルを作成する。 カラムの型は主にstring/text/integer/float/boolean/date/time/timestampを使う。 実際にDBに作成されるカラムの型はDBによって異なる。 10
  • 11.
  • 12.
  • 13.
    モデル app/models/blog.rb class Blog <ActiveRecord::Base end 本来はバリデーション/アソシエーション/ビジネスロジック等を書くけど、これでもDB操作は可能 % rails c > blog = Blog.new > blog.title = "test title" > blog.body = "test body" > blog.save # blogsテーブルに新規レコードを作成 > blogs = Blog.all # blogsテーブルの全てのレコードを取得 > blogs.each {|b| puts b.title} # 取得したレコードのtitleカラムを出力 > blog = Blog.find(1) # blogsテーブルからidが1のレコードを取得 > puts blog.title # titleカラムを出力 > blog.destroy # 取得したレコードをblogsテーブルから削除 モデルの操作例 13
  • 14.
    ルーティング1 Tutorial::Application.routes.draw do resources :blogs end config/routes.rb %rake routes Prefix Verb URI Pattern Controller#Action blogs GET /blogs(.:format) blogs#index POST /blogs(.:format) blogs#create new_blog GET /blogs/new(.:format) blogs#new edit_blog GET /blogs/:id/edit(.:format) blogs#edit blog GET /blogs/:id(.:format) blogs#show PATCH /blogs/:id(.:format) blogs#update PUT /blogs/:id(.:format) blogs#update DELETE /blogs/:id(.:format) blogs#destroy 上記のコードで設定されるルーティング 14
  • 15.
    ルーティング2 個別にルーティング設定をする場合 Tutorial::Application.routes.draw do controller :blogsdo # HTTPMethod URI, to: ExecMethod, as: :Prefix # GET /index => BlogsController#index (index_path) get :index, to: :index, as: :index # POST /create => BlogsController#create (create_path) post :create, to: :create, as: :create # GET / => BlogsController#root (root_path) get :root, to: "blogs#root" end end 15
  • 16.
    コントローラ1 class BlogsController <ApplicationController before_action :set_blog, only: [:show, :edit, :update, :destroy] def index @blogs = Blog.all end def new @blog = Blog.new end private def set_blog @blog = Blog.find(params[:id]) end def blog_params params.require(:blog).permit(:title, :body) end end app/controller/blogs_controller.rb メソッドが無い又は空の場合はviewがレンダリングされる 16
  • 17.
  • 18.
    コントローラ3 class BlogsController <ApplicationController def create @blog = Blog.new(blog_params) respond_to do |format| if @blog.save format.html { redirect_to @blog, notice: 'Blog was successfully created.' } format.json { render action: 'show', status: :created, location: @blog } else format.html { render action: 'new' } format.json { render json: @blog.errors, status: :unprocessable_entity } end end end end Blogモデルのオブジェクトをstrong parameterを通したパラメータを引数に生 成し、@blogに格納。 @blog.save(DBに保存)して成功すればリダイレクト、失敗すればnewメソッドの viewをレンダリングする。 18
  • 19.
    コントローラ4 class BlogsController <ApplicationController def update respond_to do |format| if @blog.update(blog_params) format.html { redirect_to @blog, notice: 'Blog was successfully updated.' } format.json { head :no_content } else format.html { render action: 'edit' } format.json { render json: @blog.errors, status: :unprocessable_entity } end end end end before_actionが設定されている為、set_blogメソッドを呼び出して @blog.updateでcreateと同様にstrong parameterを通したパラメータを引数 にレコードをアップデートする。 成功した場合はリダイレクトし失敗した場合はeditのviewをレンダリングする。 19
  • 20.
    コントローラ5 class BlogsController <ApplicationController def destroy @blog.destroy respond_to do |format| format.html { redirect_to blogs_url } format.json { head :no_content } end end end before_actionが設定されている為、set_blogメソッドを呼び出して @blog.destroyでレコードを削除。 削除後にリダイレクトされる。 `respond_to {|format| ...}`はformatによってレンダリングする内容を指 定している。 20
  • 21.
    ビュー1 <!DOCTYPE html> <html> <head> <title>Tutorial</title> <%= stylesheet_link_tag"application", media: "all", "data-turbolinks-track" => true %> <%= javascript_include_tag "application", "data-turbolinks-track" => true %> <%= csrf_meta_tags %> </head> <body> <%= yield %> </body> </html> このファイルがHTMLをレンダリングする時にデフォルトで使用されるlayout。 <%= yield %>の部分に対象のviewファイルで生成されたHTMLが入る。 rubyのコードは<%= %>(出力あり)か<% %>(出力無し)の中に記述する。 app/views/layouts/application.html.erb 21
  • 22.
    ビュー2 <h1>Editing blog</h1> <%= render'form' %> <%= link_to 'Show', @blog %> | <%= link_to 'Back', blogs_path %> コントローラのメソッド内で`render`や`redirect_to`等が呼ばれない場合、 app/views/コントローラ名/メソッド名.html.erb(formatがhtmlの場合)がレ ンダリングされる。 また以下のedit.html.erbのように共通で利用する部分を`render`メソッドで 読み込む事も可能。 app/views/blogs/edit.html.erb 22
  • 23.
    ログイン認証機能を付ける1 % vi Gemfile %bundle ライブラリインストール # 以下を追記 gem "passwd" Gemfile Gemfileにてインストールしたライブラリを自動的に`require`される。 (groupを指定したり、requireオプションをfalseにした場合以外) 2回目以降は.bundle/configにオプションが設定されているのでbundleのみで 問題ない。 23
  • 24.
    ログイン認証機能を付ける2 % rails gcontroller sessions ログイン/ログアウト用のSessionsコントローラを作成 Tutorial::Application.routes.draw do resources :blogs # 以下を追加 controller :sessions do get :login, to: :new, as: :new_session post :login, to: :create, as: :create_session get :logout, to: :destroy, as: :delete_session end end ルーティング設定 config/routes.rb % rake routes ... new_session GET /login(.:format) sessions#new create_session POST /login(.:format) sessions#create delete_session GET /logout(.:format) sessions#destroy 24
  • 25.
    ログイン認証機能を付ける3 <%= form_tag(create_session_path) do%> <% if flash[:alert] %> <%= flash[:alert] %> <% end %> <%= text_field_tag :email, nil, placeholder: "Email" %> <%= password_field_tag :password, nil, placeholder: "Password" %> <%= submit_tag "Send" %> <% end %> ログインページ作成(新規作成) app/views/sessions/new.html.erb class SessionsController < ApplicationController def create render text: "login" end def destroy render text: "logout" end end SessionsControllerにcreate/destroyメソッドを追加しておく app/controllers/sessions_controller.rb 25
  • 26.
    ログイン認証機能を付ける4 % rails gmodel user email:string salt:string password:string % rake db:migrate ユーザモデル作成 class User < ActiveRecord::Base include Passwd::ActiveRecord define_column end Userモデル編集 app/models/user.rb ユーザ作成 % rails c > user = User.new > user.email = "foo@example.com" > user.set_password("secret") > user.save > puts password 26
  • 27.
    ログイン認証機能を付ける5 class SessionsController <ApplicationController def create @user = User.authenticate(params[:email], params[:password]) if @user session[:user] = @user.id redirect_to blogs_path else flash.now[:alert] = "Email or password is incorrect." render action: :new end end def destroy session[:user] = nil redirect_to blogs_path end end ログイン/ログアウト処理 app/controllers/session_controller.rb 27
  • 28.
    ブログの作成等を制限する1 class ApplicationController <ActionController::Base protect_from_forgery with: :exception # 以下を追加 def require_logged_in if session[:user].present? begin @user = User.find(session[:user]) rescue ActiveRecord::RecordNotFound reset_session end end redirect_to create_session_path unless @user end end ログインチェックのメソッドをApplicationControllerに定義 app/controllers/application_controller.rb application_controller.rbにメソッドを定義しておくと他のコントローラか ら利用可能になる。 28
  • 29.
    ブログの作成等を制限する2 class BlogsController <ApplicationController before_action :set_blog, only: [:show, :edit, :update, :destroy] # 以下を追加 before_action :require_logged_in, only: [:new, :edit, :create, :update, :destroy] ... end new/edit/create/update/destroyにログイン制限をかける before_actionで`require_logged_in`メソッドを呼び出し、ログインしてい ない場合はログインページにリダイレクトさせる 29