Ruby on RailsTutorial
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
Gemfilesource "https://rubygems.org"
gem "rails"
3
プロジェクト作成1
% bundle exec rails new . --skip-bundle
conflict GemfileOverwrite /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
appcontrollers コントローラ
app helpers ヘルパーappmailers メール
app
models モデル
app
views ビューbin bundle/rails/rake等のスクリプトbundle/rails/rake等のスクリプト
config 設定ファイル設定ファイルdb スキーマ/マイグレーションファイル及びSQLite DBスキーマ/マイグレーションファイル及びSQLite DBlib 独自ライブラリ/Rakeタスク独自ライブラリ/Rakeタスクlog ログファイルログファイル
public Webサーバに設定するDocumentRootWebサーバに設定するDocumentRoottest テストコード(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 endend
マイグレーションファイルの中身
11
リクエスト処理の流れ
router(routes.rb)
DBServer
controllers(controllers/*.rb)
models(models/*.rb)
views(views/*/
*.html.erb)
request routing
sql
response
12
モデルapp/models/blog.rb
class Blog < ActiveRecord::Baseend
本来はバリデーション/アソシエーション/ビジネスロジック等を書くけど、これでも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 :blogsend
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#newedit_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" endend
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) endend
app/controller/blogs_controller.rb
メソッドが無い又は空の場合はviewがレンダリングされる16
コントローラ2
メソッド 説明
#index@blogsにblogsテーブルの全てのレコードを格納してviewをレンダリングする。
#new@blogにBlogモデルのオブジェクトを生成して格納し、viewをレンダリングする。
#show先のページではメソッドが無いが実際は空のメソッドが存在する。before_actionが設定されている為、set_blogメソッドを呼び出してviewをレンダリングする。
#editshowと同様にメソッドが無いが実際は空のメソッドが存在する。こちらもbefore_actionが設定されている為、set_blogメソッドを呼び出してviewをレンダリングする。
17
コントローラ3class 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 endend
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 endend
before_actionが設定されている為、set_blogメソッドを呼び出して@blog.updateでcreateと同様にstrong parameterを通したパラメータを引数にレコードをアップデートする。成功した場合はリダイレクトし失敗した場合はeditのviewをレンダリングする。
19
コントローラ5class BlogsController < ApplicationController def destroy @blog.destroy respond_to do |format| format.html { redirect_to blogs_url } format.json { head :no_content } end endend
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 endend
ルーティング設定config/routes.rb
% rake routes... new_session GET /login(.:format) sessions#newcreate_session POST /login(.:format) sessions#createdelete_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" endend
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_columnend
Userモデル編集app/models/user.rb
ユーザ作成
% rails c> user = User.new> user.email = "[email protected]"> 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 endend
ログイン/ログアウト処理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 endend
ログインチェックのメソッドを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
Recommended