SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

japan.internet.com翻訳記事

10分でできる初めてのRubyプログラム

プログラムを拡張しながらRubyの動作を学習する

ハンドラクラスの作成

 ファイル名をRubyコードにルーティングする簡単なフレームワークができたので、HTMLファイルのハンドラクラスを作成します。このクラスは、ターゲットのファイル名に相当する少なくとも1つの引数と、追加パラメータのオプション配列を受け取るrunメソッドを実装する必要があります。クラス名は当然ながらHtmlであり、このクラスを含んでいるファイルは「html.rb」という名前で「handlers」サブディレクトリに置かれます。

class Html

  DEFAULT_BROWSER = 'firefox'

  def run file, args
    if args.empty?
      system( "#{DEFAULT_BROWSER} #{file}" ) 
    else
      dispatch_on_parameters file, args
    end
  end

  def dispatch_on_parameters file, args
    cmd = args.shift
    send( "do_#{cmd}", file, args )
  end

  def do_opera file, args=nil
    system( "opera #{file}  #{args}" )
  end

  def do_konq file, args=nil
    system( "konqueror #{file}  #{args}" )
  end
end

 このコードでは、まずデフォルトブラウザの定数を定義しています。追加の引数が省略されると、ターゲットファイルはFirefoxで起動されます。なお、場合によってはこれを変更して実行コマンドを定義する必要があることに注意してください。私のUbuntuマシンでは、明示的なパスなしでFirefoxを実行し、ブラウザを立ち上げることができます。しかし、例えばWindowsの場合は、実行ファイルへのフルパスが必要な可能性があります。

 追加のパラメータがある場合、rundispatch_on_parametersを呼び出します。dispatch_on_parametersargs配列の先頭のアイテムを取り出し、それを使ってメッセージ文字列を動的に作成します。すべてのRubyオブジェクトにはsendメソッドが組み込まれています。このメソッドを使用すると、オブジェクトに明示的にメッセージを送信できます。ここで行っているようにメソッドを単独で使用すると、現在のオブジェクトを受け取るものとみなされます。つまり、コードは自身に対してメッセージを送信します。

 実際の引数の前にdo_を追加しているのは、メソッド名の重複を防ぐためです。例えば、先頭の引数がexitだったとしても、おそらく、Rubyのexitメソッドを呼び出すつもりではないでしょう。do_exitを呼び出すことで、正しい動作を決定できます。

 このハンドラコードは、パラメータ処理の可能性を示すちょっとした例にすぎません。現状でも、ターゲットのHTMLファイルをデフォルトブラウザで起動したり、特定のブラウザで起動したりできます。

$ ./go index.html opera
$ ./go index.html konq

時間外の作業でさらなる改善

 教育的で実用的なサンプルができ上がりましたが、これを少しだけ掘り下げてみましょう。この作業を行うと10分の目安は過ぎてしまいますが、それだけの価値はあります。

 標準のRubyディストリビューションには、あらゆる種類のタスク用の豊富なライブラリが含まれています。その中で最も興味深いものの1つが、Sean Russellが開発したREXMLです。REXMLは純粋なRubyで作成されているXMLパーサーです。REXMLを使用すると、通常のW3C DOM APIではなく、RubyスタイルのAPIを使ってXMLを操作できます。Seanの功績はすぐにRubyの標準ライブラリの一部になりました。

 話を簡単にするために、今回のサンプルのHTMLファイルではXHTMLを使用する必要があります。REXMLが処理するのはXMLのみだからです(Hpricotのように、ほぼ任意のHTMLを処理できる非常に優れたRubyツールもありますが、別のライブラリをインストールする必要があり、その説明はこの記事の範囲を超えています)。整形式のXHTMLソースになっている場合には、サンプルのHTMLハンドラでファイル分析を実行できます。Htmlクラスの最後に次のコードを追加すると、XHTMLに関する簡単なレポートを生成できます。

def do_report( file, args=nil )
  require 'rexml/document'
  begin 
    dom = REXML::Document.new( IO.read( file ) )
    if args.empty?
      puts basic_xhtml_report( dom )
    else
      puts report_on( dom, args.first )
    end
  rescue Exception
    warn "There was a problem reading '#{file}':\n#{$!}" 
  end
end

def report_on dom, element
  els =   dom.root.elements.to_a( "//#{element}" )
  "The document has #{els.size} '#{element}' elements" 
end

def basic_xhtml_report( dom ) 
  report = []
  css = dom.root.elements.to_a( '//link[@rel="stylesheet"]' )
  unless css.empty?
    report << "The file references #{css.size} stylesheets" 
    css.each do |el|
      file_name = el.attributes['href']
      file_name.gsub!( /^\//, '')
      unless File.exist?(file_name)
        report << "*** Cannot find stylesheet file '#{file_name}'" 
      end
    end
  end

  js = dom.root.elements.to_a( '//script' )
  unless js.empty?
    report << "The file references #{js.size} JavaScript files" 
    js.each do |el|
      file_name = el.attributes['src']
      file_name.gsub!( /^\//, '')
      unless File.exist?(file_name)
        report << "*** Cannot find JavaScript file '#{file_name}'" 
      end
    end
  end

  report.join( "\n" )
end

 ここでは多くの処理が行われていますが、重要なのはdo_reportメソッドです。このコードではREXMLのDocumentオブジェクトを作成し、それをdomに割り当てています。余分な引数がない場合は、基本のレポートが得られます。それ以外の場合は、特定の要素について簡単な調査が行われます。

 report_onメソッドはドキュメント引数と要素名を受け取り、REXMLのXPath機能を使ってその要素の使用頻度を見つけます。これはあくまでも初歩にすぎませんが、デモンストレーションと、プログラミングの出発点としての役割は十分に果たしています。

 basic_xhtml_reportメソッドも同様ですが、このメソッドは特定の要素のセットに焦点を当てています。REXMLを使ってすべてのCSSおよびJavaScript参照を見つけ、Fileクラスを使って参照されているファイルの有無を確認します。これも複雑なものではありませんが、プロジェクトの機能拡張に役立っています。

最小限の枠組みで簡潔かつ表現豊かなコードを作成

 これまでの説明で、以下に示すようなRubyの特筆すべきいくつかの機能について理解できたことでしょう。

  • Rubyは基本的にオブジェクト指向の言語であり、「メッセージに応答するオブジェクト」を主要な概念としています。
  • Rubyは強力な動的型を採用しています。「型」の概念は、特定のクラス名や継承階層よりもむしろ、オブジェクトが実行できる動作に基づきます。オブジェクトの動作は、メッセージとメソッドのリテラルマッピングに限定されません。動作が実行時に動的に構成されることもあります。
  • Rubyクラスはオープンです。コアクラスの動作を、アプリケーションにとって適切だと思われる動作に自由に変更できます。

 オープンなクラスと動的な動作の組み合わせによって、最小限の枠組みを利用して、簡潔かつ表現豊かなコードを作成できます。Rubyは陰からあなたのコーディングを支えてくれます。

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
japan.internet.com翻訳記事連載記事一覧

もっと読む

この記事の著者

japan.internet.com(ジャパンインターネットコム)

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

James Britt(James Britt)

アリゾナ州スコッツデールでRubyコンサルティング会社のNeurogamiを経営。仕事でRailsやNitroのアプリケーションを作成していないときは、Ruby-Doc.orgとRubyStuff.comの運営に携わる。2001年以来Rubyコミュニティで活動し、Rubyに関する書籍を多数執筆。米国およびヨーロッパのRubyカンファレンスで講演し、Phoenix Ruby Users Groupのコーディネータを務める...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/1528 2007/07/26 08:09

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー