Recent Posts - Page 29

Localization with Rails and PostgreSQL, part 1

November 30, 2005

One of the client projects that PLANET ARGON is working on requires that it work in about 20 different languages. Jeremy has been investigating different plugins for Rails to help us accomplish this. He came across Globalize.

Globalize is a Ruby on Rails plugin designed to support multilingual applications. It’s under the MIT License, same as Ruby on Rails.

Locale.set( 'en-US' )
d = Diet.find( 1 ) 
d.name -> "Vegetarian"

… we want to pull back the German version. No, it doesn’t translate it for you.. just pulls back another version of the object with the desired locale.

Locale.set( 'de-DE' )
d = Diet.find( 1 ) 
d.name -> "Vegetarier"

Pretty cool, right?

Well, we’re primarily working with PostgreSQL and the Globalize plugin didn’t pass tests with it. That’s now fixed as I found out from Jeremy that he was given COMMIT rights to the Globalize plugin and it now passes all tests against PostgreSQL!

We’ll keep you updated on how well it works as we dig deeper into using it. :-)

Try Ruby

November 29, 2005

I was lucky enough to see this when it was in the alpha-beta-try-that-again stage.

Try Ruby

That’s right… _why has done it again. You might know him as that d00d who made hoodwink.d or that weird0 who made that poignant guide.

Have friends who are skeptical of Ruby??? tell them to… Try Ruby.

Have your parents had a chance to try ruby

Maybe that weird uncle of yours needs to try ruby.

That guy who sneezed on you on the bus ride… tell him to try ruby.

I’m might get some stickers printed and litter Portland with Try Ruby stickers…

…the revolution begins… (again)

Rails Migrations and PostgreSQL Constraints

November 11, 2005

A question was posed on the Rails mailing list concerning how one would go about adding CONSTRAINTs to the database tables with ActiveRecord::Migration.

One argument was raised stating that it is easier to handle these in plain SQL schema files. I disagree. :-)

Migrations to the Rescue

Databases evolve and I have recently found the Migration structure to be perfect for handling iterations and schema changes. Using the #execute method has helped move more of my code into the Ruby/Rails framework… and that just makes things easier to manage in the long-run. This is the approach that we are using at PLANET ARGON with some of our current client projects.

# db/migrate/6_add_foreign_key.rb
class AddForeignKey < ActiveRecord::Migration
  def self.up
    execute "ALTER TABLE bees ADD CONSTRAINT beehive_id_fkey FOREIGN KEY
(beehive_id) REFERENCES beehives (id);"
  end

  def self.down
    execute "ALTER TABLE bees DROP CONSTRAINT beehive_id_fkey;"
  end
end

This gives us an easy way to use the standard, #create_table syntax for building our tables with Ruby… and then we can slap these constraints on later.

This would add the constraints…

rake migrate VERSION=6

…run tests…

rake

…roll back…

rake migrate VERSION=5

I have found that this approach is really useful with testing in Rails. When I think that I have everything working great (without CONSTRAINTS in PostgreSQL), I run another migration to add a bunch of foreign key and data constraints to the tables and… run my tests again.

Let’s give Active Record a Hug

This has helped me gain some trust in Active Record while still giving me that comforting feeling that PostgreSQL is acting as the body guard for my data.

Even if you don’t end up using Migrations to handle these types of database schema changes, I would highly suggest that you model your implementation after this. I’ve worked with many database schemas and this just makes it easy to add your new change and run one command to commit it to the database.

…and now I go play with beehives…

Migrating from MySQL to PostgreSQL in 60 seconds (with Rails)

October 29, 2005

I do quite a few MySQL to PostgreSQL migrations for clients of PLANET ARGON and over the years I have gone through different methods of handling this procedure. Typically, it involved exporting data, re-importing it through some shell script that does its best to take into consideration the slight differences between the two databases.

While working on a recent project that was to be migrated from MySQL to PostgreSQL, but after some Refactoring had been done to the code base. I had been meaning to spend a few hours coming up with some simplified process of taking data from MySQL and replicating it to a new PostgreSQL database, while maintaining referential integrity.

My original idea was to build a script that referenced two seperate databases and then copied data out and inserted it into the new db after performing a few data changes. This seemed like too much work and I knew that I should be able to harness the power of Ruby and Rails in my process. My next thought? RailsFS.

In a perfect world, I would mount one instance of the application with a mysql database and another with a postgresql database… and just copy the yaml files to the postgresql and bam, it’d work, right? Well, it doesn’t quite work that way. So, I ruled out that idea.

Then I had another idea. I would build a task in my Rakefile that… imported each of those YAML files into PostgreSQL!

We can now type in the following commands:

This first creates my PostgreSQL database tables using Migrations.

rake migrate VERSION=1

then…

rake mysql2pgsql

mysql2pgsql runs…and approx 60 seconds later, I had an exact copy of the MySQL database in PostgreSQL.

But wait! PostgreSQL has SEQUENCES… so I then run:

rake migrate VERSION=2

…and my SEQUENCES are ALTER’d.

Yes, I will post some code in the near future. But all I am doing is basically running through all the YAML files that are available from RailsFS and adding them into the new database. It automatically figures out the model name…and is fairly generic at the moment. However, I’d like to spend a bit more time stress-testing it before I post it. :-)

I want to try to work on a RailsFS-less version as well so that I can run this on my PowerBook.

Until next time… have fun!

Refactoring Rails... coming soon

October 27, 2005

As you may have heard earlier, Jeremy Voorhis and I are working on a top-secret project together. We’re going to keep things quiet for just a bit longer while we get an initial site together. In the meantime, sign up on our mailing list to be notified when we launch it.

We present to you…. Refactoring Rails.

Jeremy posted a short teaser on his blog and we’ll just keep you in suspense… but keep an eye out in the coming week(s). :-)

For more information, bookmark: http://www.refactoringrails.com

“Remove ambiguities and convert to specifics” - Brian Eno, Oblique Strategies

PLANET ARGON 2.0 Release Candidate

October 25, 2005

We finally found a way to sneak in some extra time to finish up the first phase of our new website. Allison and I are excited to announce the launch of new PLANET ARGON website, www.planetargon.com.

What Powers It?

Ruby on Rails and PostgreSQL!

What Has Changed?

For starters, we have a new design. Hopefully the information that you are seeking is easier to navigate to and the order process is a bit easier too. Aside from that, we’ve made just minor changes to our hosting offerings to reflect the needs of our customers. I’ll touch on that shortly.

ReEmphasize The Small Stuff

We first started offering Rails hosting to the public at the beginning of February. In just a week we’ll have nine full months of experience under our belts. Our customers have been a huge influence on the type of services we offer, and the level of support that comes with it. It was out of my own desire to have a web host that allowed for bleeding-edge technology that lead me to start my own hosting company… so that I could turn around and offer other developers, like myself, the same service, without the time commitment of managing your own server and the price tag that goes along with it.

Our Customers are Awesome!

No really, they are. We recently setup an RSS aggregator of some of our hosting customers that run blogs (many of them are running Typo). We call this site, Inhabitants of PLANET ARGON. (inhabitants.planetargon.com) Check it out!

More Space!

We’ve spent some time really looking over our hosting plans and wanted to give them a make-over that reflects the requests of our customers and potential customers. We’ve increased the disk space on the first three of our shared-hosting plans, and lowered the price on the fourth. Take a peek.

Some of our prices have gone up (with the increase in disk space), but our Level 1 plan still starts as low as $11.25/month. This can get you rolling on Rails using PostgreSQL and/or MySQL! :-)

Typo Hosting

We started offering affordable blog hosting last year. Then Typo took off, and none of the other blog software packages were being requested! We have dropped all the PHP blogging applications from our offerings and are now offering Typo Hosting exclusively. For $3/month, you can have your own pre-installed Typo blog!

FREE RAILS HOSTING!

Well, sort of. If you sign up by midnight (PST) on October 31st, you will receive 1 FREE Month for every 6 month account and 2* FREE Months* for every year! (Blogs too)

We’re Not Just a Hosting Company

PLANET ARGON was started as a web development and consulting company, and it still is!

Who Is Allison?

Allison is the Creative Director here at PLANET ARGON. Existing customers of ours know about her… but she’s kept a low profile up until now. She is a ninja in the ways of project management, clean design, and has been known to have a tab open in her browser to the Ruby on Rails API. Expect to hear more from (and about) her in the near future.

For more information, see: http://www.planetargon.com

Using Named Placeholders in Ruby

October 21, 2005

Insert Hip Quote Here:

“In ancient times, hundreds of years before the dawn of history, an ancient race of people… the Druids. No one knows who they were or what they were doing… “ - Nigel Tufnel, Spinal Tap

Story Time…

Earlier, I was giving a customer of ours, Jared from CommunityWalk.com a quick tutorial on some of the features script/console… which lead to helping him with a SQL query. When I provided him with some working code he was curious about what I had done in the SQL query string that I was passing to find_by_sql.

WARNING

If you have ANY SQL queries that resembles the following, PLEASE READ THE REST OF THIS. :-)

values = params[:search]
RockLegend.find( :all, :conditions => "first_name = '#{values['first_name']}'" )

If you are doing that… then you are opening yourself up to some security problems. Let’s take a few minutes and discuss how you can make this more secure and still keep your code readable. (the best of both worlds!)

The ? Placeholder

Many of you are probably familiar with this approach…

RockLegend.find( :all, :conditions => ['first_name = ?', 'Nigel'] )

RockLegend.find( :all, :conditions => ['first_name = ? AND last_name = ?', 'Nigel', 'Tufnel'] )

You can pass it a hash as well.. and as long as you put everything in the same order as the ?s are placed… then all is well.

My only real problem with this approach is that it requires you to keep things in a specific sequential order… and who wants to keep track of that? So, I would like to recommend that you use named placeholders. Aside from that, it looks magical and I don’t like magical-looking code. I like easy to read code. :-)

Named Placeholders

If you already use these… you know how useful they can be in your SQL queries. If you haven’t seen them before… it’s because the Rails docs don’t really mention it and is something that comes from the underlying database library in Ruby. So what is so great about these?

Let’s first replace the above code with named parameters…

RockLegend.find( :all, :conditions => ['first_name = :first_name', { :first_name => 'Nigel' } ] )

We are passing a hash with a matching key to the conditions option. Pretty neat, right? In this case with just one placeholder we just increased the amount of code to do the same thing. So, it might always be the best solution… but it is easier to read.

Let’s try another with multiple keys in our hash… infact, we’ll build the hash prior to calling find.

values = { :first_name => 'Nigel', :last_name => 'Tufnel'}
RockLegend.find( :all, :conditions => ['first_name = :first_name AND last_name = :last_name', values ] )

It will happily match the hash keys to the named placeholders in the conditions string. Again, nothing terribly exciting…but it is easier to read.

Who cares about order? Not named placeholders!

Okay, let’s mix things up a bit…

values = { :last_name => 'Tufnel', :first_name => 'Nigel' }
RockLegend.find( :all, :conditions => ['first_name = :first_name AND last_name = :last_name', values ] )

The hash keys were not added in the same order… but it still works!

Okay, now for one last quick example (it’s late and I am tired…).

I have a search mechanism on a site that allows you to search for a string of text across multiple fields. So, I have one string… but several fields to compare against.

Here is a string that I will pass to the find method.

conditions = "role = :role AND (first_name ~* :str OR last_name ~* :str OR nick_name ~* :str)"

Note: this string is using PostgreSQL regular expressions. (~*).

Here is a hash that with that matches the keys, :str and :role

values = { :str => '^(Nigel|Tufnel)$', :role => 'Guitar' }

If you look above, you’ll see that the conditions string contains four named placeholders… but the hash only has two keys. With the ? placeholder, we would have to pass the same vaule three times… which isn’t any fun to read or maintain. ;-/

So, with our new friends, named parameters, we can call find (or any find-like method) using this technique for placeholders.

RockLegend.find( :all, :conditions => [ conditions, values ] )

…and hopefully this is useful to you. :-)

Have fun!

New Active Record Options for Associations

October 19, 2005

Two months ago today I posted about a bug in Active Record. A bug that reminded me to remain cautious about how much trust I put into a database abstraction layer. I am happy to now say that this particular bug has been fixed, and I got to help! In the process, I also got to add some new features. (see my original rant, Active Record, I love U but I still trust my database server a tiny bit more.

I discovered this bug when I was working on a chapter in my book on Active Record. I’m known to gladly take advantage of database constraints and triggers, and it was when I decided to test my code without these constraints, I discovered the bug. “Hey, Active Record isn’t doing what it’s supposed to!” I’ve since had a number of people ask me if what a more pragmatic way to work around this issue is, rather than go my route by adding a constraint/trigger.

You can now DO AWAY with code>ON DELETE CASCADE! (sort of)

The new release of Rails 1.0 Release Candidate includes some new options for the has_many and has_one declarations.

Previously, you could do the following:

class Customer < ActiveRecord::Base
  has_many :orders, :dependent => true
end

This was supposed to nullify the dependent records, but it didn’t!

My patch not only fixes this, but also gives more control with what :dependent does. Now, you can pass the :dependent option to the has_many and has_one declarations with either :nullify or :destroy. This has a similar affect as ON DELETE CASCADE in those fancy RDBMs like PostgreSQL.

Let’s take a closer look at these new options:

has_one

A spider has_one web, and the web belongs_to one spider. If you destroy the spider, you would most likely want to destroy the web as well.

class Spider < ActiveRecord::Base
  has_one :web, :dependent => :destroy
end

On the other hand, in the case of a snail that has_one shell (and the one shell belongs_to the snail), if you destroy the snail, you may want to keep the shell. Remember, your crazy Aunt Ruby collects snail shells.

class Snail < ActiveRecord::Base
  has_one :shell, :dependent => :nullify
end

Now, for every snail we destroy, the shells, though once dependent on the snail, are now available for Aunt Ruby.

has_many

The same rules apply to the has_many association. Most people assume that if you destory a beehive that you would destroy all the bees. I’d like to think that they wander around until they find a new beehive to join. So, we can :nullify their relationship when the beehive is destroyed, thus making them homeless, but available for future hives.

class Beehive < ActiveRecord::Base
  has_many :bees, :dependent => :nullify
end

Sadly, some people might want to destroy the bees along with the destruction of the beehive. So, those people can pass the :dependent option, :destroy.

class Beehive < ActiveRecord::Base
  has_many :bees, :dependent => :destroy
end

Don’t worry, your usage of :dependent => true will now work, even though it wasn’t working before.

I’m going to try to put more trust into Active Record now, and I hope that this new addition to the library finds itself useful for you. :-)

Take a peak at the cool new features in the latest version of Rails and see the Active Record CHANGELOG for more information.

Enjoy!

RubyGems mirror to kill the wait

October 18, 2005

Like Dan Peterson, I have setup a mirror of the RubyGems repository on the same server that is an official RubyForge mirror.

http://rubyforge.planetargon.com/gems.rubyforge.org

gem install --source http://rubyforge.planetargon.com/gems.rubyforge.org postgres

The RubyForge mirror team is working on a gem mirroring solution… and in the meantime, this is my attempt to help out with the load.

Dan also noted that you could modify the .gemrc file:

gem: --source http://rubyforge.planetargon.com/gems.rubyforge.org

Thanks Danp for pointing this out… and Enjoy!

Is the Ruby community... nicer?

September 26, 2005

Our favorite programming guru, Martin Fowler has written a post on his bliki about Ruby People

From my years of working in the open source community, I have not seen a community so friendly and so cultured (meaning, we come from PHP, Java, .NET, Perl, Python, etc.) The elitism is minimal in the Ruby community… we all just want to have fun and write elegant code. :-)

Do you find the Ruby community friendlier?

Ruby 1.8.3 released, but Rails not liking it

September 20, 2005

Ruby 1.8.3 was released this evening. Yay!

Problem is?

/usr/local/lib/ruby/gems/1.8/gems/activesupport-1.1.1/lib/active_support/clean_logger.rb:13:in `remove_const': constant Logger::Format not defined (NameError)

Every Rails application that I tried with it died. So the solution?

cd ../ruby-1.8.2
./configure && make && make install

No 1.8.3 for PLANET ARGON yet.

The svn+rbot plugin, so far

September 15, 2005

Ben Bleything and I have put the plugin that we made up in our PDX.rb subversion repository. You can check it out here

Requires rbot and subversion.

Example:

< pdxrbot> robbyrussell * pdxrbot:/ [45] - Quick addition of the two author names :-)
< pdxrbot> robbyrussell * www:/ [5] - removing the logfiles from svn
< pdxrbot> ben * pdxrbot:/ [46] - Fix the post-commit hook so that relative paths get expanded
< pdxrbot> robbyrussell * www:/ [6] - ignoring the files in /log/ that end in .log

UPDATE This is what it spits back now. :-)

 < pdxrbot> svn.commit( pdxrbot, { :author => 'robbyrussell', :rev => 67, :log => 'another test of color/syntax...more' } )

Yes… the bot now responds with a subversion commit…and we made it look like ruby code! syntax colors and all!