目指そうかなRubyist RSSフィード

2011-06-21

[meta] 特異メソッド  [meta] 特異メソッド - 目指そうかなRubyist を含むブックマーク はてなブックマーク -  [meta] 特異メソッド - 目指そうかなRubyist  [meta] 特異メソッド - 目指そうかなRubyist のブックマークコメント

特定のオブジェクトにメソッドを追加できる。

str = 'hello world'

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

p str.title?
p str.methods.grep(/hello/)
p str.singleton_methods

[meta] classをキーワードを使わない  [meta] classをキーワードを使わない - 目指そうかなRubyist を含むブックマーク はてなブックマーク -  [meta] classをキーワードを使わない - 目指そうかなRubyist  [meta] classをキーワードを使わない - 目指そうかなRubyist のブックマークコメント

class MyClass < Array
  def my_method
    'Hello'
  end
end

これと同じ動きをするものを、classキーワードを用いずに書く。

class Class.new(Array)
  def my_method
    'Hello'
  end
end

class MyClass < ArrayはMyClass = Class.new(Array)で書き換えできる。

[meta] TimeDateに依存したコードのテストをどう書くか?  [meta] TimeやDateに依存したコードのテストをどう書くか? - 目指そうかなRubyist を含むブックマーク はてなブックマーク -  [meta] TimeやDateに依存したコードのテストをどう書くか? - 目指そうかなRubyist  [meta] TimeやDateに依存したコードのテストをどう書くか? - 目指そうかなRubyist のブックマークコメント

class Loan
  def initialize(book)
    @book = book
    @time = Time.now
  end

  def to_s
    "#{@book.upcase} loaded on #{@time}"
  end
end

上記のコードではTime.nowが邪魔してテストできない。

次の用にコードを帰る

class Loan
  def initialize(book)
    @book = book
    @time = Loan.time_class.now
  end

  def self.time_class
    @time_class || Time
  end

  def to_s
    "#{@book.upcase} loaded on #{@time}"
  end
end

実際に使う際には、@time_classは常にnilになるので、Timeが呼ばれる。テストコードでは、@time_classにダミーの時間を挿入してテストすると良い。以下、テストコード

require 'test/unit'
class FakeTime
  def self.now
    '2011-06-21 21:14:44 +0900'
  end
end

class Test_Loan < Test::Unit::TestCase
  def test_conversion_to_string
    Loan.instance_eval { @time_class = FakeTime }
    loan = Loan.new('War and Peace')
    assert_equal "WAR AND PEACE loaded on #{FakeTime.now}", loan.to_s
  end
end

[meta] クラス名がわからないときにクラスをオープンにする  [meta] クラス名がわからないときにクラスをオープンにする - 目指そうかなRubyist を含むブックマーク はてなブックマーク -  [meta] クラス名がわからないときにクラスをオープンにする - 目指そうかなRubyist  [meta] クラス名がわからないときにクラスをオープンにする - 目指そうかなRubyist のブックマークコメント

Module#class_evalを使用する

def add_method(a_class)
  a_class.class_eval do
    def m
      'Hello'
    end
  end
end

add_method String

'a'.m # => 'Hello'