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: