Rails チュートリアル 1章 勉強メモ14

Rails チュートリアルの勉強メモ

railstutorial.jp

rails server

$ rails server

=> Booting Puma
=> Rails 5.1.7 application starting in development 
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.12.1 (ruby 2.6.2-p47), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://localhost:3000
Use Ctrl-C to stop
  • rails server で、サーバーが立ち上がる
  • http://localhost:3000 をブラウザで見てみるとデフォルトのページが確認できる

演習

ruby -v 
ruby 2.6.2p47 (2019-03-13 revision 67232) [x86_64-darwin18]

デフォルトのページに表示されているものと一緒

$ rails -v
Rails 5.1.7

デフォルトのページに表示されているものと一緒

Model-View-Controller (MVC)

Rails チュートリアルには Wikipedia のリンクが貼られている。

ja.wikipedia.org

モデルはデータ構造とその操作、ビューはそのデータの表示、コントローラーはデータ構造を扱いビューに渡すものって感じだろうか?

Hello, world!

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  def hello
    render html: "hello, world!"
  end
end

ApplicationController は ActionController:: Base を継承している。

actionpack-5.1.7/lib/action_controller/base.rb

コメントを読んでみると ApplicationController のみが ActionController:: Base を継承し、 そのほかの Controller は ApplicationController を継承するのが普通らしい。

Action はその Action のコードを実行した後 view ディレクトリの名前に対応するテンプレートをレンダリングする。 index アクションだと app/view/hoge/index.html.erb をレンダリングする。 create アクションは index とは異なり、レンダリングをせず、リソースを作成した後リダイレクトを行う。

この2つは Action Controller のGet-and-show と do-and-redirect という2つの基本的なアクションのアーキタイプである。らしい

Get-and-show は データ取って表示、do-and-redirect はアクションを実行してリダイレクトってことかな?

リクエストをなげると Router でどの controller と Action が呼び出されるか決定する。 セッションやHTTPヘッダーなどはアクセサーメソッドを通して Action で扱える。

リクエストパラメーターは params メソッドを介してハッシュで返され、利用できる。

セッションを使用するとリクエスト間でオブジェクトを保存できる。 複数のページで常に必要であまり変更のないオブジェクトを持たせておくときに使う。 知らないうちに変更される可能性のあるオブジェクトのキャッシュとしてセッションを使うのは良くない。

session[:person] = Person.authenticate(user_name, password) でセッションにオブジェクトを配置できる。 オブジェクトを消すときは nil を入れる。 または、reset_session で全セッションを削除できる。

セッションは署名付きCookie でブラウザに保存される これは、改竄される心配はないが見ることはできる。

cookie-based session に 秘密情報を入れるのはやめよう!

response は ヘッダーとドキュメントを持ち、ユーザーのブラウザに送信される response はレンダリングとリダイレクトから自動的に生成され、ユーザーは介入しない

Action Controller は 5つのレンダリングメソッドのいずれかを使用してコンテンツをユーザーに送信するらしい もっとも用途が広く一般的なのは template のレンダリング Action Pack には template をレンダリングする Action View が含まれる controller はインスタンス変数を割り当て、オブジェクトを view に渡す

Action に応じて自動的に名前に対応したテンプレートをレンダリングするが、そこに依存する必要はなく、与えられたパラメーターによってレンダリングするテンプレートが変わる場合は手動レンダリングメソッドを使用する。

テンプレートの記述など詳しくは Action::Base を読もう!

リダイレクトは、あるアクションから別のアクションに移動するために使われる 例えば、データベースにブログエントリを create で作成し、そのアクションの後、新しいエントリをユーザーに表示することができる。 DRY原則(Don't Repeat Yourself)に従っているので show アクションを再利用できる。

e-words.jp

なるほど

Action には単一のレンダリング、または単一のリダイレクトのみを含むことができ、いずれかの操作を再試行すると DoubleRenderError が発生する。 もし何かの条件でリダイレクトする必要があるときは and return を追加して実行を停止しましょう。

  • ApplicationController に戻る

  • protect_from_forgery with: :exception なに?

[1] pry(ApplicationController)> self.method(:protect_from_forgery).source_location
=> ["$HOME/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/actionpack-5.1.7/lib/action_controller/metal/request_forgery_protection.rb", 122]
  • request_forgery_protection.rb 見てみる
actionpack-5.1.7/lib/action_controller/metal/request_forgery_protection.rb @ line 123 ActionController::RequestForgeryProtection::ClassMethods#protect_from_forgery:

    122: def protect_from_forgery(options = {})
 => 123:   options = options.reverse_merge(prepend: false)
    124: 
    125:   self.forgery_protection_strategy = protection_method_class(options[:with] || :null_session)
    126:   self.request_forgery_protection_token ||= :authenticity_token
    127:   before_action :verify_authenticity_token, options
    128:   append_after_action :verify_same_origin_request
    129: end
  • options = {:prepend=>false} に {:prepend=>false} をマージしている
  • reverse なので {:prepend=>false, :with=>:exception} こうなる

  • self.forgery_protection_strategy = protection_method_class(options[:with] || :null_session)

[4] pry(ApplicationController)> show-method forgery_protection_strategy

From: $HOME/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/activesupport-5.1.7/lib/active_support/configurable.rb @ line 113:
Owner: ActionController::Base
Visibility: public
Number of lines: 1

reader, reader_line = "def #{name}; config.#{name}; end", __LINE__
  • また便利なメソッドを見つけてしまった
  • pry のものらしい?

  • 飛んでみるとconfig_accessorの一文

  • config_accessorActiveSupport::Configurable のメソッド
    • /actionpack-5.1.7/lib/action_controller/metal/request_forgery_protection.rb で使っていた
      # Holds the class which implements the request forgery protection.
      config_accessor :forgery_protection_strategy
      self.forgery_protection_strategy = nil
  • リクエストの偽造防止・・・?

  • active_support/configurable.rb のコメントを読んでみる

    • Configurable は構成オプションをハッシュとしてもつ
    • config_accessor を用いると config を介さなくても属性を参照できるようになる。
  • 今回は書き込んでいるんでself.forgery_protection_strategyは正確にはこっちか

[11] pry(ApplicationController)> show-source forgery_protection_strategy=

From: $HOME/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/activesupport-5.1.7/lib/active_support/configurable.rb @ line 114:
Owner: ActionController::Base
Visibility: public
Number of lines: 1

writer, writer_line = "def #{name}=(value); config.#{name} = value; end", __LINE__
  • protection_method_class(options[:with] || :null_session) を見る
actionpack-5.1.7/lib/action_controller/metal/request_forgery_protection.rb @ line 134 ActionController::RequestForgeryProtection::ClassMethods#protection_method_class:

    133: def protection_method_class(name)
 => 134:   ActionController::RequestForgeryProtection::ProtectionMethods.const_get(name.to_s.classify)
    135: rescue NameError
    136:   raise ArgumentError, "Invalid request forgery protection method, use :null_session, :exception, or :reset_session"
    137: end
  • : with=>:exception なので name は exception
  • name.to_s.classify = "Exception"
  • const_get でClassオブジェクトを取ってるっぽい

hiroyukim.hatenablog.jp

[9] pry(ApplicationController)> self.forgery_protection_strategy 
=> ActionController::RequestForgeryProtection::ProtectionMethods::Exception
  • self.request_forgery_protection_token ||= :authenticity_token を見る
      # Sets the token parameter name for RequestForgery. Calling +protect_from_forgery+
      # sets it to <tt>:authenticity_token</tt> by default.
      config_accessor :request_forgery_protection_token
      self.request_forgery_protection_token ||= :authenticity_token
  • RequestForgery ってなんだろ
  • 調べた

ja.wikipedia.org

techracho.bpsinc.jp

  • なるほど、ユーザーに偽造したリクエストを投げさせるのか。面白い

  • request_forgery_protection.rb でも、 authenticity_token を入れるようになってた

  • before_action :verify_authenticity_token, optionsauthenticity_token を検証してるのかな?(直訳
  • append_after_action :verify_same_origin_request

    • アクションの後に呼び出されるメソッド・・・?
      • 眠くて調べられなかった
    • verify_same_origin_request リクエストが同じ origin かを検証する?(直訳
  • めちゃくちゃ眠いのでここで終わり

  • 早く1章終わりたいけどわからないことが多すぎる