Monday, August 31, 2009

Ruby id to Object

'hello'.object_id #=> 12345

ObjectSpace._id2ref 12345 #=> 'hello'

Sunday, August 30, 2009

Ruby Curry

is_weekday = lambda { |week_day, time| time.wday == week_day }.curry

sunday = is_weekday[0]
monday = is_weekday[1]
tuesday = is_weekday[2]

case Time.now
when sunday
  puts 'Day of rest'
when monday, tuesday
  puts 'work'
else
  puts 'maybe work..'
end

TinyUrl - URL shotener

#tinytiny.rb
# My first Ruby/Sinatra app, a URL shortener.
# by Leah Culver (http://github.com/leah)
require 'rubygems'
require 'sinatra'
require 'dm-core'

# Base36 encoded
BASE = 36

class Tinytiny
  include DataMapper::Resource
  property :id, Serial
  property :url, String
end

DataMapper.setup(:default, ENV['DATABASE_URL'] || "sqlite3://#{Dir.pwd}/tiny.sqlite3")

configure do
  DataMapper.auto_upgrade!
end

get '/' do
  # Form for entering a fatty URL
  <<-end_form
  <h1>Tiny tiny URLs!</h1>
  <form method='post'>
    <input type="text" name="url">
    <input type="submit" value="Make it tiny!">
  </form>
  end_form
end

post '/' do
  # Put the fatty URL in the database and display
  tiny = Tinytiny.new(:url => params[:url])
  if tiny.save
    url = request.url + tiny.id.to_s(BASE)
    "Your tiny tiny url is: <a href='#{url}'>#{url}</a>"
  end
end

get '/:tinyid' do
  # Resolve the tiny URL
  tiny = Tinytiny.first(:id => params[:tinyid].to_i(BASE))
  redirect tiny.url
end

Thursday, August 27, 2009

get youtube bookmarklet

javascript:if%20(document.getElementById('download-youtube-video')==null%20&&%20!!(document.location.href.match(/http:\/\/[a-zA-Z\.]*youtube\.com\/watch/)))%20{var%20yt_mp4_path='http://www.youtube.com/get_video?fmt=18&video_id='+swfArgs['video_id']+'&t='+swfArgs['t'];%20var%20div_embed=document.getElementById('watch-embed-div');div_embed.innerHTML=div_embed.innerHTML+'%3Cbr%20/%3E%20%3Cspan%20id=\'download-youtube-video\'%3E%3Ca%20href=\''+yt_mp4_path+'\'%3EDownload%20as%20MP4%3C/a%3E%20(right-click%20and%20select%20%3Ci%3ESave%20'+%20(navigator.appName=='Microsoft%20Internet%20Explorer'?'target':'link')%20+'%20as%3C/i%3E)%3C/span%3E';}void(0);

Saturday, August 22, 2009

Ruby 変数

変数とはユーザ(programmer)がプロセス空間内のオブジェクトを特定するためにユーザがこれに付けるラベルである
インタプリタは変数を基にして対象のオブジェクトにアクセスし要求されている処理を実行する

Rubyでは大きさの異なる,つまりスコープの異なる複数種のラベルが用意されている
それらは大きいものからグローバル変数、定数、クラス変数、インスタンス変数、ローカル変数である

Rubyインタプリタが起動されるとOSによって1つのプロセス空間が割り当てられ
最初にClassクラスオブジェクト、ModuleクラスオブジェクトおよびObjectクラスオブジェクトが生成され
次いで標準クラスおよびユーザ定義のクラスオブジェクト群(モジュールオブジェクトを含む)が生成され
そして各クラスオブジェクト内に1又は複数のインスタンスが生成される
なおRubyにおいてプロセス空間はObjectクラスのコンテキスト空間とほぼ等価である

プロセス空間にはクラス(モジュール)、オブジェクト、メソッドによって分離される複数の解釈のコンテキストつまり壁が生成される
インタプリタは各コンテキストにおいて変数を含むプログラムを解釈する
つまりプログラムの解釈において壁の内部を基本に解釈を行い
例外的に壁を越えてくるものを参照する

ローカル変数はそれが定義されたコンテキストの中からしか参照できない変数である
インスタンス変数は対象オブジェクト内でグローバルに参照できる変数である
クラス変数はそれが定義されたクラスとそのインスタンス内でグローバルに参照できる変数である
なおクラス変数はサブクラスが新たなコンテキストを作るものではないのでそのサブクラスおよびそのインスタンスでも参照できるようになる
グローバル変数はプロセス全体からグローバルに参照できる変数である
定数はクラス変数と同じだが,コンテキストを指定することによって外から参照できる
ここでグローバルとはその変数が定義されたコンテキストに拘わらずという意味である
したがってグローバル変数はどこからでも直接参照できるが
他の変数はその参照可能範囲(スコープ)外から直接参照できない
これらの変数にはメソッドを介して参照する

Friday, August 21, 2009

American Tune by Paul Simon

AMERICAN TUNE

  (words by Paul Simon  music by JS Bach)

Many's the time I've been mistaken, and many times confused

And I've often felt forsaken, and certainly misused.

But it's all right, it's all right, I'm just weary to my bones

Still, you don't expect to be bright and Bon Vivant

So far away from home, so far away from home.

I don't know a soul who's not been battered

Don't have a friend who feels at ease

Don't know a dream that's not been shattered

Or driven to its knees.

But it's all right, all right, We've lived so well so long

Still, when I think of the road we're traveling on,

I wonder what went wrong, I can't help it

I wonder what went wrong.

      And I dreamed I was flying. I dreamed my soul rose

      unexpectedly, and looking back down on me, smiled

      reassuringly, and I dreamed I was dying.

      And far above, my eyes could clearly see

      The Statue of Liberty, drifting away to sea

      And I dreamed I was flying.

We come on a ship we call the Mayflower,

We come on a ship that sailed the moon

We come at the age's most uncertain hour

And sing the American tune

But it's all right, its all right

You can't be forever blessed

Still, tomorrow's gonna be another working day

And I'm trying to get some rest,

That's all, I'm trying to get some rest.

filename[ AMERTUNE

SS

===DOCUMENT BOUNDARY===

Wednesday, August 19, 2009

Barbar Sati

さちに髪を切ってもらった
柴咲コウのベストを聞きながら
すっかり安心して座ってられる
柴咲コウはどれも同じに聞こえる

Ruby autoload

autoloadはその定数名が参照されたときにファイルをrequireする
定数名をrequireするファイル内のクラス名とすればそのままクラスオブジェクトの呼び出しになる

#!/usr/bin/env ruby
# encoding: utf-8
class A
  def self.a
    'hello'
  end
end

#!/usr/bin/env ruby
# encoding: utf-8
$:.unshift File.dirname(__FILE__)

autoload :A, 'a'
p A.a


Monday, August 17, 2009

Twitter Stream Ruby

#!/usr/bin/env ruby
# coding: utf-8

require 'net/http'
require 'uri'
require 'rubygems'
require 'json'

USERNAME = '' # ここを書き換える
PASSWORD = '' # ここを書き換える

uri = URI.parse('http://stream.twitter.com/spritzer.json')
Net::HTTP.start(uri.host, uri.port) do |http|
  request = Net::HTTP::Get.new(uri.request_uri)
  # Streaming APIはBasic認証のみ
  request.basic_auth(USERNAME, PASSWORD)
  http.request(request) do |response|
    raise 'Response is not chuncked' unless response.chunked?
    response.read_body do |chunk|
      # 空行は無視する = JSON形式でのパースに失敗したら次へ
      status = JSON.parse(chunk) rescue next
      # 削除通知など、'text'パラメータを含まないものは無視して次へ
      next unless status['text']
      user = status['user']
      puts "#{user['screen_name']}: #{status['text']}"
    end
  end
end

Saturday, August 15, 2009

Sinatraの仕組み2

  1. get '/' do "hello" endは引数およびブロックを伴うRubyのメソッド呼び出しである
  2. それなら対応するメソッド定義があるはずだ=>base.rbの中のBaseクラスにクラスメソッドとしてある
  3. よってBaseクラスオブジェクトに対してBase.getとしてこのメソッドを呼べるが、Sinatraではトップレベルでこれを呼んでいる
  4. つまりトップレベルがBaseクラスのコンテキストにない限りそこでこれをよぶことはできない
  5. Sinatraはこの問題を解決するためにメソッドの委譲を使っている

#!/opt/local/bin/ruby
require "rubygems"
require "sinatra/base"

def get(*args, &b)
  Sinatra::Base.send(:get, *args, &b)
end

get('/'){ "hello" }


at_exit do
  ::Sinatra::Base.run!
end

Friday, August 14, 2009

Sinatraの仕組み

Sinatraではruby app.rbでWebサーバーが起動する
そしてapp.rbのトップレベルのhttpメソッド(ex.get)でhttpリクエストが扱えるようになる
まずはサーバー起動の仕組み
  1. requireしたmain.rbが読み込まれるとその実行の最後at_exitでbase.rbのSinatra::Application.run!が呼ばれる
  2. Applicationクラスは、Default,Baseの継承クラスでBaseクラス内のrun!メソッドが起動する
  3. run!メソッドは起動するHTTPサーバーを選択し,RackのRack::Handler.getを介してそのハンドラークラス(ex.Mongrelクラス)のrunメソッドを呼び出す
  4. ハンドラークラスのrunメソッドでは、対応するWebサーバのオブジェクトが生成され(ex.::Mongrel::HttpServer.new)runされる
  5. これでsocketのTCPServerオブジェクトが生成され、Clientからのリクエストをacceptできるよう待ち受けるようになる
トップレベルの仕組み
  1. main.rbでincludeされたSinatra::Delegagotは,app.rbで定義したgetなどの既定メソッドをSinatra::Applicationクラスに委譲する
  2. ApplicationのスーパークラスであるBaseクラスにはgetなどのクラスメソッドが定義されておりここにトップレベルのメソッドの引数およびブロックを渡す
browserからリクエストがあったときの挙動についてはまだ

Thursday, August 13, 2009

Ruby DSL: define_unit

module TinyUnits
  def self.define_unit(name, quantity, *aliases)
    Numeric.module_eval do
      define_method(name) { self * quantity }
      aliases.each { |ali| alias_method ali, name }
    end
    define_method(name) { |x| x / quantity }
    aliases.each do |ali|
      alias_method ali, name
      module_function ali
    end
    module_function name
  end
  private_class_method :define_unit
  
  define_unit :cm, 0.01
  define_unit :mm, 0.1.cm
  define_unit :inch, 2.54.cm, :in
  define_unit :feet, 12.inch, :ft
  define_unit :yard, 3.feet
  define_unit :mile, 1760.yard
end

1.cm # => 0.01
2.mm # => 0.002
3.ft # => 0.9144
4.mile # => 6437.376
tall = 6.ft + 2.in # => 1.8796

include TinyUnits
cm(tall) # => 187.96

Ruby DSL: コンストラクタにブロックで属性を渡す

class Person
  def initialize(&blk)
    instance_eval(&blk)
  end
  protected
  attr_accessor :name, :age, :job
end

kyo = Person.new do
  self.name = 'kyo'
  self.age = 47
  self.job = 'none'
end

p kyo # => nil
# >> #<Person:0x23898 @job="none", @age=47, @name="kyo">

access to meta class

class Object
  def meta
    class << self
      self
    end
  end
end

class Hello
  class << self
    def self.one
      puts 1
    end
  end
end

Hello.meta.one # => nil
# >> 1

ひじに膨らみが…

先週当たりから左ヒジを突くと痛みが走る
で今日見たら膨らんで水が溜まっている
ネットで調べたら肘頭滑液包炎(ちゅうとうかつえきほうえん)らしい
医者では注射器で水を抜くらしいが
これで慢性になることも
自然治癒もあるとのことなので
暫くは様子見

Wednesday, August 12, 2009

server client with socket

  1. socketをrequireする
  2. TCPServer.open{}でサーバーオブジェクトを生成してブロックに渡す
  3. 複数のclientからのリクエストに答えられるようLoopでオブジェクトが死なないようにする
  4. Thread.start(server_obj.accept){}でclientからのリクエストがある毎にスレッドを立てる
  5. clientからのリクエストの処理後はそのソケットをcloseする
  6. クライアント側ではTCPSocket.open{}でサーバーへのソケットを開く
server.rb
#!/usr/bin/env ruby
# encoding: utf-8
require "socket"

TCPServer.open "127.0.0.1", 7430 do |server|
  loop do
    Thread.start(server.accept) do |socket|
      begin
        socket.write "hello from #{socket}"
      ensure
        socket.close
      end
    end
  end
end

client.rb
#!/usr/bin/env ruby
# encoding: utf-8
require "socket"

TCPSocket.open("127.0.0.1", 7430) do |soc|
  soc.write "hello"
  puts soc.read
end

Webrick onliner

ruby -rwebrick -e 'Thread.start{ WEBrick::HTTPServer.new(:DocumentR
oot=>".", :Port=>10080, :BindAddress=>"127.0.0.1").start};gets'

Saturday, August 01, 2009

Haml::Engine

Hamlのファイルを読み込んでhtmlとして描画する方法

        when SIGNUP
          template = File.read('./views/signup.haml')
          return Haml::Engine.new(template).render
        else