Archive for the ‘Rails’ Category

Rails makes you think you can

Tuesday, April 21st, 2009

I spent a couple of hours last weekend going over a Rails app I wrote almost two years ago. It was the very first Rails application I had written (apart from the follow-the-screencast throwaway ones) and I couldn’t help cringing when I saw the code I got paid good money to write.

That app is still my most ambitious project ever and I’m still shocked I decided to do it in Ruby (a language I barely knew) and Rails (after playing with it for a few weeks) when I had a couple of years experience in PHP and some production apps already running on CodeIgniter. I guess it was the hype.
However, almost two years later and the app is still running smoothly (I had to tweak it a bit over the weekend). I am still not sure I would have taken on the project – an internal stock trading app with a social angle to it (I was freelancing then and working alone) if I had to do it PHP but in retrospect it would probably have been done better in PHP. I’d have had less fun though.

Rails is so deceptively simple it makes you feel you’re a superstar programmer even when you just have a couple of lines of code under your belt. However, after working with it for a while, you start to appreciate how complex it is to get things done when they don’t fall into the Ruby on Rails sweet spot. I wouldn’t have it any other way though. When it rocks, it really rocks.

I currently use PHP (and the Zend Framework) at work and I have come to appreciate the flexibility of ZF but I wouldn’t recommend the framework for programming beginners. Using a lot of the components requires a good grasp of programming concepts and compared to Rails where components are written for specific use cases, with ZF, you have to come up with yours. I am currently still trying to figure out where I can use Zend_Navigation in the recently released version of ZF. I know it will come in useful but I just have to tweak and flesh it out to make it work for me and that pretty much sums up the ZF-Rails differences quite well. One makes you think you can without even trying while with the other, you know you can but you’ll just have to work at it.

Finally… passenger for nginx

Friday, April 17th, 2009

I just spent last weekend setting up a new slice at SliceHost (my bestest host ever) for a couple of Rails apps only to read this post announcing the release of Phusion Passenger for Nginx.

Considering I only needed the slice for Rails (No php and the DB is on another slice), I could have gone with Nginx except that I’ve been spoilt by Passenger’s upload-and-go deployment and being able to squeeze more apps into a small VPS (the inactive ones shut down and release memory). Now hopefully, it’s the best of both worlds.

I’ll still have to learn Nginx quirks considering I’ve always used Apache but the promise of faster page serving and a lower memory footprint is motivation enough.

Kudos to the guys at Phusion for their awesome products (I also use Ruby Enterprise). Congrats on your anniversary and a lot more power to your elbow!

On a related note, I learnt the hard way that Rails 2.3 and an old version of Passenger don’t mix very well.
Even after updating the passenger gem I couldn’t get Rails to load. The solution is to re-install the passenger module (passenger-install-apache2-module) and update your apache config file. Hope that helps someone as I spent a bit too long trying to fix it.

Restful authentication with Rails 2: Usage

Sunday, January 18th, 2009

This blog has been inactive for ages and one of my 2009 resolutions is to show the poor thing some love! I will try to keep it even if it’s the only resolution I don’t give up on. Things have become a bit less hectic at work (or maybe I’ve just gotten used to the system) and the spirit is willing so hopefully …

In my post detailing the installation of the Restful authentication plugin, it was pointed out to me in the comments that I didn’t show the actual usage of the plugin. My bad! This post will amend that oversight.

As an aside, while my tutorial post is still very relevant, I don’t do the installation from scratch anymore. In one of my earlier posts, I mentioned Bort and I still recommend it as a way of speeding up the initial setup of your rails project. However, the usage is the same whether you do the installation manually or use Bort.
Another Rails starter app I have used is leethal’s blank-rails-app. This is as light as they come and I use this when I do smaller sites in Rails rather than full fledged apps.

One of the advantages of installing manually is that Bort defaults to using RSpec as the test framework (at least on my system).
A manual installation checks for the presence of the spec folder and if it doesn’t exist, it creates the default Test::Unit tests.
However, Rails creates both a spec and test folder when i create a new Rails project (presumably because I’ve got the rspec gem installed ) and so to use Test::Unit I have to delete the spec folder before running the plugin’s generator.

To use the Restful Authentication plugin in your Rails app:

  • Include AuthenticatedSystem
    The generated controllers include the AuthenticatedSystem module but we need this available to all controllers.
    Delete the ‘include AuthenticatedSystem’ line from the Sessions and Users controllers and move the line to the application controller.
    The AuthenticatedSystem module (located in lib/authenticated_system.rb) contains the core methods used in our application code for authentication.
  • Add a before filter in the controllers you want to protect
    For any controller with actions that need protecting, add a before filter to the controller.

    class PageController < ApplicationController
    # protect all actions in this controller
    before_filter :login_required
    ...
    
    class PageController < ApplicationController
    # protect all actions in this controller except the index action
    before_filter :login_required, :except => :index
    ...
    
    class PageController < ApplicationController
    # protect all actions in this controller except the index and contact actions
    before_filter :login_required, :except => [:index, :contact]
    ...
    
    class PageController < ApplicationController
    # protect only the support action
    before_filter :login_required, :o nly => :support
    ...
    

    For the protected actions, the user is redirected to the new session url. We’ve already added a named route called ‘login’ to the routes.rb file pointing to this same action and I’d rather have my urls end with ‘/login’ than ‘/sessions/new’.
    To do that I override the access_denied method in the application_controller.rb.

    class ApplicationController < ActionController::Base
    helper :all # include all helpers, all the time
    
    include AuthenticatedSystem
    
    def access_denied
    alias new_session_path login_path
    super
    end
    ...
    
  • Use the plugin methods in your controller
    def index
    if logged_in?
    @profile = current_user.profile
    # or
    # @profile = Profile.find(current_user)
    end
    end
    
  • Use the plugin methods in your view
    
    <% if logged_in? %>
    Welcome <%= current_user.login %>
    Your Profile: <%= @profile.description %>
    <% end %>
    

And that’s all there is to it. Now get building!

Jump start your next Rails 2 application

Wednesday, October 29th, 2008

Ruby on Rails has gotten really popular owing mostly to its well-earned reputation for rapid web application development. The plugin system has also helped to add loads of functionality not built into the core. It is almost certain you’ll find a plugin (or solution) to solve most problems you run into as long as it’s not too obscure.

However you can do better than typing ‘rails PROJECT’ to start a new rails app. I have used both bort and insoshi as bases for my new rails application and I recommend them highly.

Bort – A Base Rails Application

Bort is a base Rails application with various commonly used plugins pre-installed. Various maintenance tasks have also been done (e.g. the index.html file has been deleted, the views have been modified and the database has been set as the session store).

The package includes plugins I usually end up installing and saves me a couple of hours when I start a new Rails app. Pre-installed plugins include Restful Authentication, Exception Notifier, Will Paginate and Asset Packager. I actually use a fork which is essentially the same but uses usernames email addresses for authentication with the Restful Authentication plugin rather than email addresses usernames.

The downside when I started was the use of RSpec rather than Test::Unit but then it did force me to start using RSpec and I’m glad I did.

Insoshi – Social Networking Platform

For a social site, Insoshi will save a lot of time. It is an open source social networking platform built on Rails and it rocks! Apart from being a complete application you can build from, it’s also got loads of pre-installed plugins which include Will Paginate, Restful Authentication and Attachment-fu.

Like Bort, it uses RSpec rather than Test::Unit. Check it out.

Restful Authentication with rails 2

Saturday, January 19th, 2008

I recently had to build an authentication system into a project and seeing as the restful authentication plugin was getting such buzz, I decided to try it out.

The problem was, most of the information I found on the internet was dated and I had to make a couple of changes to get it to work on Rails 2.0. This site and this forum post were really helpful. This post documents the steps I took (or rather, the steps I’ll take next time I use it) to get the plugin working. It assumes you already have a rails application running and want to add authentication to it.

  • Install the plug-in
    Open up a console window and navigate to the root of your application.
    Use script/plugin to install the plugin.

    ruby script/plugin install http://svn.techno-weenie.net/projects/plugins/restful_authentication/
  • Run the generator
    The generator sets up your controllers, model, views and observer as well as modify the routes.rb file (sets up session and users as resources). The session controller is used for signing in and out of the system while the user controller takes care of the rest.If you do not need a user activation system built into the system, type the line below:

    ruby script/generate authenticated user sessions

    If you need a user account activation system, use the line below. The rest of this post will assume the system includes user activation (the system is a lot simpler without user activation enabled).

    ruby script/generate authenticated user sessions --include-activation
  • Run the migration
    The system also generated a migration file. Run the migration with:

    rake db:migrate
  • Modify the routes file
    Open up config/routes.rb and add to the named route section:

    map.activate '/activate/:activation_code', :controller => 'users', :action => 'activate'
    

    While the routes file is still open, add more named routes (giving the user actions nice, friendly urls)

    map.signup '/signup', :controller => 'users', :action => 'new'
    map.login '/login', :controller => 'sessions', :action => 'new'
    map.logout '/logout', :controller => 'sessions', :action => 'destroy'
    
  • Add an observer (required for user activation emails)
    Add an observer to config/enviroment.rb (within the Rails::Initializer.run block) :

    config.active_record.observers = :user_observer
    

    At this point, the basic system should be working. Start up your development server and go to http://localhost:3000/signup. You should see the sign up form.
    Also try http://localhost:3000/login to confirm it’s fine.

  • Set up ActionMailer (required for user activation emails)
    The rails config/environment.rb file includes a Rails::Initializer.run block and prior to Rails 2, configuration code went in there.
    With Rails 2, there’s now a directory (config/initializers) where seperate, discreet bits of configuration are placed in files of their own.
    These are automatically loaded after plugins are loaded when Rails starts up.Create a new file called mail.rb in the config/initializers directory (you can actually call the file anything you like). SMTP setting will go into this file.
    Rails 2 also changed the variable for ActionMailer settings from server_settings to smtp_settings
    Place the following into the mail.rb file:

    ActionMailer::Base.delivery_method = :smtp
    ActionMailer::Base.smtp_settings = {
    	:address => "mail.example-domain.com",
    	:port => 25,
    	:domain => "www.example-domain.com",
    	:authentication => :login,
    	:user_name => "user@example-domain.com",
    	:password => "secret"
    }
    

    :address and :port – Determines the address and port of the SMTP server you’ll be using. These default to localhost and 25 , respectively.
    :domain – The domain the mailer should use when identifying itself to the server (usually the top-level domain name of the machine sending the email).
    :authentication – One of :plain, :login or :cram_md5. Should be omitted if the server does not require authentication. Also omit :username and :password options if you omit this parameter.
    :username and :password – Mail account login credentials. Required if :authentication is set.

  • Modify the activation email parameters
    Open the production and development configuration files, config/environments/production.rb and config/environments/development.rb respectively.In the development config file:

    SITE_URL = "localhost:3000"

    and in the production:

    SITE_URL = "example-domain.com"

    You need to restart the server for these settings to take effect.Open app/models/user_mailer.rb. Change:

    @body[:url]  = "http://YOURSITE/activate/#{user.activation_code}"

    to:

    @body[:url]  = "http://#{SITE_URL}/activate/#{user.activation_code}"

    Change:

    @body[:url]  = "http://YOURSITE/"

    to:

    @body[:url]  = "http://#{SITE_URL}/"

    Change the setup_email block settings (ADMINEMAIL and YOURSITE) to your desired settings.Open the email template files (app/views/user_mailer/activation.html.erb and app/views/user_mailer/signup_notification.html.erb) and modify as desired.

    And that’s it. The system should now be working.

    Note: You need to include flash[:notice] and flash[:error] in your templates or layout to view the status messages e.g. just before the <%= yield %> line in app/views/application.html.erb, type:

    <%= flash[:notice] %>
    <%= flash[:alert] %>
    

Update: Need help with using the plugin in your view or controller? Go here.