logo

Archive for 11 月, 2007


シンプルな日付選択用ライブラリ「protocalendar.js」を公開しました

prototype.js ベースの日付選択用 javascript ライブラリ「protocalendar.js」を公開しました。

simple metal paper

rails や cakephp でアプリケーションを作っていて、セレクトタグでは日付を選択し辛いと感じていました。

また、オープンソースの Date Picker ライブラリでは機能不足、もしくはオーバースペック過ぎて手頃なものがないと感じていました。

そこで、社内で prototype.js ベースの日付選択用ライブラリを作ってみようということになり作ってみました。

今後もバージョンアップしていきたいと考えているので、ご意見ご要望などありましたらコメントでお願いします。

【特徴】
*prototype.js ベース(1.5 以降)。
*シンプルで軽量。
*MIT LICNESE
*16のローカライゼーションに対応。
*フォーカスでカレンダー表示。(トリガーを追加可能)
*日付フォーマットを変更可能。
*日付のラベル表示が可能。(フォーマットも変更可能)
*年・月を直接変更可能。(年選択時に前後指定年数を表示)
*カレンダーの開始曜日を変更可能。
*日本の祝日対応。(カスタマイズ可能)
*「今日」、「明日」、「明後日」などの任意の文字入力にも対応。(カスタマイズ可能)
*いくつかの標準スタイルを用意。(付属の paper, metal などの画像、 css も MIT LICNESE)
*effects.js と組み合わせてエフェクトに対応。(現在は、Appear のみ。他のエフェクトにも対応予定)
*クロスブラウザ (IE6 以降, Firefox2 以降, Safari2 以降, Opera9 以降)

【使い方はこちら】
http://labs.spookies.co.jp/static/protocalendar-js-1.0/sample/calendar_usage.html

【download はこちら】

http://code.google.com/p/protocalendar/downloads/detail?name=protocalendar-js-1.1.0.zip

【今後の展望】
*Appear 以外のエフェクトに対応。
*スタイルの追加。
*「閉じる」、「クリア」を表示するオプションの追加。

Railsの解読(1)

Railsで開発するのはもう一年たちました。 しかし、Railsの仕組みはよく分からないのです。最近LighttpdのFastCgiでRailsを動かすときに、迷いました。

週末家でいらいらして、Railsのソースコードを読んで見ました。

みんな知っているように、RailsはActiveRecord, ActiveSupport, ActionControllerとActionViewによって構成されています。ActiveRecordはO/R Mappingで、ActiveSupportはrubyを拡張するライブラリです。 Railsの中心にあるのはやはりActionControllerです。

一つのRequstを送る際に、Railsはどういう流れで処理するのかに注目しつつ、ソースコードを解読しました。

Mongrelにしても、FastCgiにしても、最初はCgiRequestを作って、Dispatcher.dispatchを呼び出します。 Dispatcher.dispatchは主に下の二行です。

controller = ActionController::Routing::Routes.recognize(request)
controller.process(request, response).out(output)


Routingはroutes.rbにしたがって、urlを解析して、controllerのクラスを返します。 

def self.process(request, response)
  new.process(request, response)
end

def process(request, response, method = :perform_action, *arguments) #:nodoc:
  initialize_template_class(response)  #ActionViewのクラスの取る
  assign_shortcuts(request, response)  #params, session, requestなどのショートカットを設定する
  initialize_current_url
  assign_names  #@action_nameの書き込み
  forget_variables_added_to_assigns                 

  log_processing
  send(method, *arguments)  #!!perform_actionの実行                 

  assign_default_content_type_and_charset
  response
ensure
  process_cleanup
end

def perform_action
  if self.class.action_methods.include?(action_name)
    #Actionの呼び出し
    send(action_name)
     #Actionの中でrenderとredirect_toが実行されなかったら、デフォルトのテンプレートを表示する
     render unless performed?
  elsif respond_to? :method_missing
    #Actionがない場合、method_missingを呼び出す
    send(:method_missing, action_name)
     render unless performed?
  elsif template_exists? && template_public?
    render
  else
    raise UnknownAction, "No action responded to #{action_name}", caller
  end
end

これでRailsの流れをちょっと捕まえました。

しかし、そんなに単純ではありません。 様々な処理が見えていません! FilterでもBenchmarkでも、Sessionでも。 いったいどこにあるのか?
答えはここです。(benchmark.rb)

module Benchmarking #:nodoc:
  def self.included(base)
    base.extend(ClassMethods)
    base.class_eval do
      alias_method_chain :perform_action, :benchmark
      alias_method_chain :render, :benchmark
    end
  end
  #省略
end

alias_method_chain :perform_action, :benchmarkをやると、下の二行と同じです。

alias_method :perform_action_without_benchmark, :perform_action
alias_method :perform_action, :perform_action_with_benchmark

これでperform_actionはテンプレートメソッドみたいに、名前変えずにbenchmarkの動作が組み込まれました。むしろ、rubyでのAOPとみなされるでしょう。
さらに、ちょっと考えてみると、perform_actionに対して、alias_method_chainは何回適応しても、うまくいけます。すっごいです!

「ModelやControllerはいつロードされましたのか?」ともう一つの疑問を抱いてきました。
答えはdependencies.rbです。DependenciesはObjectのconst_missingとrequireをオーバーライドしています。それで毎度Controllerなどをリフレクションでインスタンス化する際に(const_missingが呼び出される)、Railsのネーミングルールによって特定のフォルダーから読み込んで、ロードするのです。

これでRailsの仕組みをおおざっぱに理解できるでしょうか。 何か間違ったら、皆さんぜひ指摘してください。

Spookies Labs

Spookies Labs を公開しました。

Spookies Labs では主に技術的な話題を扱う予定です。

Spookies では ruby on rails を始めとする、多くのオープンソースフレームワーク・オープンソースライブラリを活用して、サービスを開発・提供しています。

そのため、社内で開発したライブラリ・ツールをオープンソースとして公開していくことで、少しずつではありますが、オープンソースやソフトウェア業界の発展に貢献していきたいと考えています。


©2007 spookies