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~

On Oct 14, 2006, at 6:37 PM, Richard wrote:

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 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

Hi~

On Oct 15, 2006, at 2:18 PM, Richard wrote:

show_session to method to work both upon entry and exit from the
global

  tables.each { |tbl| session[tbl] = {} }
  }

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

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 Z.
– Lead Rails Architect
[email protected]
– Engine Y., 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

This is just a test.