TONY0922のブログ

学んだことを適当に記録していくブログです。主にRubyで仕事してます。最近はJavaScriptとObjectibe-C始めました。Titanium関連もちょいちょい触ってます。更新頻度はそんなに高くないので、ご了承下さい。

パーフェクトRuby を読んだ。

パーフェクトRuby (PERFECT SERIES 6)

パーフェクトRuby (PERFECT SERIES 6)

Ruby歴3年ですが、ここで初心に戻って、 パーフェクトRubyを読んだので、興味のあるところを 備忘録で示す。

例外処理


rescue 引数なしは Standard Error を補足

begin
    error_method # 例外発生を含むメソッド
rescue => e # standard Error とそのサブクラスを補足。

end

rescue後のraiseで同様のエラーを発生させられる。

begin
    error_method # 例外発生を含むメソッド
rescue => e
    raise # eと同じ内容の例外が発生
end

後置rescueはStandard Errorのみ補足

(例1)
raise rescue puts('error') # error (例外を補足する)

(例2)
raise Exception rescue puts('error') # これはエラーを補足しない。

メソッドで例外を補足する。

def
    error_method
rescue
    ## メソッド呼び出し時に例外発生した場合に補足
end

クラスやモジュールで例外を補足する。

class
    ## 何らかの処理
rescue
    ## クラス定義時に例外発生した場合に補足
end

例外のリトライ

rescueの中でリトライをするとbeginからやり直す。

その他

  • 例外が発生しなかった時のみ処理するelseが使用できる。

大域脱出


任意処理からの脱出

  • ネストしたループなどで一気にループを抜け出したいときはcatch,throwを使う。
  • throw時にループを抜ける箇所を指定するシンボルを指定することができる。

メソッド定義と呼び出し


メソッドのカッコ()の付け所

括弧がいらないケース

  • 戻り値が必要ない。
set_current member
  • メソッド引数がない。
member = find_menber_first

メソッド呼び出しとローカル変数

  • メソッド呼び出し(括弧なし)とローカル変数はかぶるので、注意する。 そういう時は明示的に()をつける。

ブロック

  • yealdを含むメソッドはブロックを必ず渡すこと。でないと、エラーになる。
    • 仮引数に&blockとすると、Procオブジェクトとしてブロックにアクセスできる。
  • ブロック内でnext,breakが使用できる。戻り値の返し方がそれぞれ違うので注意。
  • ブロック内の変数はスコープ外の変数にアクセスすることができる。
  • メソッド呼び出し時、実引数の先頭に「&」をつけると、Procオブジェクトをブロックとして渡せる。
people = %w(Alice Bob Charlie)
block = Proc.new{|name| puts name}

people.each %block # Alice Bob Charlie
  • ブロック引数に引数なしのメソッドを使う場合は下記の用に書ける。
container.map(&:method_name)
  • ブロックは準備 → 本質的な処理 → 後片付け といった前後の処理を共通化する際に役立つ。

    • ファイルのOpen/Close、DBへの接続/切断
  • ブロックにはブロック外の同名変数に影響を受けないブロックローカル変数が存在する。

someone = 'Dave'
    
%w(Alice Bob).each do |person; someone| # ;のあとに定義する。
    someone = person
end

someone # => 'Dave'

外部ファイルの読み込み

  • require や load は $: , $LOAD_PATH に格納されているファイル・ディレクトリを探す。

モジュール

  • クラスがモジュールを取り込んだ際、インスタンスメソッドを取り込み事ができる。
  • 特徴」と取り込むことができる。
  • extend でオブジェクトに特異メソッドを取り込むことができる。
  • クラス内でextend モジュールでクラスメソッドを定義する。
  • モジュール関数 ... サブルーチンとして利用されることを目的としたメソッド
  • autoload 必要時に読み込みする。

オブジェクト

オブジェクトのコピー

  • dup, clone でも参照先の配列の要素はコピーしない。したがって、コピー元の要素を変えた場合、コピー先の要素も変わってしまう。

Enumerable

Hash

  • Ruby1.9ではHashは順序を保持する。
  • 外部イテレータを用いると、柔軟な繰り返しが行えて、複数の配列を一度に使用したいことができる。

    • Enumerator#rewind, Enumerator#next を使う。

      IO・File

  • ファイルのオープン・クローズはブロックを使用した方が手軽に書ける。

  • 各1行の取り出しはeach_line を使う。
  • エンコーディング情報は外部と内部で所持しているため、適切に指定すること。

スレッド

あとで試す。

Struct

  • 構造体を示すクラス。
    • 使いドコロがいまいちわからん。

クラスオブジェクト

  • Class.new でクラスの定義が可能
  • Class XXX end との違いは?
    • Class.new でクラス定義するメリットはブロックでメソッドを定義するため外部スコープの変数を参照できる。
  • Class.newを定数に代入するか、変数で代入するかで挙動が変わる。
    • 定数の場合 … クラス名を持ったClassオブジェクト
    • 変数の場合 … 無名クラスができる。
  • selfがクラス自身を表す部分で定義するインスタンス変数をクラスインスタンス変数と呼ぶ。
    • selfがクラス自身を表す場所で参照可能。
    • クラス変数とは異なる。
      • クラスインスタンス変数はそのクラスのインスタンスメソッドから直接参照したり、変更したりできない。
      • クラスが継承された際に、継承したクラスから参照、変更ができない。
  • クラスメソッドはクラスオブジェクトに定義された特異メソッドである。
    • クラスの定義外でもクラスメソッドを定義することが可能。
  • インスタンスメソッドもメソッド定義式を使わずに定義可能。
    • Module#define_methodを使えば可能

メソッド探索方法

  • include module でインクルードしたクラスの一つ上の階層に無名クラスが定義される。
    • 連続でmoduleをincludeした場合は、後のmoduleが近くなる。

Module#prepend

  • メソッド実行前に処理をはさみたいときはModule#prependを使用する。
    • prependにて同名のメソッド内にsuperを組み込むことによって、prependしたクラスの前処理を挟むことが可能。

7-2 BasicObject#method_missing

  • method_missing内で存在しないメソッドを呼ぶと無限ループになってします。

7-3 eval

  • evalで文字列をそのプログラミング言語の式として評価できる。
    • 実行コンテキストを共有するために、実行中のコンテキスト内の変数を共有できる。
    • evalにてメソッド定義が可能。
      • メソッド名が違うけど、ほとんど同じような処理を行っているものの定義に有効。
      • 動的なメソッドの追加も可能。
    • あるコンテキストで定義された変数やメソッドなどをまとめたオブジェクトをBindingオブジェクトと呼ぶ。
      • コンテキストの内容を様々な場所で持ち回すことが可能。
      • eval の第2引数 もしくは Binding#evalで呼び出し可能。
    • module_eval, class_eval, instance_evalで式を評価するコンテキストとなるモジュール、クラス、オブジェクトを指定してevalすることが可能。

8-1 Procクラス

  • Proc#===でProcオブジェクトで定義したブロックを呼び出す。
    • when式ではcase式で評価したい値と\=\=\=でマッチさせたい式を書くため、Procを渡すと\=\=\=でブロックが実行されるため、ブロック内の返り値と評価させることができ、柔軟な評価式を記述することが可能。

8-2 Proc#new以外のProcオブジェクトの作り方

  • Kernel#lambda で Proc を生成可能。
    • -> が lambda のシンタックスシュガー
    • Proc#new, Kernel#proc, Kernel.lambdaでreturnやbreakの挙動が異なるので注意。
    • Kernel#lambdaは引数の数が一致していないとエラーになる。

10-1 オブジェクトについて調べる

  • インスタンス変数名の確認や更新をアクセサを無視して、行えるメソッドがある。
    • オブジェクトのインスタンス変数を確認。
      • Object#instance_variables
      • Object#instance_variable_defined?
    • オブジェクト変数の値を更新
      • Object#instance_variable_get
  • オブジェクトが持つメソッドの調べ方
    • メソッドの可視性によって、使うメソッドが異なる。
メソッド スコープ
Object#methods プライベートメソッド以外のメソッド
Object#public_methods パブリックメソッド
Object#private_methods プライベートメソッド
Object#protected_methods プロテクテッドメソッド
Object#singleton_methods 特異メソッド
  • オブジェクトが持つメソッドの調べ方 その2
    • Object#respond_to?
  • メソッドの可視性に関わらず、Object#sendでメソッド呼び出し。
    • sendは他の場所で使われている可能性があるメソッド名のため、sendエイリアスとして、使用できる。

10-2 クラスについて調べる

  • Module#ancestors で継承しているモジュールやクラスがわかる。
  • Module#included_modules でインクルードしているモジュールのみわかる。
  • Module#nesting でモジュールの階層が判明する。
  • クラスメソッドは未定義にしたり、新しく定義したりすることが可能。
  • ActiveSupport::Concern をextendしたモジュールはClassMethodsをモジュールとして定義することで、そのモジュールをincludeしたクラスにクラスメソッドを提供する。

10-3 イベントをフックする

  • クラスの継承されたタイミングやモジュールがincludeされた際にフックが可能。
    • Module#included モジュールのinclude時
    • Module#extended モジュールのextend時
    • Class#inherited クラスの継承時
  • メソッドの追加、削除、禁止時にイベントをフックすることも可能

12-1 組み込みツール

  • irb
    • irbの初期設定は .irbrc にて定義可能。
      • SAVE_HISTORY irbのコマンドを履歴として残せる。
      • LOAD_MODULES 予め読み込むライブラリを指定できる。
  • RubyGems
    • gemのコマンドに対して、常にオプションを指定できるように .gemrc を定義可能。
    • 複数あるバージョンの古い方を削除する cleanup
      • -d でドライランが可能。
    • インストールしたgemパッケージを元に戻す prinstine

14-1 標準外のツール

Bundler

  • bundle outdated はインストール済みのバージョンと最新バージョンを比較する。
  • bundle open はGemをインストールしたディレクトリでエディタを開く。
    • Gemの動作を確認したい際に便利
  • bundle console はgemを読み込んだ状態でpryを呼び出す。
  • 開発ツール系のGemはアプリケーションに読み込ませる必要はない。
    • Gemfileでrequire => false とすると、アプリに読み込まないので、 メモリの使用量を抑えることが可能。
  • bundle package でキャッシュしたGemをインストール可能
    • デプロイの度にbundle installしている時間が膨大な場合はこちらを利用すると良い。

Capistrano

  • デフォルトのデプロイ先は /u/apps/#{app_name}
  • cap -v でログを表示制御 -vv, -vvv でより詳細
  • タスクの中にTrnsactionとRollbackを載せることが可能。
  • Capistranoのフック
    • 複数登録ができる。
    • フックする内容をブロックで渡せる。
  • パスワードを書くのはセキュリティ上問題になるので、コマンドラインインターフェースを使用する。
  • 実行結果を利用して、Capistranoの処理を分岐させることが可能。
    • capture
      • 指定した:roleの最初のサーバで実行した内容を取得できる。 - サーバのディスク容量を確認して、なんらかの処理を行う等の確認ができる。
    • stream
      • 複数のサーバに継続的にアウトプットを得たいときに利用する。
        • tailを利用すると、複数のサーバのログを全部覗くことができる。

yard

  • yard diff
    • gemのバージョン間でのdiffを行ってくれる。
    • バージョンupのメソッドやクラスの増減をチェックしてくれる。

pry

  • binding.pry

    • 埋め込んだ部分のスコープでオブジェクトの内容を確認できる。
    • 変数の書き換えも可能。
  • show-source

    • gemのソースを見る。
  • show-doc
    • ドキュメントを見る。
  • edit
    • Pryからエディタを起動させて、評価することができる。
  • .pryrcで起動時にデフォルト設定をする。
    • 詳細はPryのwiki もしくは Pry::Configを参照。
  • pry-stack_explorer
    • 起動した時点での呼び出しスタックを表示して、スタックが示すコンテキストの選択と移動が可能。
      • さらにそのコンテキストのスコープで変数の確認も可能
      • デバッグや開発中のソースを追うことができる。
  • pry-debugger
    • ブレイクポイントを設定して、デバッグが可能。