LoginSignup
43
40

More than 5 years have passed since last update.

Railsメモ - 初心者を抜け出す助けになるかもまとめ

Last updated at Posted at 2016-04-19

完全に自分用にまとめたのですが、初心者には盲点になりそうなところが多くもしかしたら役立つかもしれないな、ということで公開。修正・アドバイス等あればコメントください。

主には、『たのしい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 

例外処理

application_controller.rb
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.htmlpublic/500.htmlに飛ばされる。

独自のフラッシュメッセージの追加

以下のように追加できる。

class ApplicationController < ActionController::Base
    add_flash_types :info
end

複数コントローラー共通の処理

app/controllers/concernsにまとめる

sample.rb
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列の値というキーを生成してくれるらしい。これなら更新しててもわかるね。

親子関係にあるモデルにおける注意点
review.rb
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)

的な。

※注意:キャッシュはメモリの上限まで累積する。最終アクセス日などから判断して定期的に削除すること

43
40
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
43
40