Archive for February, 2008

Google Sitemap Generator

February 26th, 2008 by pyrat

maps are good

Google sitemaps are nice for telling google what is where. Often clients want it for SEO or you have a site which has new content all the time and you want to keep google up to date.

Whatever the reason is thats you are interested in these little xml files, the following code allows you to generate a sitemap for a dynamic site in ruby.

Firstly the class:

  require 'net/http'
  require 'uri'
 
  # A class specific to the application which generates a google sitemap from
  # the contents of the database.
  # Author: Alastair Brunton
  class GoogleSitemapGenerator
 
    def initialize(base_url, sources)
      @base_url = base_url
      @sources = sources 
    end
 
    # The main generator method which in turn adds to the path_array from the different
    # sources.
    # Sources are: pages, events, properties
    def generate
      path_ar = Array.new
      @sources.each do |source|
        # initialize the class and call the get_paths method on it.
        path_ar = path_ar + eval("#{source}.get_paths")
      end
      xml = generate_xml(path_ar)
      save_file(xml)
      update_google
    end
 
    # This creates the xml document.
  	def generate_xml(path_ar)
  		xml_str = ""
  		xml = Builder::XmlMarkup.new(:target => xml_str)
 
  		xml.instruct!
  			xml.urlset(:xmlns=>'http://www.google.com/schemas/sitemap/0.84') {
    			path_ar.each do |path|
      	    xml.url {
        	    	xml.loc(@base_url + path[:url])
        			xml.lastmod(path[:last_mod])
        			xml.changefreq('weekly')
     			 }
    			end
  			}	
  		xml_str
  	end
 
  	# Saves the xml file to disc. This could also be used to ping the webmaster tools
  	def save_file(xml)
  		File.open(RAILS_ROOT + '/public/sitemap.xml', "w+") do |f|
  			f.write(xml)	
  		end		
  	end
 
  	# Notify google of the new sitemap
  	def update_google
  	    sitemap_uri = @base_url + '/sitemap.xml'
  	    escaped_sitemap_uri = URI.escape(sitemap_uri)
  	    Net::HTTP.get('www.google.com',
  	                  '/webmasters/sitemaps/ping?sitemap=' +
  	                  escaped_sitemap_uri)
  	end
 
 
  end

You will notice that an array of strings are passed when calling the generator. These are names of object which implement the get_paths method. An example get_paths class method is as follows:

  # for the google sitemap
   def self.get_paths
     path_ar = Array.new
     Property.live_properties.each do |property|
       path_ar << {:url => "/property/#{property.to_param}", :last_mod => property.updated_at.strftime('%Y-%m-%d')}
     end
     path_ar
   end

Basically, you need an array of hashes which each contain the url and the last_mod.

To call this little beastie it is best done from a cron on the production server. An example rake task to do this is as follows:

  namespace :google_sitemap do
    desc "Generate a google sitemap from the site."
    task(:generate => :environment) do
      sources = ['Page', 'Event', 'Property']
      sitemap = GoogleSitemapGenerator.new('http://www.your_url.com', sources)
      sitemap.generate
    end
  end

Remember when you are calling it from a cron to pass the RAILS_ENV. This generator does rely on rails but you could convert it to only rely on ruby by modifying the rake task and changing the RAILS_ROOT reference in the save_file method. Probably can be made to work with Merb but I am unsure of how merb and rake work together. Will hopefully get my hands dirty with Merb sometime soon.

   cd /var/www/apps/site/current /usr/bin/rake RAILS_ENV=production google_sitemap:generate

Throw your own exceptions

February 24th, 2008 by pyrat

exceptions

Throwing and catching exceptions can be a good design pattern in your rails app. Especially when you want to be able to deal with the unexpected in a clean way. Overuse is a no no as with most techniques but it is nice here and there.

I find that a good idea is to make your own exceptions when writing a rails app. This means that standard low level exceptions which often should not be caught are not.

eg.

(in config/initializers/custom_config.rb)

  class ApplicationError < RuntimeError
 
  end

This way in your application code you can do something like the following

  begin
    @user = User.find_by_password_reset_code(params[:id])
    raise ApplicationError if @user.nil?
 
  rescue ApplicationError => msg
    flash[:message] = "Sorry - That is an invalid password reset code. Please check your code and try again. (Perhaps your email client inserted a carriage return?"
    redirect_to logins_url
  end

In other news I have started testing deploying with git and capistrano. It is blazingly fast even for a full checkout. I cant get :remote_cache deploy via working due to an ancient version of git on LTS 6.06. But event with full checkout this is faster than deploy_via :remote_cache with subversion! (This is with 2 slices on a local network.)

15 Top Tools for a Rails Programmer

February 12th, 2008 by pyrat

toolbox

Here are my top 15 tools for rails development. I felt compelled to compose a list in an effort to help rails developers that are just starting out.

1. A mac / linux machine for development. (macports and apt-get are your friends.), with Rails 2 and Mongrel by Zed Shaw. I have not bothered to include all the individual tools on your development platform but recommend setting it up yourself as you will learn a lot and will end up with a setup which is tailored to your needs. Info for mac , Info on the rails wiki

2. A healthy collection of feeds. Ruby Inside, Err the Blog, Nubyonrails, and Riding rails. Also, new age feeds such as ruby on rails podcast, railscasts, rails envy podcast are top. Also, the peepcodes are all pretty good and if you want to learn about something in detail which is fairly meaty, they are worth the reasonable price.

3. A great editor you know inside out. The main reason I use a mac is because of the existance of textmate. Otherwise I would still be on windows. The book is a lifesaver, also this cheatsheet is very useful.

4. A shell. Instead of spending time with bloated IDE’s which take a year to load an use more RAM than a I eat waffles, spend time getting familiar with the shell. BASH is my favourite and is by far the most common. You should become familiar with the rails console commands, command line mysql, command line source control and command line filesystem commands. These take a bit of time to get used to, but are often the fastest way to do things. BASH aliases are MASSIVE time saver. Have a look at my ALIASES for some inspiration. Load them in with the following in your .bashprofile_:

  # Get the aliases and functions
  if [ -f ~/scripts/.personal_profile ]; then
          . ~/scripts/.personal_profile
  fi

5. An automated deployment tool, this should really be “one-click” stuff. Capistrano is the king of the hill, with projects like Vlad the deployer following in its wake. Try and get your deployment recipies into a plugin. Here is a plugin which includes a collection of recipies (including an update basecamp recipe) which I use in my projects at iformis. deployment_recipiez

6. Sysadmin skills. At the moment rails on shared hosting aint the best. Hopefully projects like mod_rubinius will sort that. You need to be able to install a rails stack from the ground up and deploy to it. Things like backups, database setup, process monitoring etc should be familiar. I was hoping to try Ruby Works the rails stack provided by Thoughtworks. If you have had the chance please let me know what its like. In terms of cheap dedicated hosting which is reliable I recommend slicehost. If you are not yet familiar with systems administration I recommend reading a few books on the subject as it isnt something you can learn overnight. Also a good tip is to maintain a collection of scripts which you keep in source control which you can easily checkout on the different servers that you work. It is essentially a mobile server toolkit which is customized to your needs.

7. Testing is very important for your rails application. This will save time in the future. I wont harp on about the many benefits of testing but point you to TDD and BDD.

8. Zentest especially autotest which runs your tests automatically each time you save a relevant file. Linking in the Growl notifications You might also want to get this working with Rspec. If you do then.. this might be of interest.

9. Know which are the top good quality plugins out there. Keep an eye on the rss for agilwebdevelopment.com for what is new and hot. For established plugins, I recommend will_paginate, exception_notification, attachment_fu, restful_authentication and arts. I am sure you know of some more goodies!

10. Monit is a great tool for your production servers. After it is properly configured it just keeps stuff up for you and can warn you if you experience high load. It also means that if your mongrels crash for any reason you can sleep soundly in the knowledge that they will be started for you. There is an example monit configuration which you can start from if you like.

11. Firefox/Firebug: Often referred to as ruby’s ugly-cool sister, Javascript is used a lot in rails apps. You should use firebug to debug errors with AJAX calls rather than having to dig through the server logs to try and find what you are looking for! This saves a LOT of time and other features such as the CSS inspector are top notch. As a side, also thing about other firefox plugins such as LiveHTTPHeaders which are shit hot also.

12. HAML : You either love it or you hate it. I love it, well, I like it. For developing templates really quickly this is an amazing tool. However, you have to watch out for long files as it can look ugly if you are doing too much in a template. This forces you to use more partials and helper methods. These are good design practices.

13. Continuous Integration is a great technique which makes sure you dont have any broken windows in your project. Often testing on a development machine is tied too much to the environment on the development machine. Often Davey, your designer will delete an erb tag by mistake. CI involves automatically building the project after each subversion commit. Cruisecontrol.rb is your tool of choice here. As the number of projects you have configured with it grows, make sure your server has quite a bit of RAM. You can also integrate this with campfire and basecamp to use these tools as a centre to the development in your work environment.

14. SCM should probably be higher up the list but it isnt. This is because it is rubbish. No only joking, you are not one of the ‘enlightened’ if you dont use this on all your projects which have more than one file! Subversion is the defacto standard but there is a new kid on the block called Git which is really good for open source projects but maybe isnt so good for Davey the designer.

15. Javascript is a core element of rails application development. You should have a working knowledge of the language itself. You should also know what can be done with prototype and scriptaculous the javascript frameworks which ship with rails. The downside of these frameworks is the overhead. There are some fanboys of jquery which is more lightweight and apparently can do the same I recommend you check out jquery but knowledge of prototype and scriptaculous is a must. Have a look at the book on prototype or the peepcode screencast for further info.

I hope this helps you get an overview of all the main tools and sources of information in the rails development space. If you would like to point out any glaring errors or give me a pat on the back please do so in the comments.

Hpricot 0.6 Caveat Setting Attributes

February 6th, 2008 by pyrat

Watch out with Hpricot 0.6 it doesnt seem to work properly with setting attributes. Use 0.5 instead.

sudo gem install hpricot -v0.5