メグ「ねえ、最近なんか世の中景気が良さそうだから、あたしも株やってみようと思うんだけど。」

るびお「…。」

メグ「それで、折角だからデータベース作って興味ある会社のデータを管理しようと思うの。」

るびお「…。」

メグ「ジュエリーショップとかドーナツ屋さんとかに興味あるんだけど…。」

るびお「はい、はい。作れってことね、オレが。こんな感じじゃない。」

Stock = Struct.new(:name, :market, :ticker, :sector, :website, :desc) do
  def to_s
    format = <<-EOS
    %s (%s:%s)
      sec: %s
      url: %s
      des: %s
    ----------
    EOS
    format % values
  end
end

require "csv"

stocks = CSV.parse(DATA.read).map { |data| Stock.new *data.map(&:strip) }

puts stocks

__END__
Tiffany & Co., NYSE, TIF, Jewelry Retailers, www.tiffany.com
Krispy Kreme Doughnuts, NYSE, KKD, Food Retail, www.krispykreme.com
Apple Inc, NASDAQ, AAPL, Computer, www.apple.com
The Coca-Cola Company, NYSE, KO, Beverages, www.coca-colacompany.com
Google Inc, NASDAQ, GOOG, Search Engines, www.google.com

るびお「はい、プリントアウト。」

    Tiffany & Co. (NYSE:TIF)
      sec: Jewelry Retailers
      url: www.tiffany.com
      des: 
    ----------
    Krispy Kreme Doughnuts (NYSE:KKD)
      sec: Food Retail
      url: www.krispykreme.com
      des: 
    ----------
    Apple Inc (NASDAQ:AAPL)
      sec: Computer
      url: www.apple.com
      des: 
    ----------
    The Coca-Cola Company (NYSE:KO)
      sec: Beverages
      url: www.coca-colacompany.com
      des: 
    ----------
    Google Inc (NASDAQ:GOOG)
      sec: Search Engines
      url: www.google.com
      des: 
    ----------

メグ「るびお君素敵!でも、よく見ると生成したStockオブジェクトたちをstocksってローカル変数で管理してるけど、ちょっとそれってダサくない?これらはStockクラスから生成されるんだから、Stockクラスが管理するのが自然だと思うんだけど。」

るびお「…。わかったよ。じゃあ、クラス変数かクラスインスタンス変数を使って管理すればいいよ。ほら。」

Stock = Struct.new(:name, :market, :ticker, :sector, :website, :desc) do
  def initialize(*args)
    super
+   self.class.stocks << self
  end
  
  def to_s
    format = <<-EOS
    %s (%s:%s)
      sec: %s
      url: %s
      des: %s
    ----------
    EOS
    format % values
  end
  
+ def self.stocks
+   @stocks ||= []
+ end
end

require "csv"

CSV.parse(DATA.read).each { |data| Stock.new *data.map(&:strip) }

+puts Stock.stocks

__END__
Tiffany & Co., NYSE, TIF, Jewelry Retailers, www.tiffany.com
Krispy Kreme Doughnuts, NYSE, KKD, Food Retail, www.krispykreme.com
Apple Inc, NASDAQ, AAPL, Computer, www.apple.com
The Coca-Cola Company, NYSE, KO, Beverages, www.coca-colacompany.com
Google Inc, NASDAQ, GOOG, Search Engines, www.google.com

メグ「るびお君素敵!でも、こういうことってよくやるわよね。だったらモジュールに切り出して汎用的に使えるようにしてくれたらうれしいんだけど…。」

るびお「相変わらず、リクエスト多いよね。じゃあ、やってみるよ。Class.newをオーバーライドすればいいのかな…。ほら。」

+ module ObjectTrapper
+   def new(*args, &blk)
+     obj = allocate
+     obj.send(:initialize, *args, &blk)
+     objects << obj
+     obj
+   end
+   
+   def objects
+     @objects ||= []
+   end
+ end

Stock = Struct.new(:name, :market, :ticker, :sector, :website, :desc) do
+ extend ObjectTrapper
  
  def to_s
    format = <<-EOS
    %s (%s:%s)
      sec: %s
      url: %s
      des: %s
    ----------
    EOS
    format % values
  end
end

require "csv"

CSV.parse(DATA.read).each { |data| Stock.new *data.map(&:strip) }

p Stock.objects

メグ「るびお君素敵!Class.newの機能が、allocateでオブジェクトを生成して、initializeで初期化して、そのオブジェクトを返すことだから、それをシミュレートしつつも、そのオブジェクトをobjectsに格納できるようにしたのね!」

るびお「えへん。まあ、大したことじゃないよ。じゃあ実行してみるよ。ほら。」

# >> []

るびお「げっ!おかしいな。クラスのときは上手くいってたのに、Structはダメなのか…。なんかObjectTrapperのnewが呼ばれてないみたいだ…。1

メグ「るびお君の嘘つき!だめじゃないのよ。」

るびお「…。」

メグ「もう。こういうときはどうすればいいか、前に教えたよね?後ろがダメなら前に刺すのよ!」

参照:分別のあるRubyモンキーパッチャーになるために

Stock = Struct.new(:name, :market, :ticker, :sector, :website, :desc) do
+ class << self
+   prepend ObjectTrapper
+ end
  
  def to_s
    format = <<-EOS
    %s (%s:%s)
      sec: %s
      url: %s
      des: %s
    ----------
    EOS
    format % values
  end
end

require "csv"

CSV.parse(DATA.read).each { |data| Stock.new(*data.map(&:strip)) }

puts Stock.objects

# >>     Tiffany & Co. (NYSE:TIF)
# >>       sec: Jewelry Retailers
# >>       url: www.tiffany.com
# >>       des: 
# >>     ----------
# >>     Krispy Kreme Doughnuts (NYSE:KKD)
# >>       sec: Food Retail
# >>       url: www.krispykreme.com
# >>       des: 
# >>     ----------
# >>     Apple Inc (NASDAQ:AAPL)
# >>       sec: Computer
# >>       url: www.apple.com
# >>       des: 
# >>     ----------
# >>     The Coca-Cola Company (NYSE:KO)
# >>       sec: Beverages
# >>       url: www.coca-colacompany.com
# >>       des: 
# >>     ----------
# >>     Google Inc (NASDAQ:GOOG)
# >>       sec: Search Engines
# >>       url: www.google.com
# >>       des: 
# >>     ----------

るびお「ほ、ほんとだ…。ま、まあ、ちょっと不手際あったけど、オレのお陰で目的達成できただろ?感謝してる?」

メグ「…。あなた相変わらずね。でもね、あたしね、しびれ切らしちゃったから、自分でも作ってみたの。ほら。」

module ObjectTrapper
+ def objects
+   ObjectSpace.each_object(self).to_a
+ end
end

Stock = Struct.new(:name, :market, :ticker, :sector, :website, :desc) do
+ extend ObjectTrapper

  def to_s
    format = <<-EOS
    %s (%s:%s)
      sec: %s
      url: %s
      des: %s
    ----------
    EOS
    format % values
  end
end

require "csv"

CSV.parse(DATA.read).each { |data| Stock.new(*data.map(&:strip)) }

puts Stock.objects

# >>     Google Inc (NASDAQ:GOOG)
# >>       sec: Search Engines
# >>       url: www.google.com
# >>       des: 
# >>     ----------
# >>     Tiffany & Co. (NYSE:TIF)
# >>       sec: Jewelry Retailers
# >>       url: www.tiffany.com
# >>       des: 
# >>     ----------
# >>     Krispy Kreme Doughnuts (NYSE:KKD)
# >>       sec: Food Retail
# >>       url: www.krispykreme.com
# >>       des: 
# >>     ----------
# >>     The Coca-Cola Company (NYSE:KO)
# >>       sec: Beverages
# >>       url: www.coca-colacompany.com
# >>       des: 
# >>     ----------
# >>     Apple Inc (NASDAQ:AAPL)
# >>       sec: Computer
# >>       url: www.apple.com
# >>       des: 
# >>     ----------

__END__
Apple Inc, NASDAQ, AAPL, Computer, www.apple.com
The Coca-Cola Company, NYSE, KO, Beverages, www.coca-colacompany.com
Krispy Kreme Doughnuts, NYSE, KKD, Food Retail, www.krispykreme.com
Tiffany & Co., NYSE, TIF, Jewelry Retailers, www.tiffany.com
Google Inc, NASDAQ, GOOG, Search Engines, www.google.com

るびお「ObjectSpace…。」



(追記:2013-09-12) 一部コードを修正しました(initializeの削除)。


=== Ruby関連電子書籍100円で好評発売中! ===

M’ELBORNE BOOKS

ruby_trivia ruby_parallel rack


  1. どなたか理由を教えて下さい!


blog comments powered by Disqus
ruby_pack8

100円〜で好評発売中!
M'ELBORNE BOOKS