Another sessions' persistence problem

Hi All,

I started out hashes intended to be populated with status info, e.g.
sort_order, for several of my tables. I started ApplicationController
with:

  session = {}
  tables = [:customers, :invoices, :payments]
  tables.each { |tbl| session[tbl] = {} }
  session[:tables] = tables

Question 1: I had to include the initialization of session, for
otherwise the assignment in the third line fails. But if Rails has a
built-in 'session' hash-like element, why is this assignment
necessary.

I checked that the above code worked by following it up with debugging
code:

    logger.debug "Application tables:"
    nTables = session[:tables].length
    (0..(nTables-1)).each { |i|
      symTbl = session[:tables][i]
      objElement = session[symTbl]
      logger.debug "\t" + symTbl.to_s + " => " + objElement.inspect
    }

The log showed that the three empty hashes were indeed created.

I followed that up with a def show_session defined with a copy of the
debugging code. When this method was subsequently invoked by some
other controller, it crashed on the second line because
session[:tables] was nil ... because session isn't persistent, I
believe.

Any ideas on how to correct this situation? I read the two recent
threads about sessions, but they don't seem to address my problem.

Thanks in Advance,
Richard

Hi~

Hi All,

I started out hashes intended to be populated with status info, e.g.
sort_order, for several of my tables. I started ApplicationController
with:

  session = {}
  tables = [:customers, :invoices, :payments]
  tables.each { |tbl| session[tbl] = {} }
  session[:tables] = tables

Is this inside of a method in your application controller? Or is it just right in the class def? If its not inside of a method then the session is not in scope. You shoudl do this with a before_filter and a method:

before_filter :setup_tables

def setup_tables
   tables = [:customers, :invoices, :payments]
   tables.each { |tbl| session[tbl] = {} }
   session[:tables] = tables
end

  Then it should work for you.

-Ezra

Hi~

Hi Ezra,

Your advice was a great boost forward. But I still have a problem.

BTW, I'm running:
WinXP-Pro/SP2, MySQL 5.0.15-nt, Ruby 1.8.2-15, Rails 1.1.4
SciTE 1.59, FireFox 1.2.0.7, Java JDK 1.5.0_06

I used the before_filter :setup_tables, :show_session That allowed my
show_session to method to work both upon entry and exit from the
ApplicationController's instantiation.

Show session also worked in app\controllers\MainController.rb#welcome

However, it failed in app\views\main\welcome.rhtml with the error:
ActionView::TemplateError (undefined local variable or method
`show_session'

So I think I need to move it's def to someplace higher than both
controllers and views. How can I do that? Or should I make it a global
function somehow?

If you don't mind an additional question, please give me your
assessment of a rescue clause I added to show_session, as shown below.

Thanks for your outstanding advice.

Regards,
Richard

class ApplicationController < ActionController::Base
  before_filter :setup_tables, :show_session
  layout "base"

  logger.debug "==================================="
  logger.debug "Entering app\\controllers\\application.rb (top level)"
  logger.debug "==================================="

  def setup_tables
    tables = [:customers, :invoices, :payments]
    tables.each { |tbl| session[tbl] = {} }
    session[:tables] = tables
  end

  def show_session
    logger.debug "Application tables:"
    nTables = session[:tables].length
    (0..(nTables-1)).each { |i|
      symTbl = session[:tables][i]
      objElement = session[symTbl]
      logger.debug "\t" + symTbl.to_s + " => " + objElement.inspect
    }
  rescue
    raise "session[:tables] => nil" unless session[:tables]
    raise "nTables => #{nTables}" unless nTables != 3
    raise "symTbl => nil for session[:tables][#{i}]" unless symTbl
    raise "objElement => nil for session[#{symTbl}]" unless objElement
  end

protected
  def sort_clause(model, column, *order)
        [snip]
  end

  logger.debug "^^^^^^^^^^^^^^^^^^^^^^^"
  logger.debug "Leaving app\\controllers\\application.rb (top level)"
  logger.debug "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv"
end

  Lets rewrite some of this code to make it clearer.

class ApplicationController < ActionController::Base
  
   before_filter :setup_tables, :show_session
   layout "base"

   def setup_tables
     tables = [:customers, :invoices, :payments].map{ |tbl| session[tbl] = {}; tbl }
     session[:tables] = tables
   end
    <snip>
end

  SO I think you can leave out the show_session method. And when you want to see whats in the session in your view use this instead:

<%= debug(session) %>

  That will show you everything that is currently in the session in a nice yaml formatted view. If you really want to be able to call the show_session method from a view then you can do that by useing helper_method like this:

   helper_method :show_session

put that in your application.rb class right after the definition of show_session.

Cheers-

-- Ezra Zygmuntowicz-- Lead Rails Architect
-- ez@engineyard.com
-- Engine Yard, Serious Rails Hosting
-- Reliability, Ease of Use, Scalability
-- (866) 518-YARD (9273)

Hi Ezra,

Thanks again for your excellent suggestions:
   <%= debug(session) %> and
   helper_method :show_session

They're nice to know. For the nonce, I want to stick with my
show_session because it focuses on the specific details I want from
session. (OK, call me "stubborn".)

And the good news (for me, anyway) is that I solved the scope problem,
thanks to Rails For Ruby: I moved the def to
app\helpers\application_helper.rb

(By the way, I deleted my previous message because I was going to
substitute the essential part of this message. Then I discovered your
reply. This electronic correspondence is great!)

Again, many thanks for taking the time to look at (and solve!) my
problem.

Best wishes,
Richard

Ezra Zygmuntowicz wrote: