Topic: How does one decypher code like this....Beast??

I assure you I am spending hours staring at this code and trying to imagine all possibilities of what it's trying to accomplish. This is the SHOW action for the main Beast forum controller.
I'd be happy to hire someone if my posts seem 'pesty'. I've bought every Rails book available through Amazon.com and find no examples of code such as this. My reason for learning Beast is that I'm trying to utilize their forum but feel irresponsible if I don't understand the code.
Here's the SHOW action:

  def show
    respond_to do |format|
      format.html do
        # keep track of when we last viewed this forum for activity indicators
        (session[:forums] ||= {})[@forum.id] = Time.now.utc if logged_in?
        (session[:forum_page] ||= Hash.new(1))[@forum.id] = params[:page].to_i if params[:page]
        @topic_pages, @topics = paginate(:topics, :per_page => 25, :conditions => ['forum_id = ?', @forum.id], :include => :replied_by_user, :order => 'sticky desc, replied_at desc')
      end
      format.xml { render :xml => @forum.to_xml }
    end
  end

Some babbling commentary here:
Why would someone want to move the time into an autoincrement field such as forum.id?
What is that "hash.new(1) all about? and why would they move the forum.id into it?
Thanks for any enlightenment,
Kathy

Re: How does one decypher code like this....Beast??

The code isn't updating any model attributes. Instead, the code is working with a hash in the session. Its purpose is to remember when the user last visited each forum. For instance, if the user visits forum #3 and it is now 12:30pm, then the forums hash might update to look similar to:

session[:forums] => {3 => Tue Jul 03 12:30:00 UTC 2007,
                     5 => Tue Jul 03 11:38:45 UTC 2007}

To make the discussion easier, lets break this line into two smaller pieces:
(session[:forums] ||= {})     [@forum.id] = Time.now.utc
|---------- 1 ----------|     |----------- 2 ----------|

First part:
Assign to session[:forums] its own value OR a new hash if session[:forums] has no value. This ensures that there is always a hash at session[:forums]. Also, it returns the session[:forums] hash so that a method could be called on it in the next part of the line.

Second part:
Assign a new value associated with the key @forum.id. It makes a copy of @forum.id here. This part is equivalent to calling session[:forums][3] = Time.now.utc


The next line works the same way. However, hashes will return nil by default if given an unrecognizable key. The beast authors wants the default to be the number 1 (the value given when creating the new hash).

x = hash.new
x[3]              # Returns nil

x = hash.new(1)
x[3]              # Hash doesn't know the page for forum 3 so returns 1

Vincent Woo Ruby on Rails Blog

Re: How does one decypher code like this....Beast??

Vincent,
Thank you very much for your kind reply. I visited your website and you are amazing!
Obviously, to understand a program one just can't know the meanings of the words, but have to understand the story and message.
Firstly, I see in the Beast that they have table called Sessions. Would you expect that they're writing all these values into the sessions.data TEXT field so when the user logs back in the history of their activities becomes apparent?
Your explanation of 'packing' the hashes was excellent and I followed it all except for your comment "Also, it returns the session[:forums] hash so that a method could be called on it in the next part of the line." I don't see a method at the end of the:
(session[:forums] ||= {})[@forum.id] = Time.now.utc if logged_in?
When you mention that the authors of Beast are creating a 'default' value for Hash.new(1) what is the key then? I've learned that hashes are key, value pairs that are accessed by calling hash[key] to find the value. Is ONE supposed to be a key or a value?
Thank you for your kind reply.
Kathy

Re: How does one decypher code like this....Beast??

Firstly, I see in the Beast that they have table called Sessions. Would you expect that they're writing all these values into the sessions.data TEXT field so when the user logs back in the history of their activities becomes apparent?

Correct. However, sessions are not tied to any authentication schemes. By default, authenticated or not, Rails will assign a new session to anybody that accesses the website if they don't have one already. Also, save important information elsewhere in the database. The session might expire between page views, cookies cleared by the end user, reset_session() called during the user logout process etc.

Your explanation of 'packing' the hashes was excellent and I followed it all except for your comment "Also, it returns the session[:forums] hash so that a method could be called on it in the next part of the line." I don't see a method at the end of the:
(session[:forums] ||= {})[@forum.id] = Time.now.utc if logged_in?

[]= is the method name. It's a special case where Ruby allows you to invoke it in the form [key] = value

When you mention that the authors of Beast are creating a 'default' value for Hash.new(1) what is the key then? I've learned that hashes are key, value pairs that are accessed by calling hash[key] to find the value. Is ONE supposed to be a key or a value?

In the example, 1 is the default value. There is no corresponding default key. I guess what you can do is to pretend the default value doesn't yet exist. The default value springs into action only when you try retrieving the value of a non-existent key.

blah = Hash.new(1)      # Hash is {}
blah[:key1] = :value1   # Hash is {:key1 => :value1}
blah[:key2] = :value2   # Hash is {:key2 => :value2, :key1 => :value1}

blah[:key1]             # Returns :value1
blah[:dunno]            # Returns the default value 1


# Are you confused with this form of hash creation?
# Notice the different set of parentheses.
fnord = {:key1 => :value1, :key2 => :value2}    # Hash is {:key1 => :value1, :key2 => :value2}

Vincent Woo Ruby on Rails Blog

Re: How does one decypher code like this....Beast??

Just to expand on the answer question 1, Beast actually uses ActiveRecordStore, which will stick around in the database by default. This (coupled with the fact that the user_id is stored in the table) would allow one to collect session data indefinetely.

However, it looks like sessions get swept out pretty regularly, so I guess its not being used for any kind of historical purpose. It must have  some other mysterious purpose...

Alex

Last edited by alexpt (2007-07-03 18:17:53)