Tatva-Artha

meaning of "it"

Ruby Authlogic: lazy initialization based on defined?() call

without comments

What is the difference between following two versions of code?

  # Version: V1
  def current_user_session
    return @current_user_session if defined?(@current_user_session)
    @current_user_session = UserSession.find
  end

This is very similar to following code:

  # Version: V1
  def current_user_session
    unless @current_user_session
      @current_user_session = UserSession.find
    end
    @current_user_session
    # the above code could also be written as: @current_user_session ||= UserSession.find
  end

The difference is that V1 optimizes the code is by making that expense “UserSession.find” query only once per lifetime of enclosing class (which, if you’ve used authlogic, you recognize that it is the ApplicationController class). Then V2 version is a bit inefficient in that if the UserSession.find happens to be nil (when the user is not logged in), it continues to call UserSession.find each time this method is called. Fair enough.

However, this messes up your test if you aren’t writing your test with this fact (the first call to current_user_session method will fix the value of @current_user_session and cannot be changed for the entire test run) in mind.

Consider this test, which passes:

  # Test for when "logout" is invoked, the user-session is properly destroyed and user is redirected
  context "with a logged-in user" do
    setup do
      User.create(:username => "foo", :email => 'foo@company.com', :password => "secret", :password => "secret")
      UserSession.create(:username => "foo", :password => "secret")
      assert controller.logged_in?
    end
    should "destroy session and redirect to root page on logout" do
      post :destroy
      assert_nil(UserSession.find)
      assert_redirected_to root_url
    end
  end

Now, if you introduce a print statement to print the current_user_session after the user is logged in, it will mess up the test and your test will fail:

  # Test for when "logout" is invoked, the user-session is properly destroyed and user is redirected
  context "with a logged-in user" do
    setup do
      User.create(:username => "foo", :email => 'foo@company.com', :password => "secret", :password => "secret")
      # The following line is to make sure user is not logged in initially
      # However, this line will end up calling controller.current_user_session and will fixate @current_user_session to nil for the rest of the test !!!
      assert_nil controller.logged_in?
      UserSession.create(:username => "foo", :password => "secret")
      assert controller.logged_in?
    end
    should "destroy session and redirect to root page on logout" do
      post :destroy
      assert_nil(UserSession.find)
      assert_redirected_to root_url
    end
  end

I can see the reasoning for V1 but I still prefer V2, even though it is little ‘inefficient’.

Written by Sharad

November 12th, 2009 at 10:31 pm

Posted in All

Ruby ActiveRecord: How to implement has_few using has_one and belongs_to

without comments

Google search for has_one vs. belongs_to reveals that the concept is a little confusing and it takes some practice for it to settle in. From Ruby Doc, it appears that in a one-to-one cardinality, we are free to choose which class holds “has_one” and which holds “belongs_to”, with belongs_to class’s database table schema holding the foreign key relationship.

Depending on your business case, one object comprises of other and hence the comprising object ends up having “has_one” side of it. For example, a mortgage application has a borrower_profile. And hence, one can say that borrower_profile belongs to a mortgage application. This is modelled as:

class MortgageApplication
  has_one :borrower_profile
end
class BorrowerProfile
  belongs_to :mortgage_application
end

So far, it’s good.

However, what happens when a mortgage application allows a co-borrower profile? Now we have one-to-TWO relationship that we need to model. One way to model this would be to think of it as one-to-many relationship and add custom validation to ensure that there are a maximum of 2 borrowers for a given mortgage application.

class MortgageApplication
  has_many :borrower_profiles, :order => "borrower_order ASC"
end
class BorrowerProfile
  belongs_to :mortgage_application
end

The :o rder option is needed to ensure that first item in list is the borrower and second item is the co-borrower.

That could work. But, strictly speaking a mortgage application has-one borrower and has-one co-borrower. So, can we model it using has-one/belongs-to? Let’s try.

class MortgageApplication
  has_one :borrower_profile # default: table = borrower_profiles, foreign_key = mortgage_application_id
  has_one :coborrower_profile, :class_name => "BorrowerProfile", :foreign_key => :mortgage_application_id
end
class BorrowerProfile
  belongs_to :mortgage_application
end

The above code won’t work since both borrower_profile and coborrower_profile are being looked up using same foreign key. The problem here is that MortgageApplication needs to foreign key to refer to each of the borrowers. The problem can be resolved by keeping the foreign keys in the mortgage_applications table instead of borrower_profiles table, effectively flipping the has-one/belongs-to relationship. Here we go:

class MortgageApplication
  belongs_to :borrower_profile # default: table = "BorrowerProfile", foreign_key = "borrower_profile_id"
  belongs_to :coborrower_profile, :class_name => "BorrowerProfile", :foreign_key => "coborrower_profile_id"
end
class BorrowerProfile
  has_one :mortgage_application
end
 
# Problem: coborrower.mortgage_application will always be null

The above will solve the problem with mortgage_application pointers to borrower_profile. However, bi-directional relationship from borrower to mortgage-application will only work for primary borrower and not for co-borrower. This is because the lookup for mortgage-application from borrower model will always be attempted using foreign-key: borrower_profile_id.

So, we do the following:

class MortgageApplication
  belongs_to :borrower_profile # default: table = "BorrowerProfile", foreign_key = "borrower_profile_id"
  belongs_to :coborrower_profile, :class_name => "BorrowerProfile", :foreign_key => "coborrower_profile_id"
end
class BorrowerProfile
  has_one :mortgage_application
  # coborrower will use following reference to mortgage-application
  has_one :comortgage_application, :class_name => "MortgageApplication", :foreign_key => "coborrower_profile_id"
end

The above code solves that problem of reverse reference from borrower-profile to mortgage-application for both borrower as well as co-borrower. The only wrinkle is that when looking up mortgage application for co-borrower, we have to use comortgage_application reference. This wrinkle could be wrapped inside the object by overriding “mortgage_application” method.

As we can see, it is possible to map has-few relationship using either has_many/belongs_to or has_one/belongs_to. Each approach has some wrinkles and we can use either depending on which fits our style of programming.

Written by Sharad

November 8th, 2009 at 11:16 pm

Posted in All

Ruby Interview Questions

without comments

I’ve been attending a few Ruby interviews recently. Here are a few questions that I liked being asked. The answers are all mine and may not be all correct.

# Question: Invert the following array
{:a => 1, :b => 2}
# Expected Result: 
{1=>:a, 2=>:b}
 
# Answer:
Hash[{:a => 1, :b => 2}.collect {|k,v| [v,k] }]
# OR
{:a => 1, :b => 2}.inject({}) { |r,e| r.merge({e[1] => e[0]}) }
# Question: What will following code return
{:a => 1, :b => 2}.to_a
# Answer:
[[:a, 1], [:b, 2]]
# Question: How to you quickly determine if a given hash is identity hash or not?
# (Identity Hash is where key == value. For example, {:a => :a, :b => :b})
hash.keys == hash.values
# (Note: hash.keys and hash.values will return the elements in matching order as long as hash is not modified between those 2 calls)
# Question: What is the difference between following to codes?
x = 'a'
x += 'b'
# and
x = 'a'
x << 'b'
# Answer: Nothing. They both return the same result
x = 'ab'
# Question: What will following code return
''.to_sym
# Answer: ArgumentError: interning empty string
# (in other words, an empty string cannot be symbolized/internalized)
# Question: What will the following code return
begin
  ''.to_sym
rescue => e
  5
ensure
  6
end
# Answer:
5
# Note: logic inside ensure does get executed but it still returns the final output of rescue block! This is different from Java, where anything returned from inside finally will override the original return value.
# Question: Given following classes, specify the parent-child inheritance relationship
Class
Object
Module
String
# Answer:

# Question: What will following code return?
x = 1
Array === x
# Answer:
false
# === is a equality operator used for case/when statement.
# Question: What will following code return?
x = []
Array === x
# Answer:
true

Written by Sharad

October 24th, 2009 at 5:18 am

Posted in All

COBRA and Insurance Shopping Tips

without comments

I blogged about some basic information when shopping of individual insurance and recently there was an article in Business Week about COBRA. I found a few more information that are worth keeping in mind when shopping for insurance.

Facts about COBRA:

  • Decide within 60 days of qualifying event whether to take cobra or not. Qualifying event is changing job (voluntary or involuntary).
  • More info about Cobra: dol.gov/ebsa/cobra.html
  • cobra is valid for 18 month. Obama govt. is subsidizing premium by paying 65% of the premium (for the first 9 months of the full 18month coverage)
  • This 65% subsidy is not available for somebody who has another group plan option available (like spouse’s employer insurance plan)
  • COBRA coverage is usually the same coverage that the employee had when on job. It has the same premium + 2% administrative fee. However, employee becomes responsible for full premium (unlike employer paying 2/3rd premium when employed).

When shopping for health insurance, look out for following things:

  • StateHealthFacts.org: information about consumer protection, plan features required by each state
  • Ask insurers for “Explanation of Benefits (EOBs), which are more detailed than summary. Insurers hesitate and sometimes provide EOBs only after you are signed up. Ask to see EOBs before signing up.
  • Avoid plans with annual benefit caps. Lifetime benefit maximum of 1.5 to 2 million are more common now.
  • If employer based group plans are not available, look for association based group plans. e.g. New York Freelancers Union. Each have qualifying rules.
  • There is a difference between insurance plans and “limited-benefit” plans. LB plans (usually touted on TV and offer doctor visit, prescription discounts) don’t cover surgery and hospital stays.

Written by Sharad

October 19th, 2009 at 12:13 am

Posted in All

Looking for Ruby/Rails Work

without comments

Job losses accelerate to 263,000 in September and yes, that number includes me.

After exciting, hard working, fun filled 2 and 1/2 years at Pathfinder Associates, we had to part ways. On the bright side, I worked with some of the finest programmers, agile practitioners and visionaries in Chicagoland area. I got to practice the goodness of agile, pair-programming, scrum, Test Driven Development, became a fan and devotee of Ruby/Rails. I got into serious habit of blogging. Thanks pathfinder!

Yes and it is time to move on. And I am actively looking for Ruby/Rails opportunities. If you are looking for senior level ruby developer or Java architects, please do not hesitate to contact me.

Wish you all a Happy Gandhi Anniversary.

Written by Sharad

October 2nd, 2009 at 4:37 pm

Posted in All

Authlogic: after the initial hype

with 3 comments

On my rails projects, I’ve used restful_authentication before and I am using authlogic now. Even though I have passed the initial hesitation phase with authlogic, I can’t say that I am totally sold.

What I like about authlogic is it refrains from providing any controller/view level support and handles model layer better. Instead, it provides a solid model functionality that is similar in principle to ActiveRecord and provides lots of how-to examples on how you might code your controllers/views/workflows. It does it well. Although authlogic is complemented for refraining from too much code generation, Authlogic still does a lot of magical stuff. You encounter this readily with tests. Instantiating and persisting a user will log you in! It is hard to test your User model from console since authlogic will fail if you try to instantiate User object in console. You have to jump thru hoops (include Authlogic, set proper controller reference) to get it to work.

Problem with Perishable Token:
Today I encountered another issue with authlogic realted to perishable token. According to docs, perishable tokens are useful for implementing features such as reset-password and confirm email. These functionalities are essentially similar in implementation in that application generates a token and emails url containing this token to the user’s registered email address. User clicks on the url and resets his password or confirms that email is indeed his email. The implementation details are explained very well by author here.

However, it didn’t work in my case. The problem, I believe, is that perishable_token changes often… too often actually. Looking side the codebase for Authlogic::ActsAsAuthentic::PerishableToken reveals this:

def self.included(klass)
  return if !klass.column_names.include?("perishable_token")
  klass.class_eval do
    extend ClassMethods
    include InstanceMethods
 
    before_save :reset_perishable_token, :unless => :disable_perishable_token_maintenance?
  end
end
def reset_perishable_token
  self.perishable_token = Random.friendly_token
end

As you can see, the token changes on each save. This can be readily verified from console:

>> u = User.find_by_email("sjain@iit.edu")
#=> #<User id: 1, email: "sjain@iit.edu", perishable_token: "6qLHkU_vBQK6rLQGy-oL", login_count: 54, failed_login_count: 0, last_request_at: "2009-09-30 18:00:46", current_login_at: "2009-09-30 18:00:42", last_login_at: "2009-09-30 18:00:42", current_login_ip: "127.0.0.1", last_login_ip: "127.0.0.1"...>
>> u.perishable_token
#=> "6qLHkU_vBQK6rLQGy-oL"
>> u.save
#=> true
>> u.perishable_token
=> "1tlcpvc_sCGtNEfIQCt1"
>>

Everytime the user object is saved, the token changes. In a running app this could happen for any number of reasons. I wonder, if having other authlogic magic attributes like login_count, last_request_at etc. causes the instance to get saved immediately after the token was sent in email, practically overwriting the token that was critical to password-reset workflow…

Solution:
Fortunately, Authlogic allows you to take control and manage token yourself. To do this, you disable the automatic maintenance of perishable_token by authlogic as follows:

class User < ActiveRecord::Base
  acts_as_authentic
  disable_perishable_token_maintenance(true)
end

By doing this, authlogic leaves this column in database alone. You can now reset the token when you need it. Here is what my password-reset and confirm-email hooks look like then:

class User < ActiveRecord::Base
  def deliver_confirm_email_instructions!
    reset_perishable_token!
    Notifier.deliver_confirm_email_instructions(self)
  end
 
  def deliver_password_reset_instructions!
    reset_perishable_token!
    Notifier.deliver_password_reset_instructions(self)
  end
end

In addition, since we took the control of perishable_token in our hands and that it is a non-nullable field in database, we have to reset the token when a new user registers for an account on our website.

class UsersController < ApplicationController
  def create
    @user = User.new(params[:user])
    # set the token manually
    @user.reset_perishable_token
    if @user.save
      @user.deliver_confirm_email_instructions!
      flash[:notice] = "Registration successful. Please check your email to confirm your email address."
      redirect_to root_url
    else
      render :action => 'new'
    end
  end
end

Conclusion:
All in all, authlogic is a well designed authentication library. However, you can’t get around the fact that authentication and its surrounding sub-features (password reset, registration, email confirmation) can get complex. When coming away from restful_authentication to authlogic you will be glad to find intuitive for its API that is very similar to ActiveRecord, configurablility to enable/disable features that you need and don’t need. But, don’t expect an easy ride. You are bound to have to dive into the codebase to take advantage of some of the complex features.

Written by Sharad

September 30th, 2009 at 8:33 pm

Posted in All

Setting up Sphinx Search on remote server

without comments

If you are using sphinx gem for search functionality in your rails application, here is a quick rundown of commands that you will need to install and setup sphinx server and rails plugin on remote server.

Download and installl Sphinx package:

# download from http://sphinxsearch.com/downloads.html
$ tar zxf <tar.gz file>
$ ./configure
$ make
$ sudo make install

The rails app should already list gem dependency. Install the necessary gem on system:

# environment.rb:
config.gem 'freelancing-god-thinking-sphinx', :lib => 'thinking_sphinx'
$ sudo gem install freelancing-god-thinking-sphinx

Here are 2 rake commands to index the database for sphinx search. And to start the sphinx daemon when the app is running.

$ rake thinking_sphinx:index (have a cron job for this)
$ rake thinking_sphinx:start (start the daemon)

There is also the capitate gem that makes managing sphinx on remote server easier.

Written by Sharad

September 30th, 2009 at 1:52 am

Posted in All

Rails monkeypatching to pin-point offending code

without comments

Monkey-patching is generally a bad thing but it can help you pin point offending code. I ran into a situation today where I was getting logger to be nil inside ActiveRecord model class. Normally, every ActiveRecord object has reference to logger for logging purposes. This logger is ideally never nil.

I knew, this must be a code somewhere in my codebase that must be setting it to nil. The trouble with rails’ dynamic nature is you can’t find reference to a method call in your IDE. You are left with brute-force find/grep … or monkey patching.

I was able to pin-point offending code using following code:

# this can go in environment.rb temporarily
module ActiveRecord
  class Base
    class << self
      def logger_with_nil_check=(new_logger)
        raise "logger cannot be set to nil" if !new_logger
        logger_without_nil_check
      end
      alias_method_chain :logger=, :nil_check
    end
  end
end

Isn’t this what they call “developer freedom”.

Written by Sharad

September 25th, 2009 at 8:17 pm

Posted in All

Getting session_id in rails

with one comment

If you are using database sessions, rails sessions table stores session information in “sessions” table that contains two columns: “session_id” and “data”.
Now, if you need to know the session_id of current session your first instinct would be to do the following:

session.session_id

This will not work since session is just hash containing name/value pairs and not an ActiveRecord object. So what do we do introspect session’s own information.

Solution: We use “request.session_options”. It is a hash that contains session_id and a few more options related to session.

request.session_options.inspect ={:secure=>false, :secret=>"ZBYULTOIJYLYWVNONXNSWUJCKMVVFPIZCEEGDAIE", :expire_after=>nil, :key=>"_SOMEGT_session", :id=>"4d4999d4650f4b21121c8f2b65917fac", :cookie_only=>true, :httponly=>true, :path=>"/", :domain=>nil}

Here :id is the session_id and :key is the cookie name under which it stores the session_id.

Now I know.

Written by Sharad

September 25th, 2009 at 4:57 am

Posted in All

Working with Authlogic in script/console

with 8 comments

When probing / debugging issues with Authlogic on rails console, you want to be able to create UserSessions and authenticate just like a live app does. However, you may run into issues if you plainly try to instantiate and save UserSession objects in console.

>> UserSession.new(:email => "validemail@domain.com", :password => "password")
Authlogic::Session::Activation::NotActivatedError: You must activate the Authlogic::Session::Base.controller with a controller object before creating objects
	from /var/lib/gems/1.8/gems/authlogic-2.1.1/lib/authlogic/session/activation.rb:47:in `initialize'
	from /var/lib/gems/1.8/gems/authlogic-2.1.1/lib/authlogic/session/klass.rb:61:in `initialize'
	from /var/lib/gems/1.8/gems/authlogic-2.1.1/lib/authlogic/session/scopes.rb:79:in `initialize'
	from (irb):2:in `new'
	from (irb):2

Authlogic uses framework adapters (RailsAdapter or MerbAdapter) to extract information such as session/cookies when working on authentication stuff. In order to enable this same mechanism for rails console, you need to do the following inside console:

>> Authlogic::Session::Base.controller = Authlogic::ControllerAdapters::RailsAdapter.new(self)

After this, you should be able to create UserSession objects like you normally would:

>> us = UserSession.new(:email => "validemail@domain.com", :password => "password")
=> #<UserSession: {:password="<protected", :email="validemail@domain.com"}>
>> us.save!
  User Load (0.6ms)   SELECT * FROM `users` WHERE (LOWER(`users`.email) = 'validemail@domain.com') LIMIT 1
  SQL (0.2ms)   BEGIN
  User Update (0.4ms)   UPDATE `users` SET `failed_login_count` = 2, `updated_at` = '2009-09-25 02:31:57', `perishable_token` = 'bP_s1_z9gwCFmrIX9cdV' WHERE `id` = 1
  SQL (1706.2ms)   COMMIT
Authlogic::Session::Existence::SessionInvalidError: Your session is invalid and has the following errors: Password is not valid
	from /var/lib/gems/1.8/gems/authlogic-2.1.1/lib/authlogic/session/existence.rb:85:in `save!'
	from (irb):11

Written by Sharad

September 25th, 2009 at 2:38 am

Posted in All