初めてのRubyを読んで

初めてのRuby
Ruby会議で購入した初めてのRubyを最近読み終わりました。新たに理解したことをまとめてみようと思います。

2章 配列とハッシュ

  • Ruby1.9では、ハッシュを{name:'dia',full:'DianthuDia'}と記述出来ます

4章 文字列の構築

文字列化メソッド
メソッド名 説明
to_s オブジェクトを人間に読みやすい文字列にする
to_str Stringクラスではないが、Stringクラスのようなものに定義するべきメソッド
inspect pした時に使われる、デバック用の出力
Marshal.dump 直列化(Serialize)*1する
パーセント記法

引用符が多く含まれる文字列を表記するときに便利。

記法 結果 説明
%q[d"i"a] d"i"a 文字列リテラルで式展開無効
%Q['d'#{ 'i'.next }'a'] 'd'j'a' 文字列リテラルで式展開有効
ヒアドキュメント
  • 区切り語を'(シングルクォート)で囲むと式展開無効
  • 区切り語を'(ダブルクォート)で囲むと式展開有効
  • 区切り語のクォートの前に'-'をつけると区切り語にインデント使用可(通常はインデント負荷)
unless user_id.blank?
  User.find_by_sql [<<-"SQL", user_id ]
    SELECT *
    FROM user
    WHERE id = ?
      AND modified_at <= #{DateTime.now}
  SQL
end
Ruby1.9での多言語対応

Ruby会議で聞いた事がとてもわかりやすくまとまっている。そのままの引用になってしまうので、ここではかかない。$KCODE、マジックコメント等。

6章 変数と式

多重代入

他言語のswapは以下のようにかける。

x, y = y, x
多値と配列展開
x, *y = 'd','i','a'
p y # => ["i", "a"]
name = ['d','i','a']
s1, s2, s3 = *name
p s1+s2+s3 # => dia
範囲演算子
記法 説明
a..b a-bの範囲のRangeオブジェクト
a...b a-(b-1)の範囲のRangeオブジェクト
脱出
  • breakには引数をつける事が出来る。その引数は、繰り返し構造の戻り値となる。
p loop { break 'loop break'} # => "loop break"
例外処理
begin
  # 例外発生する可能性がある処理
rescue 例外名
  # 例外発生時の処理
else
  # 例外発生しなかった場合
ensure
  # どんな場合でも実行する処理
end
大域脱出

例外処理と似たような仕組みを用いて、C言語のgotoのように大域脱出を行う。

catch(:exit) do
  (1..10).each do |i|
    (1..10).each do |j|
      puts i*j
      throw :exit if i*j >= 50
    end
  end
end

7章 メソッド

クロージャとしてのブロック
def fact
  i = 1
  return Proc.new do
    i += 1
    (1..i).inject(1) {|r,n| r*n}
  end
end

f1 = fact
p f1.call # =>  2(2!)
p f1.call # =>  6(3!)
p f1.call # => 24(4!)

f2 = fact
p f2.call # =>  2(2!)
Proc
  • ブロックとして渡されたコードをProcオブジェクトとして受け取りたい場合、仮引数の最後に&blockのように記述する。利点としては、後でそのブロックを実行することが出来る。
class Parrot
  def initialize(&block)
    @proc = block
  end

  def call
    @proc.call
  end
end

parrot = Parrot.new {puts 'オウム返し'}
parrot.call
  • Procオブジェクトをブロックとしても渡すことが出来る
proc = Proc.new {puts 'オウム返し'}
2.times(&proc)

8章 オブジェクトとクラス

super
class Child < Parent
  def foo(arg)
    super # super(arg)と同義
  end
end
特異メソッド
foo = 'foo'
def foo.bar
  p 'bar'
end
p foo.methods - foo.class.instance_methods # => ["bar"] 特異メソッド一覧
  • 特異メソッドとは特異クラスのインスタンスメソッド
  • クラスメソッドとは、Classオブジェクトの特異メソッド
  • これらのコードを使うと、ActiveSupportのcattr_accessorは以下のコードで代替出来る
class Sample
  class << self
    attr_accessor :text
  end
end

Sample.text = 'Welcome!'
puts Sample.text # => Welcome!
Module
  • 他のクラスに対してちょっとした「トッピング」を施すことが出来る
  • includeしたモジュールは、ancestorsメソッドで列挙される
  • モジュールは具体的なものではない。例えば「比べられる(comparable)」という概念を体現するオブジェクトなど存在し得ない
  • オープンクラスで既存のクラスを外部で拡張するとき、拡張部分をモジュールでまとめておく流儀がある
    • どこまでが元の機能で、どれが拡張した機能なのか判断ができるようになる

オープンクラスにそのまま追記

class String
  def puts2
    puts self*2
  end
end

"dia".puts2 # => diadia

モジュールを介して追加

module MyStringModule
  def puts2
    puts self*2
  end
end

class String
  include MyStringModule # mix-in
end
# ARなどは ActiveRecord::Base.exted MyStringModule でmix-in可能な模様

"dia".puts2 # => diadia
    • 欲しい「トッピング」をクラス自体にmix-inするのか、特定のオブジェクトにmix-inするのか決められる

特定のオブジェクトに追加

str = "Hello!"
str.extend MyStringModule

str.puts2 #=> Hello!Hello!
"Hello!".puts2 # => NoMethodError

*1:プロセスを超えてオブジェクトを渡すときに使う