組織選択ウィンドウのレンダリングを遅延させて表示速度改善

組織選択ウィンドウやグループ選択ウィンドウは、組織選択ボタンとかを押したらすぐに使えるように、
一番最初(mainとか)でレンダリングしておく必要があるが普通にやろうとすると、
組織選択ウィンドウをレンダリングするまで全体も描画されず非常に表示が遅かった。


そこで、組織選択ウィンドウのレンダリングをAjaxUpdaterで非同期に実施するようにしたところ
初期画面表示に約5秒かかっていたところ、1秒程度に改善された。


(修正前) main.rhtmlにそのまま記述

c<div id="search_result_area"></div>
<script type="text/javascript">
  <%# 初期表示用検索実行 %>
  <%= remote_function(
        :url => {:controller => '/sample/hoge', :action => 'search'}, 
        :update => 'search_result_area') %>
</script>

<%# 組織選択ウィンドウ %>
<%=
  render_organization_select_window({
    :element_id => 'hoge_organization_select_window',
    :options    => {
      :prefix   => 'hoge_org_select_',
    },
    :title      => '組織選択',
    :variable   => 'rubricks.sample.hoge_org_select_window',
  })
%>
・・(以下略)・・

(修正後) main.rhtmlから別rhtmlに切り出して、Ajaxで読み込み

=== main.rhtml ===
<div id="search_result_area"></div>
<script type="text/javascript">
  <%# 初期表示用検索実行 %>
  <%= remote_function(
        :url => {:controller => '/sample/hoge', :action => 'search'}, 
        :update => 'search_result_area') %>
</script>

<%# 組織選択ウィンドウ用 %>
<div id="hoge_window_org_select_area"></div>
<script type="text/javascript">
  new Ajax.Updater($("hoge_window_org_select_area"), 
    "<%= url_for(:controller => "/sample/hoge", :action => "main_window_org_select") %>",
    {evalScripts:  true}
  );
</script>



=== main_window_org_select.rhtml ===
<%# 組織選択ウィンドウ %>
<%=
  render_organization_select_window({
    :element_id => 'hoge_organization_select_window',
    :options    => {
      :prefix   => 'hoge_org_select_',
    },
    :title      => '組織選択',
    :variable   => 'rubricks.sample.hoge_org_select_window',
  })
%>
・・(以下略)・・


初期画面での検索処理が終わるとすぐその画面は表示されて、
組織選択ウィンドウのレンダリングは非同期で裏で実行される。
勿論、非同期でレンダリングしている最中は組織選択ウィンドウは使えないが
初期画面表示直後に組織選択ボタンを使わせるようなケースでなければ有効と思う。


ちなみに、非同期レンダリング中に組織選択ボタンを押した場合、モーダル状態+ウィンドウなしになるが、レンダリングが終わるとモーダルが解けるので、もう一度組織選択ボタンを押せばOKであった。

RubyWorld Conference 2009 メモ(1)

RubyWorld Conference

特に印象に残った話

GWebLink-Neo CMS : 富士通四国システムズ

2001年からやってて2009年4月現在318システム稼働中とのこと。
CMS(ブラウザUI)だけじゃなくて、デジタルサイネージ(データ配信)でイオンモールとかみずほ銀行金利ボードなんかもやっているとのこと。
直近の50案件(商談)の内容を見てみると、言語やプラットフォーム指定は減少傾向・OSS利用できる機会は増加傾向ということで、特にASPSaaSの案件では機能のみに注目しているとのこと。

  • 開発言語指定
    • 96% 不問
  • 導入環境指定
    • 84% 不問
    • 16% ASP
  • プラットフォーム指定

課題

  • Word/Excelの読み込み/出力(連携指定ありが30〜40%で増加傾向)
  • 帳票用のPDF出力
  • Windows認証、ActiveDirectory連携


Rails用の高機能帳票PDFプラグイン作れば商売になるかも?w

楽天

楽天Rubyを推している理由=「日本発世界へ」という理念が共通。Rubyの信念に楽天の経営層が共感したそうな。
トップダウンで適用指示してもらえるといいよね^^;
Ruby適用範囲広がってるとのこと。
my Rakuten - 楽天が提供するmyポータル
楽天では、どのページにどの言語を使っているとか基本的には公表できないそう。(複数の言語で開発しているということですね)
画面編集のツールをRailsで作成。
ROMA=分散データストア
Fairly=分散処理システム
楽天=ユーザ数4600万人、商品数3千万、日商30億 →分散のシステムは必須。
→分散システムがここでできると他のエンタープライズ分野にも広がるかも?
楽天技術研究所では、1/3がRuby、2/3は他の技術の研究。






どうでもいいけど、Ruby "World Conference"じゃなくて、"RubyWorld" Conferenceなのよねww (多分)

component_initでActiveRecord関連のエラー(load_missing_constant)


以下のようなエラーが発生してた。

C:\work\NetBeans65\bizca>ruby script\component_init hoge
C:/work/NetBeans65/bizca/vendor/rails/activerecord/lib/../../activesupport/lib/active_support/dependencies.rb:263:in 
`load_missing_constant': uninitialized constant Hoge::HogeReviewBugCount (NameError)
        from C:/work/NetBeans65/bizca/vendor/rails/activerecord/lib/../../activesupport/lib/active_support/dependenc
        ies.rb:452:in `const_missing'
        from ./script/../config/../install/hoge/_install/db/101_hoge_schema_101.rb:312:in `real_up'
(以下略)

該当ソースは、モデルをcreateするところ。

Hoge::HogeReviewBugCount.create(
  :dts_pjdata_project_id => pj.id, 
  :dts_pjdata_review_bug_category_id => tmp_id, 
  :count => rbc_count[i]
)

間違っているように見えないけど。。。 モデルの関連とかも間違ってないようだし。。



結論:modelのファイル名が間違ってた。
(正)hoge_review_bug_count
(誤)hoge_reviewe_bug_count


......orz

 Rails+MySQLで日付指定

こんな感じのフォームがあったとして、年月とか日付を指定してDBから値を取ると。


画面側からわたってくるパラメータはこんなかんじ

"conditions"=>{"trails_select"=>"month", "select_year"=>"2009", "select_month"=>"7"}
"conditions"=>{"trails_select"=>"term", "to_date"=>"2009/07/31", "from_date"=>"2009/07/01"}


方法は大きく分けて、DBの型をDateでやるか文字列にするか2通りあるっぽい。

(1)Date型

SQL的にはこんなかんじ。7/23以降のレコードを取得。

 select * from hoge where created_at >= '2009-07-23';

ruby側は、パラメータからDate型を作ってあげる。
ちなみにnewするときの日に-1を指定すると、その月の最終日が取れる。
Date型そのままでもOKだけど、conditionsを(デバッグとかで出力して)
見やすいようにstrftime掛けている。
(これならDate型にしないでStringで連結の方がいいかも)

      current_year = params[:conditions][:select_year].to_i
      current_month = params[:conditions][:select_month].to_i
      from_date = Date.new(current_year, current_month,1).strftime("%Y-%m-%d")
      #日付指定だと00:00:00扱いになるので、翌月1日(00:00)未満という指定にする
      to_date = Date.new(current_year, current_month + 1,1).strftime("%Y-%m-%d")
      #最終日を指定すると含まれなくなってしまう
      #to_date = Date.new(current_year, current_month, -1).strftime("%Y-%m-%d")
      conditions = [""]
      conditions[0] += " created_at >= ? AND created_at < ?"
      conditions << from_date
      conditions << to_date

(2)文字列型

MySQLのdate_format関数を使って、DB側を文字列にする方法。

 select * from hoge where date_format(created_at,'%Y-%m-%d') >= '2009-07-23';

今回の場合は、パラメータが「2009/07/23」という形式で渡ってくるので、date_formatの方も
/区切りにしてあげる。

        to_date = params[:conditions][:to_date]
        conditions = [""]
        conditions[0] += " date_format(created_at,'%Y/%m/%d') <= ? "
        conditions << to_date

参考リンク
http://private.ceek.jp/archives/002738.html

RailsアプリでJavascriptライブラリを使用してグラフ描画その2

前回のやつをちょびっと改良して、描画する系列を動的に増やしたりできるようにしてみる。

コントローラ

action内で配列をto_jsonしてインスタンス変数に格納。今回は2つの商品の月別売上推移みたいなイメージ。
配列の頭(index=0)が系列名、以後は値となるみたい。
以下の2つをインスタンス変数に設定する。
(1)グラフの値の配列 の配列
 中の配列が、1つの系列を示す(index=0が系列名、以後は値)。
(2)グラフのオプションを示すHash
 オプション詳細については折線グラフ - Javascriptライブラリ - HTML5.JPを参照。
 上記ページのサンプル(JS)ではハッシュのキーが変数っぽくなっているが、文字列にする必要あり。

    @hoge_array = []
    arr1 = ['商品A', 20, 58, 40, 14, 38, 20, 40]
    arr2 = ['商品B', 10, 14, 58, 80, 70, 90, 20]
    @hoge_array << arr1
    @hoge_array << arr2

    @hoge_params = {
      'x' => ["曜日", "", "", "", "", "", "", ""],
      'y' => ["注文数(個)", 0, 20, 40, 60, 80, 100],
      'yMax' => 100,
      'yMin' => 0,
      'lineWidth' => [1,2],
      'dotRadius' => [3,4],
      'dotType' => ["disc", "square"]
    }

  end

JS

処理本体。引数が可変長なのでargumentで対応。
// 第1引数(必須):グラフを描画するcanvas要素のID
// 第2引数(必須):描画するグラフの値配列の配列 のJSON
// 第3引数(オプション):X軸やY軸などグラフのオプションパラメータ のJSON
ちょっとはまった箇所として、evalでパースするときに"(" ")"で囲ってやる必要があること。
単純にパラメータのJSONを eval(param_json)てかんじにすると、invalid labelっていうエラーになっちゃう。
(evalの問題らしい。参考:JSONをevalした時のエラー「invalid label」について - 悲喜交々 -へたれの技術メモ置き場-)

<script type="text/javascript">
Object.extend(rubricks.hoge ,{
  draw_graph_line :function() {
    if (arguments.length < 2) {return;}
    var lg = new html5jp.graph.line(arguments[0]);
    if( ! lg ) { return; }
    var items = eval("(" + arguments[1] + ")");
    if (arguments[2] == null) {
      lg.draw(items);
    } else {
      var params = eval("(" + arguments[2] + ")");
      lg.draw(items,params);
    }
  }
});
</script>

View

描画したい箇所にcanvas要素を書くところは変わらず。

<div>
  <canvas width="400" height="300" id="line_sample3"></canvas>
</div>

アクションからのインスタンス変数をto_jsonしたものを引数として、上記のJSを実行。
グラフのオプション指定する場合は引数3つ、オプション指定なしの場合は引数2つ。

<script type="text/javascript">
  // X軸、Y軸などオプションも指定する場合
  rubricks.hoge.draw_graph_line('line_sample3', '<%= @hoge_array.to_json %>', '<%= @hoge_params.to_json %>');
  // 値の配列のみを指定する場合
  //rubricks.hoge.draw_graph_line('line_sample3', '<%= @hoge_array.to_json %>');
</script>

結果

RailsアプリでJavascriptライブラリを使用してグラフ描画


結論:これは使えそう!


RailsっていうかRubricksだけどww

使ったライブラリ

Javascriptライブラリー - HTML5.JP のグラフのやつ。
HTML.JPのライブラリは、グラフの種類毎にJSファイルが分かれてる。
今回のサンプルでは折れ線。


準備

JSファイルを読み込むようにしておく。IE用にexcanvas.jsも。
Rubricksの場合はpreloadで以下のような感じ。

<!--[if IE]><%= javascript_include_tag '/javascripts/components/hoge/excanvas/excanvas' %><![endif]-->
<%= javascript_include_tag '/javascripts/components/hoge/graph/line' %>

コントローラ

action内で配列をto_jsonしてインスタンス変数に格納。今回は2つの商品の月別売上推移みたいなイメージ。
配列の頭(index=0)が系列名、以後は値となるみたい。

    arr1 = ['商品A', 20, 58, 40, 14, 38, 20, 40]
    arr2 = ['商品B', 10, 14, 58, 80, 70, 90, 20]
    @hoge_json1 = arr1.to_json
    @hoge_json2 = arr2.to_json
  end

JS

処理本体。
引数:第1=描画対象のDOM-ID。第2・第3=描画する系列用の配列(とりあえず引数で1つずつ渡してる。)。
JSONで渡してevalで配列に戻す。で、ライブラリのクラス(html5jp.graph.line)のdrawメソッドに渡す配列を組み立ててdraw実行で描画。

<script type="text/javascript">
Object.extend(rubricks.hoge ,{
  line_sample3 :function(target_html_id, obj1, obj2) {
    var lg = new html5jp.graph.line(target_html_id);
    if( ! lg ) { return; }
    var items = [
      eval(obj1),
      eval(obj2)
    ];
    //↓ベタ書きするとこんな感じ
    //var items = [
    //  ["商品A", 20, 58, 40, 14, 38, 20, 40],
    //  ["商品B", 10, 14, 58, 80, 70, 90, 20]
    //];
    lg.draw(items);
  }
});
</script>

View

まず、描画したい箇所にcanvas要素を書く。

<div>
  <canvas width="400" height="300" id="line_sample3"></canvas>
</div>

で、アクションからのインスタンス変数を引数として上記のJSを実行。

<script type="text/javascript">
  rubricks.hoge.line_sample3('line_sample3', '<%= @hoge_json1 %>', '<%= @hoge_json2 %>');
</script>

結果

デキター!