Feb 242010
 

I discovered an interesting difference between two patch levels of the same Ruby (1.8.7)

def index
 respond_to do |format|
  format.html {
   super # call the index method of the superclass
  }
 end
end

This does not produce an error in Ruby 1.8.7 patchlevel 72 (the one that happens to ship with Snow Leopard), but in Ruby patchlevel 249 (the most recent one), it tells me I’m not allowed to do this.

super called outside of method

If you think about it from an OOP perspective it actually makes a lot of sense that this would be illegal programming – super is being called from within a block that is passed to respond_to. So, although the intended meaning appears clear from the way the code is written, the Ruby devs probably saw this as something that should be prohibited and fixed Ruby to make it so. Hence, apps written by programmers unaware of this using earlier patch levels may see this after upgrading to the latest Ruby 1.8.7

 Posted by at 8:20 pm  Tagged with:
Feb 182010
 

This method was adapted from this blog post.

So, you are creating a thing (record) or maybe you are updating it. You’ve added created_by and updated_by fields to your model, and you’ve made these integers with the intention of them both being foreign keys to the Users model.

Maybe you’ve even setup a belongs_to relationsion to your User model like so:

class Thing
 belongs_to :creator, :foreign_key => ‘created_by’, :class_name => ‘User’
 belongs_to :updater, :foreign_key => ‘updated_by’, :class_name => ‘User’
end

(this way you can refer to thing.creator and thing.updater)

Now, you want to actually set these fields when you create a record or update a record. Problem is, your current_user method is a controller method, and isn’t available in your model layer.

Well, this IS a problem. There are many ways to hack it- but here’s the best approach. I’m going to do this backwards for clarity.

1. Make user_info.rb in your models directory

module UserInfo
 def current_user
  Thread.current[:user]
 end

 def self.current_user=(user)
  Thread.current[:user] = user
 end
end

2. Now you need the TrackUsers class, which is real simple. Make another file in your models class called “track_users.rb”. Notice that we’re mixing in the UserInfo module we just created.

module TrackUsers
 # mix me into the OBSERVER for any class you want to set the created_by, updated_by fields
 
 include UserInfo
 
 def before_update(record)
  record.updated_by = current_user.id if current_user
 end
 
 def before_create(record)
  record.created_by = current_user.id if current_user
 end
end

3. Make an observer class for Thing (you can make this in your models folder). Call the file “thing_observer.rb”. Notice that all this basically does is mix in the TrackUsers module.

class ThingObserver < ActiveRecord::Observer
 include TrackUsers
end

4. Setup an Observer for your (this goes inside the Rails::Initializer.run do |config| block)

 config.active_record.observers = [
  :thing_observer
  ]

5. In your ApplicationController add this:

 before_filter :set_user

 # … some more of your code …

protected
 def set_user
  if current_user
   UserInfo.current_user = current_user
  end
 end

 Posted by at 11:30 am  Tagged with:
Feb 162010
 

The referrer is the URL the user came from. (It gets passed as part of the headers to the new request). You can get it out of rails this way:

request.env[‘HTTP_REFERER’]

Or the shorter version:

request.referrer

It seems that no one noticed that “referer” is actually not a word – the correct spelling is double-R (“referrer”). request.referer and request.referrer both work, but request.env[‘HTTP_REFERRER’] does not.

 Posted by at 3:49 pm  Tagged with: