ルーティング
名前付きルート
以下のようなルート定義があった場合、名前付きルート help_path と help_url が自動的に使用できるようになる。
名前付きルートは、ルートのパスやURLが変更されても自動的に更新されるため、リンクを生成する際に非常に便利。
Rails.application.routes.draw do
root 'static_pages#home'
get '/help', to: 'static_pages#help'
end
# ビューやコントローラー内で名前付きルートを使用する例
<%= link_to 'Help', help_path %>
# フルURLを取得する場合は help_url
<%= link_to 'Help', help_url %>
基本的なルートの書き方
Rails.application.routes.draw do
# indexアクションとshowアクションだけを指定(参照のみの画面など)
resources :tweets, only: [:index, :snow]
end
-
resources
resourcesを使ってリソースを定義することができます。resourcesを使うと、RESTfulなルーティングが簡単に設定できます。resourcesを使うと、一連の標準的なRESTfulアクションに対してルートが生成されます。
GET /articles index articles#index
GET /articles/new new articles#new
POST /articles create articles#create
GET /articles/:id show articles#show
GET /articles/:id/edit edit articles#edit
PATCH/PUT /articles/:id update articles#update
DELETE /articles/:id destroy articles#destroy
-
collection
collectionルートを使用すると、リソース全体に対してのアクションを定義できます。つまり、リソースに関連する全ての要素に対して実行されるアクションです。
resources :articles do
collection do
get 'search' # /articles/search にアクセスした際のアクションを定義
get 'popular' # /articles/popular にアクセスした際のアクションを定義
end
end
-
member
memberルートを使用すると、特定のリソース要素に対してのアクションを定義できます。つまり、個々の要素に対して実行されるアクションです。
resources :articles do
member do
get 'comments' # /articles/:id/comments にアクセスした際のアクションを定義
post 'upvote' # /articles/:id/upvote にアクセスした際のアクションを定義
end
end
モデル
-
モデルの作成
$ rails generate model Micropost
-
リレーション
class Micropost < ApplicationRecord
#userに所属(belong)する
#自動的にインデックスと外部キー参照付きのuser_idカラムが追加される
belongs_to :user
end
class User < ApplicationRecord
has_many :microposts
.
.
.
end
オプション | 所要時間 | 特徴 |
---|---|---|
micropost.user | Micropostに紐付いたUserオブジェクトを返す | 返す |
ビュー
-
form_with
form_with を利用して簡単にHTMLフォームを生成することができる。
// 名前とメールアドレスを指定して、Userモデルを新規作成するサンプル
<%= form_with(model: @model_object, url: url_for_route, local: true/false) do |form| %>
<%= form.label :name %>
<%= form.text_field :name %>
<%= form.label :email %>
<%= form.text_field :email %>
<%= form.submit "Create User" %>
<% end %>
model: フォームの対象となるモデルオブジェクト
url: フォームの送信先のURL
local: true:非Ajaxの通常のフォーム、false:Ajax対応フォーム。デフォルトtrue
<% provide(:title, 'All users') %>
<h1>All users</h1>
<ul class="users">
<%= render @users %>
</ul>
<%= will_paginate @users %>
Railsは @users を User オブジェクトのリストであると解釈する。さらに、ユーザーのコレクションを与えて呼び出すと、Railsは自動的にユーザーのコレクションを列挙し、それぞれのユーザーを_user.html.erbパーシャルで出力しようとする。
コントローラー
-
Strong Parameters
paramsハッシュでは:user属性を必須とし、名前、メールアドレス、パスワード、パスワードの確認の属性をそれぞれ許可し、それ以外を許可しないようにする例
params.require(:user).permit(:name, :email, :password, :password_confirmation)
# createアクションでStrong Parametersを使う例
class UsersController < ApplicationController
.
.
def create
@user = User.new(user_params)
if @user.save
# 保存の成功をここで扱う。
else
render 'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
end
処理の流れ
コントローラーからの画面遷移
redirectメソッド route参照して アクション実行
renderメソッド route参照せずにviewを表示
テスト
- rails test: Railsアプリケーション内のすべてのテスト(ユニットテスト、統合テスト、機能テスト、モデルテストなど)を実施する
- rails test:integration: Railsアプリケーション内の統合テストのみを実行します。主にブラウザシミュレーションを用いて、ユーザーエクスペリエンスやアプリケーションのワークフローをテストします。
- rails test:models モデルに関するテストのみ実施
- rails test test/integration/users_login_test.rb 特定のテストファイルのみ実施
プロジェクトルート
└─test テスト用フォルダ
├─controllers ※コントローラのテスト
└─integration ※統合テスト
テスト用ファイル作成
$ rails generate integration_test users_edit
invoke test_unit
create test/integration/users_edit_test.rb
フィクスチャ
@user = users(:michael)
このようにメソッド名の後ろにコロン(:)とフィクスチャ名を指定することで、フィクスチャからテストデータを取得します。このような構文はRailsのテストフレームワークによって提供されているものであり、通常のメソッド呼び出しではありません。
generateコマンド
作成されるもの
コマンド名 | コントローラー | ビュー | モデル | マイグレーション | アセット | ルート | テスト | ヘルパー |
---|---|---|---|---|---|---|---|---|
model | × | × | ○ | ○ | × | × | ○ | × |
controller | ○ | ○ | × | × | ○ | ○ | ○ | ○ |
scaffold | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ |
scaffold_controller | ○ | ○ | × | × | × | × | ○ | ○ |
migration | × | × | × | ○ | × | × | × | × |
暗黙の戻り値
明示的なreturnがない場合、メソッド内で最後に評価された式の値が自動的に返される
def string_message(str = '')
if str.empty?
"It's an empty string!"
else
"The string is nonempty."
end
end
破壊的メソッド
a = [42, 8, 17]
#メソッドの戻り値はソートされた配列だが、元の変数aはそのまま
a.sort
# !をつけると元の変数そのものも更新される
a.sort!
クラスメソッド
def User.digest(string)
の部分は一見メソッドの呼び出しにも見えるが、クラスメソッドを定義している。他の言語でいう static
を表現するために 「クラス名.メソッド名」という書き方をする。
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 }
# 渡された文字列のハッシュ値を返す
def User.digest(string)
cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
BCrypt::Engine.cost
BCrypt::Password.create(string, cost: cost)
end
end
構文
ブロック構文
Rubyのメソッド呼び出しにおいて、ブロック構文を使うかどうかはそのメソッドによって異なります。
例えば、Array#eachメソッドはブロックを取ります。以下はその例です:
numbers = [1, 2, 3, 4, 5]
numbers.each do |num|
puts num
end