Ruby on rails

Ruby on rails: quick tips

5 great tips when working with Ruby on Rails: guidelines on working with views, accessing controller and action names, dumping tables to YAML, instantiated fixtures, and simple CAPTCHAs. Read More...
|

Ruby on Rails and Postgres: how to clear out sessions

If you’re running Ruby on Rails with a PostgreSQL database then you can clear out old session data by executing this command from your application directory:

ruby script/runner -e production \
"ActiveRecord::Base.connection.delete(\" \
DELETE FROM sessions \
WHERE updated_at < timestamp 'now' - interval '24 hours'\")"

This removes any sessions older than one day.

You might want to run this on a regular basis, perhaps even automatically with a cron entry.

This is the equivalent of the MySQL command described in the great book Agile Web Development With Rails (2nd edition).

Tcsh users: you may have to prefix the above command with sh if you get an error message about Unmatched “..

|

The Rails Way: Painless PNG in Ruby on Rails

The Painless PNG plugin allows your Rails application to support PNG images with transparencies for Internet Explorer 5.5+ through 6.x without changing existing code.

Quick fix for the impatient

For the impatient here’s the quick fix to solve your worries:

  ruby script/plugin install \
http://svn.wheremydogs.at/painless_png/tags/painless_png

Yes, that’s right — it’s all you have to do.

The Painless PNG plugin transparently supports PNG images in Ruby on Rails with the image_tag method. You don’t have to change your existing code.

Can I see the plugin in action?

Sure, we rely heavily on it at our library of the world’s finest books and at our code snippets collection.

Background

PNG images are a blessing and a curse to web developers. They allow for high-resolution, compact graphics with beautiful transparency support. But the alpha transparency doesn’t work out of the box in Internet Exploer 5.5+ and 6.x, a bane to web developers world-wide.

This plugin solves the curse part and leaves only the blessing.

How does it work?

The Painless PNG plugin monkey patches the image_tag method such that

  • If the browser is Internet Explorer 5.5 or 6.x then it uses the AlphaImageLoader filter method prescribed by Microsoft
  • For all other browsers it uses the default image_tag method from the Rails framework

This happens behind the scenes, transparently to your Rails application.

Sounds too good to be true, where’s the catch?

For HTML, there’s none. That is, provided you’ve been using the image_tag method to place your images rather than hand-coding <img> tags.

The only exception is that the plugin won’t work for PNG images used in CSS stylesheets.

Like it? Support us!

The Painless PNG plugin is released under the flexible MIT License, so you can basically do what you want with provided you keep the copyright in tact.

If you like and use it, we’d love to know—please drop us an email at contact@wheremydogs.at.

Also, please support us by visiting and spreading the word of our library of the world’s finest books and at our code snippets collection.

Problems? Found a bug?

Please let us know if you experience problems using the Painless PNG or if you think you’ve found a bug.

For us to fix any problems or bugs, please send the code you used and the exact error messages by email to philipp at wheremydogs.at.

|

The Rails Way: migrating from one-to-many to many-to-many

I must confess I was initially weary of migrations. But I tend to refactor mercilessy when I code and more often than not this refactoring involves changing the database.

When I started coding 17books.com I had only one copy of the database — on my laptop. But the moment I uploaded a copy of the site (then still in development) for my colleagues to test I knew I was heading for trouble.

After giving migrations a go I became a convert overnight.

I thought I’d share the non-obvious migrations here in the hope that they will be useful to other merciless refactorers. I’ll assume that you’re familiar with the basics of migrations, in particular that you can generate migrations and can do basic operations such as adding tables and columns.

Down to business. Say you’re creating a movie database (taking on IMDB are we?) and for a start you would like to record films and their directors. Here’s how you’ve defined your tables:

  create_table "directors", :force => true do |t|
t.column "name", :string
end

create_table "films", :force => true do |t|
t.column "name", :string
t.column "director_id", :integer
end

Eagerly you start adding your favourite directors:

idname
1Steven Spielberg
2George Lucas

And then their early films from the late 70s onwards:

idnamedirector_id
1Jaws1
2Star Wars Episode IV: A New Hope2

But then you get to 1981 and want to add Raiders of the Lost Ark … and run into a problem. It turns out Steven Spielberg and George Lucas teamed up to direct this film together, but our films table allows only one director per film!

What we need to do is turn the one-to-many association between directors and films into a many-to-many association. In plain text, we need to allow more than one director per film.

How can we do this with migrations without losing our data?

First we need to create the table that will link films to directors:

  create_table "directors_films", :id => false do |t|
t.column :film_id, :integer
t.column :director_id, :integer
end

Now comes the key part: we transfer the existing film directors to the newly created table:

  execute "INSERT INTO directors_films " +
"SELECT id AS film_id, director_id AS director_id FROM films"

That’s the hard part done with, now we can safely drop the redundant director foreign key from the films table:

 remove_column :films, :director_id

Eyes closed, fingers crossed — let’s migrate:

 $ rake migrate

No data should be lost, but let’s check anyway. First the films table:

idname
1Jaws
2Star Wars Episode IV: A New Hope

Looks good. The director_id column is gone, as expected. How about the directors_films table?

film_iddirector_id
11
22

Excellent! No data has been lost, migrations (and a bit of SQL) saved the day.

For the sake of completeness let’s add Raiders of the Lost Ark. I’m not keen on SQL so let’s do this in Ruby:

  $ ruby script/console
>> indy = Film.create("name" => "Raiders of the Lost Ark")
>> steven = Director.find(1)
>> george = Director.find(2)
>> indy.directors << steven
>> indy.directors << george
>> indy.save

Note: the above assumes that you have defined the following associations in your models:

  class Director < ActiveRecord::Base
has_and_belongs_to_many :films
end

class Film < ActiveRecord::Base
has_and_belongs_to_many :directors
end
I’ve tested the above in PostgreSQL, but it should work equally in MySQL. Let me know if you experience any problems.

|