Railsインストール・プロジェクト作成
Railsインストール
$ gem install rails
プロジェクト作成
$ rails new hoge
MySQL使う場合
$ rails new hoge --database=mysql
モデル作成・マイグレーション
モデル
Controllerは複数形、modelは単数形。
$ rauls g model User name:string email:string
を実行すると、マイグレーションファイルが作成される。作成されたマイグレーションファイルをDBに反映されるために、$ rails db:migrate
を実行する。
モデルの作成・削除
$ rails g model User name:string email:string
$ rails destroy model User
マイグレーションファイル作成が不要の場合
モデル作成時のマイグレーションファイルの作成が不要な場合、--migration false
をつける。
$ rails g model User --migration false
モデルの更新
モデルのフィールドを変更したい場合、下記でマイグレーションファイルを作成する。
$ rails generate migration add_index_to_users_email
$ rails db:migrate
既存DBからプロジェクト作成する場合
Rails - schema.rb(既存DBを使ったアプリ作成)
モデルのValidation
class User < ApplicationRecord
before_save { self.email = email.downcase }
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, presence: true, length: { minimum: 6 }
end
マイグレーション
$ rails db:migrate
$ rails db:migrate RAILS_ENV=production #本番環境DB作成
$ rails db:rollback #1つ前に戻る
$ rails db:migrate VERSION=0 #最初に戻る
$ rails db:migrate:reset #DBをリセット
コントローラの作成・ルーティング
コントローラ作成・削除
$ rails g controller StaticPages home help
$ rails destroy controler StaticPage home help
ルーティング
resources :users
と書くと、usersの規定のルーティングが反映される。
Rails.application.routes.draw do
root 'static_pages#home'
get '/help', to: 'static_pages#help'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/signup', to: 'users#new'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
resources :users
resources :account_activations, only: [:edit]
end
規定のルーティング
規定のルーティングは下記。
HTTP Req | URL | action | name |
---|---|---|---|
get | /users | index | users_path |
get | /users/1 | show | user_path(user) |
get | /users/new | new | new_user_path |
post | /users | create | users_path |
get | /users/1/edit | edit | edit_user_path(user) |
patch | /users/1 | update | user_path(user) |
delete | /users/1 | destroy | user_path(user) |
rails routes
ルーティングの状態を確認できる。
$ rails routes
Link
リダイレクトのときは、hoge_urlを使って、あとは、hoge_pathを使う。
<%= link_to "About", about_path %>
root_path -> '/'
root_url -> 'http://hoge.com/'
help_path -> '/help'
help_url -> 'http://hoge.com/help'
ユーザ登録・ログイン・アクセス制限
devise(ユーザ登録・ログイン)と、cancan(アクセス制限)というgemを使うことで、実現するのが割と一般的。
Railsコマンド
Rails Commandの短縮形
$ rails g (generate)
$ rails c (console)
$ rails s (server)
$ rails t (test)
$ bundle (bundle install)
gemfile -> bundle install
$ bundle install
$ bundle install --without production
$ bundle update
rails server
--environment production
をつけると本番環境になる。
$ rails s --environment production
Scaffold
scaffoldでモデル・コントローラ・規定のルーティングとかもろもろ作成される。Migration Fileも作成されると思う。migrateでテーブルにモデルの内容が反映される。
$ rails generate scaffold User name:string email:string
$ rails db:migrate
rails console
--sandbox
を付けると、DBを更新しないモードになる。testをつけるとテスト環境になる。
$ rails c
$ rails c --sandbox
$ rails c test
irbの設定
この設定によりirbのプロンプトが簡潔な表示に置き換えられ、irbの邪魔な自動インデント機能がオフになります。
IRB.conf[:PROMPT_MODE] = :SIMPLE
IRB.conf[:AUTO_INDENT_MODE] = false
パスワードのハッシュ化
bcrypt追加
bcryptというハッシュ関数のgemが必要。
gem 'bcrypt', '3.1.11'
Modelに追記
Modelに、has_secure_password
を追加する
class User < ApplicationRecord
.
.
.
has_secure_password
end
出来るようになること
自動化半端ない。
- セキュアにハッシュ化したパスワードを、データベース内の
password_digest
という属性に保存できるようになる。 - 2つのペアの仮想的な属性 (
password
とpassword_confirmation
) が使えるようになる。また、存在性と値が一致するかどうかのバリデーションも追加される 。 -
authenticate
メソッドが使えるようになる (引数の文字列がパスワードと一致するとUserオブジェクトを、間違っているとfalseを返すメソッド) 。
ログインチェック
authenticate
メソッででチェックできる。
>>user = User.find_by(email: 'hoge@hoge.com')
>>user.authenticate(password)
true
ログインメソッド
上記ログインチェックがTrueだったら、下記でログインさせることができる。
session[:user_id] = user.id
Helperに書く例
module SessionsHelper
# 渡されたユーザーでログインする
def log_in(user)
session[:user_id] = user.id
end
end
ログイン用のSessionControllerの例
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by(email: params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
log_in user
redirect_to user
else
flash.now[:danger] = 'Invalid email/password combination'
render 'new'
end
end
def destroy
end
end
ログイン中ユーザの取得
@current_user ||= User.find_by(id: session[:user_id])
上記は、下記と同じ。
@current_user = @current_user || User.find_by(id: session[:user_id])
Helperに書く例
module SessionsHelper
# 渡されたユーザーでログインする
def log_in(user)
session[:user_id] = user.id
end
# 現在ログイン中のユーザーを返す (いる場合)
def current_user
@current_user ||= User.find_by(id: session[:user_id])
end
end
View
Form
こんな感じ。cakephpより全然いいけど、どれも似ている。<%= render 'shared/error_messages' %>
というのは、全Viewに対して有効なパーシャルを読み込んでいる。
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(@user, url: signup_path) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
<%= f.submit "Create my account", class: "btn btn-primary" %>
<% end %>
</div>
</div>
上のパーシャル
<% if @user.errors.any? %>
<div id="error_explanation">
<div class="alert alert-danger">
The form contains <%= pluralize(@user.errors.count, "error") %>.
</div>
<ul>
<% @user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
上記に対応するコントローラ
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
end
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
flash[:success] = "Welcome to the Sample App!"
redirect_to @user
else
render 'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
end
flash message
flash[:success]
でflash messageを登録できる。
Viewに表示させるためには、下記のようにする。
<% flash.each do |message_type, message| %>
<div class="alert alert-<%= message_type %>">
<%= message %>
</div>
<% end %>
下記が出力されるようになる。
<div class="alert alert-success">Welcome to the Sample App!</div>
Helper
Controllerに関連付けすることで、Controllerに対応する全てのViewでHelperを利用できるようになる。(関連付けしないとデフォルトで全てのViewで使えるのかもしれない。)
module UsersHelper
# 引数で与えられたユーザーのGravatar画像を返す
def gravatar_for(user)
gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}"
image_tag(gravatar_url, alt: user.name, class: "gravatar")
end
end
ControllerにHelperをインクルードする
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
include SessionsHelper
end
これをViewで使う。
<% provide(:title, @user.name) %>
<h1>
<%= gravatar_for @user %>
<%= @user.name %>
</h1>
Layout
<!DOCTYPE html>
<html>
<head>
<title><%= full_title(yield(:title)) %></title>
<%= csrf_meta_tags %>
<%= stylesheet_link_tag 'application', media: 'all',
'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application',
'data-turbolinks-track': 'reload' %>
<%= render 'layouts/shim' %>
</head>
<body>
<%= render 'layouts/header' %>
<% flash.each do |message_type, message| %>
<div class="alert alert-<%= message_type %>"><%= message %></div>
<% end %>
<div class="container">
<%= yield %>
</div>
</body>
</html>
パーシャル
パーシャルはcakephpのelementみたいなやつ。
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js">
</script>
<![endif]-->
<header class="navbar navbar-fixed-top navbar-inverse">
<div class="container">
<%= link_to "sample app", '#', id: "logo" %>
<nav>
<ul class="nav navbar-nav navbar-right">
<li><%= link_to "Home", '#' %></li>
<li><%= link_to "Help", '#' %></li>
<li><%= link_to "Log in", '#' %></li>
</ul>
</nav>
</div>
</header>
Asset
- app/assets: 現在のアプリケーション固有のアセット
- lib/assets: あなたの開発チームによって作成されたライブラリ用のアセット
- vendor/assets: サードパーティのアセット
Bootstrap + Sass
gem 'bootstrap-sass', '3.3.6'
$ bundle
$ touch app/assets/stylesheets/custom.scss
@import "bootstrap-sprockets";
@import "bootstrap";
Debug
debug()
をviewに追加する。
<%= debug(params) if Rails.env.development? %>
開発環境
テスト(test)、開発(development)、本番(production)がある。デフォルトはdevelopment。railsにはRailsオブジェクトがあり、env属性がある。Rails.env.test?
はテスト中ならtrueを返す。
SSL接続
本番環境のSSL接続を強制する。全てが簡単だ。httpでアクセスしたらhttpsにリダイレクトされるのかな。
Rails.application.configure do
.
.
config.force_ssl = true
.
.
end