完全に自分用にまとめたのですが、初心者には盲点になりそうなところが多くもしかしたら役立つかもしれないな、ということで公開。修正・アドバイス等あればコメントください。
主には、『たのしいRuby』と『Ruby on Rails4 アプリケーションプログラミング』のまとめです。
たのしいRuby
require
requireは使いたいライブラリのファイルを読み込む。
例:"uri"
メモ:以下のモジュールのincludeなどがクラスに対するものだとしたら、ファイルに対するincludeみたいなものかな?
モジュール
クラスとの違い
モジュールはメソッドを提供し、クラスに似ているが以下の点で違う
- インスタンスを作成できない
- 継承できない
includeとextend
基本的にはRailsのヘルペーみたいにどこでも(?)呼び出せる
module Test
def explain(name)
p "#{name}さん、これはテストです"
end
end
Test::explain("田中") #=> "田中さん、これはテストです"
includeすると、インスタンスメソッドに追加される
module Test
def explain(name)
p "#{name}さん、これはテストです"
end
end
class MyClass
include Test
end
test = MyClass.new
test.explain("田中") #=> "田中さん、これはテストです"
extendすると、クラスメソッドに追加される
module Test
def explain(name)
p "#{name}さん、これはテストです"
end
end
class MyClass
extend Test
end
MyClass.explain("田中") #=> "田中さん、これはテストです"
例外処理
基本系
begin
# 通常の処理
raise "メッセージ" # RuntimeErrorが発生
raise 例外クラス # 指定した例外の発生
raise 例外クラス, "メッセージ" #指定した例外を発生させ、そのオブジェクトにメッセージをセット
raise # RuntimeError
rescue
# error処理
# $で例外オブジェクトにアクセスできる
# $! => 最後に発生した例外 $@ => 最後に発生した例外の位置に関する情報
raise # $!をもう一度発生させる
ensure
# 例外の有無にかかわらず実行される処理
end
例外オブジェクト
呼び出せるメソッド
- class : 例外の種類
- message : 例外のメッセージ
- backtrace : 例外が発生した位置に関する情報
ブロック
def total(from, to)
result = 0
from.upto(to) do |num|
if block_given? # ブロックが渡されていたら
result += yield(num) # numを引数として渡されたブロックを実行
else
result += num
end
end
return result
end
p total(1, 10) # 1から10の和 => 55
p total(1, 10) { |num| num ** 2 } # 1から10の2乗の値の和 => 385
ブロックの中でbreak
を呼びと、nilになる。break 0
など値を渡すと戻り値が設定される
あとは辞書的に使おう笑
Rails アプリケーションプログラミング の学びまとめ
View
debugを使おう
debug(@items)
といった形で、変数の中身をviewに表示できる。
簡単な部分テンプレートのcapture
- @current = capture do
= "ただいまの時刻は#{Time.now}です。"
= @current
div.container = @current
Model
Validation
こうやると綺麗にかけるのか
class Book < ActiveRecord::Base
validates :isbn,
presence: true,
uniqueness: true,
length: { is: 17 },
format: { with: /¥a[0-9]/ }
validates :title
# ...(省略
データベースに関連づかないモデルを定義する
フォームからの入力を検証したい時など
# app/models/search_keyword.rb
class SearchKeyword
include ActiveModel::Model
attr_accessor :keyword
validates :keyword, presene: true
end
# record_controller
def keywd
@search = SearchKeyword.new
end
def keywd_process
@search = SearchKeyword.new(params[:search_keyword])
if @search.valid? # ここでバリデーターを呼び出す。
render text: @search.keyword
end
end
Controller
基本認証:簡易なログイン実装
ひとまず管理者のみにしたいときとか。
class CtrlController < ApplicationController
before_action :auth, only: :index
private
def auth
# 認証に使う名前とパスワード
name = 'kimuko'
passwd = '8dohardk4kfn45ngiij4359058'
#基本認証を実行
authentiate_or_request_with_http_basic('Railsbook') do |n, p|
n == name && Digest::SHA1.hexdigest(p) == passwd
end
end
end
例外処理
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
rescue_from ActiveRecord::RecordNotFound, with: :id_invalid
private
def id_invalid(e)
# 404用のビュー
render 'shared/record_not_found', status: 404
end
デフォルトではpublic/404.html
やpublic/500.html
に飛ばされる。
独自のフラッシュメッセージの追加
以下のように追加できる。
class ApplicationController < ActionController::Base
add_flash_types :info
end
複数コントローラー共通の処理
app/controllers/concerns
にまとめる
module Name
extend ActiveSupport::Concern
included do
# call_clazz
before_filter :check_logined
end
module ClassMethods
#定義
end
#インスタンスメソッドの定義
private
def check_logined
end
end
そして、読み込みたい側でinclude Name
とすればOK
ルーティング
namespaceとscopeの違い
namespace
:参照コントローラー、URLパターン、Urlヘルパーも変わる(RESTful)
scope module
:参照コントローラーは変わるが、その他は変わらない
※scope
はコントローラーは変えないが、URLだけ変える
path_name
newやeditなどの標準アクションに関連づいたURLを変更したいならば、:path_namesオプションを指定。これやりたかった...!
resources :reviews, path_names: { new: :insert, edit: :revise }
ネストを浅くするshallowオプション
resources :books do
resources :reviews, shallow: true
end
こうすると、reviews
リソースがidを受け取らない、index,new,createアクションでのみ:book_id
が入り、それ以外は、id
のみのパスが出来上がる。
さらにscopeとshallow_pathを利用すると、reviewsリソース時に、books/
ではなくb/
を指定できたりする。
scope shallow_path: :b do
resources :books do
resources :reviews, shallow: true
end
end
キャッシュについて
サイトのスケーラビリティを考えたら必須の機能。これ以外にもありそうだけど本書ではフラグメントキャッシュを利用。
基本
- cache do
= Time.new
br
ビューヘルパーcacheでキャッシュしたい領域を囲うだけ。簡単!!
同一ページでのキャッシュキー
基本的にキャッシュキーで管理しているらしいが、複数のキャッシュが同一ページにあるとキーが重複してしまう、とのこと。なので以下のように指定
- cache(suffix: 'footer') do
= Time.new
br
キャッシュキーの複数ページでの共有
同一のキャッシュキーを利用すればOK
キャッシュキーの決め方
モデルを元に
- cache(book) do
#ビュー
このようにモデルのオブジェクトを渡すとモデル名.id値-updated_at列の値
というキーを生成してくれるらしい。これなら更新しててもわかるね。
親子関係にあるモデルにおける注意点
class Review < ActiveRecord::Base
belongs_to :book, touch: true
end
このtouch: true
があれば、親のupdated_atも更新されるので最新のキャッシュを保てるとのこと。
一覧画面とかは?
- cache(books_cache_key) do
module ExtraHelper
def books_cache_key
"books-#{Book.count}-#{Book.maximum(:updated_at).to_i}"
end
end
ヘルパーを拡張して作っちゃおう。
条件つき
- cache_if(book.published <= Date.today, book)
的な。
※注意:キャッシュはメモリの上限まで累積する。最終アクセス日などから判断して定期的に削除すること