Ruby勉強

インターネットの企画職な人がプログラミングを勉強するブログ

Ruby Gold 3を受ける

2.xは持っているが 日曜プログラマーRubyは業務効率化くらいでしか使ってないので 知識をアップデートする。

要項は以下

実行環境

  • 組み込み変数/定数

文法

  • リテラル
  • 変数と定数
  • 演算子
  • ブロック
  • 例外処理
  • 大域脱出
  • キーワード引数
  • ナンバードパラメータ
  • ラムダ式(->)
  • パターンマッチ
  • ヒアドキュメント

オブジェクト指向

  • メソッドの詳細
  • メソッドの可視性
  • クラスの詳細
  • クラスの継承
  • モジュールの詳細
  • Module#prepend
  • Refinements

メタプログラミング

  • eval、define_method、instance_variable_get等

組み込みライブラリ

  • よく使用されるクラス、モジュール
  • (Object、Module、Kernel、Enumerable、Comparable等)
  • 数値
  • 正規表現
  • Proc
  • Enumerator

標準添付ライブラリ

  • time、date、singleton、forwardable等

Ruby %記法

%q, %Q, % コーテーションをエスケープしてくれる。%Q, %は式展開あり

%q(ダブルコーテーションは"と書きます) #=> "ダブルコーテーションは\"と書きます"

%w,% W 配列。%Wは式展開あり

%w(aa bb cc) #=> ["aa", "bb", "cc"]

%i, %I シンボル配列。%I は式展開あり

%i(aa bb cc) #=> [:aa, :bb, :cc]

%s シンボル

%s(hogehoge) #=> :hogehoge

%x コマンド

%x(ruby -v) #=> ruby 2.1.5

%r 正規表現

str = "hoge"
%r("bar/fuga/#{str}) #=> /"bar\/fuga\/hoge/

Ruby 古いメソッドを呼び出された場合

古いメソッドを警告を出しながらも実行する方法

module Deprecator
  def deprecate(old_method, new_method)
    define_method(old_method) do |*args,&block|
      warn "Warning: #{old_method} is deprecated. Use #{new_method}()"
      __send__(new_method,*args,&block)
    end
  end
end
class A
  extend Deprecator
  def new_fuga
    "hello"
  end
  deprecate :old_fuga, :new_fuga
end
p A.new.old_fuga #=> Warning: old_fuga is deprecated. Use new_fuga()

Ruby 特異メソッドとダックタイピング

特異メソッドはこういった変数に入ったStringオブジェクトにも追加可能 ・オープンクラス ・Refinements これらを作成するほどでもない特定箇所でのメソッド利用の場合は、お手軽にこういうものが使える。 厳密なクラス定義に拠らないところが特徴。 ダックタイピング(walk とquackを振る舞う動物ならそれはもうDuckだろう)という考え方

str = "FUGA"

def str.isUpcase?
  self.upcase == self
end

p str.isUpcase? #=> true
p str.methods.grep(/^is/) #=> [:isUpcase?, :is_a?]

Ruby 無名クラス、クラス定義のもうひとつの形

無名クラス、クラス定義をフラットスコープ

# 変数にクラス定義を代入
c = Class.new(Array) do
  def my
    'Hello!'
  end
end
# それでもメソッドはつかえる
p c.new.my #=> "Hello!"
# cは無名クラス
p c.name #=> nil
# 定数に代入してみる
Myclass = c
# cの名前は MyClass
p c.name #=> MyClass

Ruby Methodクラス UnboundMethodクラス

Methodオブジェクトは、メソッドを保存でき、callで実行できる

class A
  def hoge
    puts 1
  end
end
a = A.new.method(:hoge)
a.call #=>

UnboundMethodはメソッドの付け替えが可能 同じクラス、もしくはサブクラスにしかつけかえられない

class C
  def my_method
    88
  end
end
class A
end
u = C.instance_method(:my_method)
p u.bind(C.new).call #=> 88
p u.bind(A.new).call #=> TypeError: bind argument must be an instance of C
  • self の instance_methodを指定するとメソッドをUnboundMethodとしてとりだすことができる

モジュールのメソッドを使ってbindする

module M
  def my_method
    88
  end
end
class A
end
u = M.instance_method(:my_method)
p u.bind(A.new).call #=> 88
  • 以上が成功するのは、module Mのクラスが、Moduleクラスだから。ClassのsuperclassはModuleだからだとおもう。たぶん。