ハマり道の記録 (DynamicCalendarHelper)

む。昨晩やたらにハマった原因は javascript_include_tag かも。(駄目
とゆー事で現状の正常動作に影響が無いよう、プロジェクトをディレクトリごとコピって作業。ヤる事は以下か。

  • app/views/layouts/application.rhtml に javascript_include_tag 盛り込み
  • scriptaculous なナニを所定の場所に投入
  • app/helpers/calendar_helper.rb の修正 (table タグに DOM の ID を)
  • app/views/calender/index.rhtml の修正 (link_to_remote の盛り込み)

基本的には link_to_remote で index アクション実行すれば良いだけのはず。

不具合

  • で、上記修正を実装してみたら、calender な ID にコンテンツ全体が入れ子になって表示されていきます。マズい。でも、calender 部分だけを render したらナビゲートするボタンが固定になっちゃうし ...
  • もしかして calendar コントローラのアクション内で year と month の操作したら良いだけの話ですか?? ちょっと試験してみます。
  • calender コントローラに before と after というアクション追加して、@year と @month の操作をした後に render :partial => 'cal' してるんですが、invalid date と言われ怒られております。どうしたモノやら ...

てーか、ここまで苦労するんなら link_to でとりあえず OK という事に昼寝しながら決定。その内解決策みたいなナニに hit するだろうから、そん時に。
しかし、コントローラのインスタンス変数で状態を保持って微妙スギ??

と、考え始めると例えば controller なクラスのインスタンスってどういった形で管理されてるのか、が気になってきた。

最後のがビンゴっぽい気もするんですが、そうだとすればインスタンス変数で状態管理は可能なはずなんだけどなあ。てゆーかインスタンスが destroy されるのはどーゆータイミングになるのか、という話もありますな。
あ、もしかしてインスタンス変数じゃなくって session[:year] とか session[:month] とかで管理する、とか??
# 追補:結局のトコロ、コントローラなインスタンスはリクエスト単位で、な模様。

AWDwR 確認してみた方が良いな。(してない

その後

我慢ならず、integration test で確認しようとしているんですが、コントローラのインスタンス変数はどうやったら確認できるのか。

その後 2

p assign(:year) とかで見れました。やはり、とゆーかコントローラのインスタンス変数は view には渡せるんですが、ライフサイクルは request 単位の模様。がしかし、session に保管するとインスタンス変数が view に渡せない??

何故だ。

その後 3

上記は lambda が返す値を session に入れてたのが理由らしい。がしかし、次のリクエスト時には値が 0 になっております。session 上に hash は残っているのに値が 0 クリアって一体 ...

その後 4

結局、config/routes.rb の定義の問題でした。で、動作はするようになったんですが、どんどん table が小さくなっていっております。まだ正常動作にはほど遠い。

その後 5

えーと、その後 2 以降はきちんと確認取れていません。というのも問題の原因自体が config/routes.rb の map.connect の指定足らずが原因だったようで、正常に動作する状態でインスタンス変数やらその他モロモロの検証をする必要があります。

で、今んトコ原因と思われるのは config/routes.rb に以下の map.connect が足らなかった為のようです。でも routes.rb の map.connect が足らなくて sessions のナニが 0 クリアって ...
はい。rails のソース読めって事ですね。(とほほ

  map.connect 'calendar/:action', :controller => 'calendar'

ちなみに一番下にこんなのがあって

  map.connect ':controller/:action/:id'

これがあればセーフでしょう、と勘違いしていたのが原因のようです。もしかするとこの方が良いのかもしれない。

  map.connect ':controller/:action'

あと、確認のために integration な試験で使用したのが以下のコード。(幼稚スギ

test/integration/calendar_test.rb

require File.dirname(__FILE__) + '/../test_helper'

class CalendarTest < ActionController::IntegrationTest
  def test_before_next
    open_session do |sess|

      get "/"
      p assigns(:session)
      assert_equal 200, status
      assert_template 'index'

      get "/calendar/xxx"
      p assigns(:session)
      assert_equal 200, status
      assert_template 'index'

      get "/calendar/before/"
      p assigns(:session)
      assert_equal 200, status
    end
  end
end

コントローラに xxx という確認のための action も追加していたり。修正したコントローラも一応引用しときます。

app/controllers/calendar_controller.rb

class CalendarController < ApplicationController

private
  def getDatabinder
    events = Event.find(:all)

    lambda do |d|
      cell_text = "#{d.mday}<br />"
      cell_attrs = {:class => 'day'}
      events.each do |e|
        if e.startdate == d
          cell_text << e.name << "<br />"
          cell_attrs[:class] = 'specialDay'
        end
      end
      [cell_text, cell_attrs]
    end
  end

public
  def index
    @year = session[:year] = @params[:year].to_i
    @month = session[:month] = @params[:month].to_i
    @databinder = getDatabinder
  end

  def xxx
    @year = session[:year]
    @month = session[:month]
    @databinder = getDatabinder
    render :action => 'index'
  end

  def before
    session[:year] = (session[:month] == 1 ? session[:year] - 1 : session[:year])
    session[:month] = (session[:month] == 1 ? 12 : session[:month] - 1)

    render :partial => 'cal', :locals => { :year => session[:year], 
      :month => session[:month], 
      :databinder => getDatabinder }
  end

  def after
    session[:year] = (session[:month] == 12 ? session[:year] + 1 : session[:year])
    session[:month] = (session[:month] == 12 ? 1 : session[:month] + 1)

    render :partial => 'cal', :locals => { :year => session[:year],
      :month => session[:month],
      :databinder => getDatabinder }
  end

end

いちいち getDatabinder 呼び出すのも微妙。
今回の教訓は config/routes.rb はちゃんと書きましょう、だな。

とりあえず小さくなるテーブルの対処が。(吐血