Tag: Rails
2011
10.06

I’m adding multiple authentications to a web app I am working on using Omniauth. I ran into an error early on with integrating twitter into my rails app.

I followed along with the install instructions on the wiki, however when I hit the url: /auth/twitter which should have redirected me to the twitter oauth authorization page, I got the following:

I searched the net and found many others getting the same error, but none of the suggestions for correction seemed to match the issue I was having.

Then I realized, the setup instructions on the omni auth wiki list the configuration as:

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :developer unless Rails.env.production?
  provider :twitter, ENV['id'], ENV['secret']
end

When they should have been:

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :developer unless Rails.env.production?
  provider :twitter, 'id', 'secret'
end

I hope this helps someone else!

2010
10.02

Recently I had a need to add action caching to a Rails app that contained a fair about of dynamic data, so required frequent expiration of cached fragments.

There seemed to be plenty of information on creating Cache Sweepers that observed / implemented ActiveRecord callbacks (after_save, after_destroy etc…) but I could not find any good examples of implementing callbacks in the CacheSweeper for controller methods / actions.

Here is a short example of how to implement callbacks / observe action methods in a CacheSweeper:

Example Controller:

class BusinessesController < ApplicationController
  layout 'main'
 
  caches_action :businesss_directory, :show,
                 :if => Proc.new { |controller| !controller.user_authenticated? }, :layout => false
  cache_sweeper :business_sweeper, :only => [:sort_images]
 
  def business_directory
    #... implement business directory action
  end
 
  def show
    #... implement show action
  end
 
  def sort_images
    #... implements resort action
  end
end

So in my example, I want to observe the standard Business model as well as expire certain cache fragments when the sort_images method is called.

Let’s write a CacheSweeper implementation that will handle *both* for us.

class BusinessSweeper < ActionController::Caching::Sweeper
  #this will allow us to implement active record callbacks
  observe Business
 
  #after active record create
  def after_create(business)
    expire_cache_for(business)
    expire_directory_cache(business)
  end
 
  #after active record update
  def after_update(business)
    expire_cache_for(business)
    expire_directory_cache(business)
  end
 
  #after active record destroy
  def after_destroy(business)
    expire_cache_for(business)
    expire_directory_cache(business)
  end
 
  #Here we are going to observe / filter the controller action
  def after_businesses_sort_images
    expire_cache_for(assigns(:business))
  end
 
  private
 
  def expire_cache_for(business)
    expire_action(business_url(business))
  end
 
  def expire_directory_cache(business)
    expire_action(business_directory_url(business))
  end
end

In order to filter / observe the action on the controller we just need to include the controller name before the action name. If we want to reference any instance variables assigned inside the action, such as @business, we can use the assigns() method to get a handle on them.

It’s that easy!

2010
01.13

Rails didn’t move a mountain.

Rails didn’t part the Red Sea.

Rails only really had to do one thing to make me a convert:

Rails read my mind. That’s it!

Here’s what happened. I’m building a relatively simple little webapp, but was having an issue of how I wanted to handle some functionality over the weekend. I had two models, a service item and a service. The service item had a price and the multiple service items that belong to a service made up the total for the service.

I initially started out with a one to many relationship between a service and service item but then ran into a problem: If I updated the price of a service item, I didn’t want to update the price of *every* service item that had previously been associated with a service. I briefly flirted with the idea of just duplication entries in the service items table, which would work, but soon became unweildly as I try to juggle between a set of possible service items and the set of cloned service items that were actually associated with a service.

It was a bad idea and quickly crashed.

The solution I came up with was to change the relationship to a many to many relationship through a service_service_items table. Then I would keep the current price for a service item in the service item table and then store the price for a particular service >> service_item relationship in the join table. Should be relatively simple I thought, wouldn’t take too much extra code to update the price of the join table on save and remember to only read the data from the join table. I’d have to probably create a model for the join table but some extra convenience methods in the model and I’d be gold.

So I got started.

I created my join table, updated each of my models to specify the relationship to has_and_belongs_to_many (habtm) and ran rake db:migrate

I thought I’d use the interactive console to create some services and service items to make sure the relationship worked, then I’d get down to writing the extra code to manage storing / retrieving the price in the relationship column.

Created the service, saved it and checked the database.
Good it was in the table

Created a service item, assigned it a price then added it to the service_items collection of the service.
Saved the service and checked the database.

The service item was saved through the collection. Perfect.

Checked the relation table to make sure it had a row reflecting the relationship I just created:

Screen shot 2010-01-12 at 10.42.40 PM

I looked at the database table for a second, trying to figure out what had gone wrong! Then after a couple seconds I realized that Rails just KNEW what I wanted to do. since I named the field in the relation table the same as the service_item, it automatically just added that data to the relation table for me.

This was too good to be true. I decided to update the price on the service item and save it by itself.
The price updated but the history in the relationship stayed intact!

I grabbed a copy of the service from the database and checked the price on the related service_item:
It read the old price!

Rails was handling the entire operation for me!

That sealed the deal. I officially love Rails.

Okay so this is a relatively simple thing and a common solution for a common problem.

But this is the great thing about Rails. It just does things for you.

I was excited! When you’ve been programming for many years, it feels good to be excited about a language or framework.

Whoever came up with this feature is a great man.

Like Ghandi.

Thank you web development Ghandi.

2009
12.30

Git on Rails!

So I’m beginning the new year (technically started the beginning of December) with two new projects. With these new projects I decided to finally take the opportunity to do a couple things I’ve wanted to do for a while: use Rails and use Git.

Rails I hadn’t used for anything because truthfully I didn’t really feel like deploying my applications using fastcgi or mongrel, I just didn’t want to mess with it. Then I took a look at Phusion Passenger, it was exactly what I had been waiting for.

I made the plunge!

I’m still at the very early stages of the projects, but I had a couple thoughts on starting to use both pieces of software:

Git

Not a lot to report here. It does a lot of the same stuff I’m used to, but has a lot of other cool features. I’m mostly jazzed about the ‘stash’ command, as that will speed up trying out new features on a branch greatly for me. The only thing that I’m not excited about is the commit serials. Maybe I’ve just been doing it for so long, but when working with other people I find it particularly easy to refer to changesets as 8999 or 12391. The serial seems a little more cumbersome, but I’m still at the beginning stages, so I may find an easy / convenient way of handling this in the future.

Rails

So far this has been great. I had done some pet projects in rails 1 and played with rails 2 when it came out. The biggest boon for me so far has been that when I started to work on my project, I was equally unfamiliar with (controller)action / view layers as I was with the testing components, so I sat down and learned the testing components *first*. This so far has turned out great because I roughed out the near entirety of one of my apps functionality in unit and functional tests before really writing much of the standard app at all. I ended up with great test coverage (thanks rcov!). I really like the quality of the rails plugins I’ve encountered so far. ActiveMerchant is so easy to use compare to alot of other payment gateway libraries I’ve used in PHP land and if feels good to be saying collection.size again instead of count(collection).