Recent Posts - Page 30

RubyURL meets rbot

September 13, 2005

I was asked to submit the small plugin that I created for rbot so that we can do fun stuff like this in #pdx.rb (irc.freenode.net).

21:42 < robbyonrails> ?help rubyurl
21:42 < pdxrbot> rubyurl <your long url>
21:43 < robbyonrails> ?rubyurl http://www.google.com/
21:43 < pdxrbot> Your RubyURL: http://rubyurl.com/hbGjx

It’s nothing complex and uses the plugin example as a foundation. I just popped in my ShortURL requires and modified what it replies with.

We’re almost at 2,000 unique URLs in RubyURL. :-)

You can pick up the plugin here in the trac for rbot. I don’t know if it will be accepted in the default plugins or not, but you can download the file there and start using it today!

Have fun!

Thank you hoodwink.d

August 25, 2005

So, a few days ago… I accepted the rules of the wink and have been an active winker since Tuesday… when the winking began.

If you haven’t winked yet… it might be a good time to start doing so. (while it’s cool… )

Hipster is out.. Winkster is in.

Thanks _why!

…35 winks to date!

harrisj> robbyonrails: yes, you're winking all over the place... keep it up and you'll go blind. ;) 

robbyonrails> harrisj: i saw that you winkd last night

harrisj> robbyonrails: been doing it here and there this morning... have to get it out of my system before i head off on vacation...

I have just joined #hoodwinkd on freenode.

PL/Ruby loves RubyGems and DRb

August 22, 2005

I admit it. I have had a torrid love affair with procedural languages ever since I started playing with PostgreSQL. The ability to share logic amongst all the applications touching the same database server.. was…well… a breath of fresh air.

What is a procedural language in Postgresql?

PostgreSQL docs describe them as, “…allows user-defined functions to be written in other languages besides SQL and C. “

Well, PostgreSQL has PLs for Perl, Python, Java, C, PHP… and even RUBY!

CREATE FUNCTION ruby_max(int4, int4) RETURNS int4 AS
' if args[0].to_i > args[1].to_i return args[0] else return
args[1] end ' LANGUAGE 'plruby';

PL/PGSQL is nice and all, but it’s not as fun as playing with Ruby. PL/Perl… well is perl, and PL/Python… is python. Both PL/Perl and PL/Python have untrusted variants. You see, they don’t want your PostgreSQL server to do anything harmful to the machine by being able to do stuff like system(‘cat /dev/null > /etc/passwd). But for some people, (like me) they want the flexibility of their language anyways. :-)

Note: Never do this if your system user that runs PostgreSQL has privileges to do anything harmful on your system.

The PL/Ruby documentation is minimal at the moment, but covers enough to get you started. I don’t know if many people are using it out there… but hopefully that is about to change! I’ve played with it a bit, but always wanted to be able to do stuff like require ‘rubygems’, but this is a feature of an untrusted language. I even found myself digging around in C code to see if I could figure out how to hack the plruby language to skip over those checks… but I am not a C programmer and I got lost in some header files.

Then it hit me. “Why haven’t you emailed the author?”

So I emailed the author of PL/Ruby, Guy Decoux, who responded pretty quickly with the answer to my dreams! Okay, I do have bigger dreams than this… but you get the idea.

First of all, some of you might be thinking, “Why on Earth would you want to do this?”

Well, here is a simple example of how it could be used with RedCloth Let’s say that I want to be able to perform the following query from within SQL.

SELECT redcloth('**strong text** and *emphasized text*');

Why not do this in the application? Well, I do actually have a case where I have an older PHP application that I will be porting to Ruby in the future, but would like to give the application some access to some of the features of Ruby that I will be using, such as RedCloth.

Okay, so show me an example of one of these scary PostgreSQL functions.

CREATE FUNCTION redcloth(text) RETURNS text AS '

  require "rubygems"
  require "redcloth"

  content = args[0]

  rc = RedCloth.new(content)

  return rc.to_html

' LANGUAGE 'plruby';

“Wait! You said this would be scary!?”

Well, PL/Ruby allows you to write… plain ole Ruby within your functions. (do you see where I am getting here?)

PL/Ruby meets RedCloth

rb=# SELECT redcloth('*strong text* and _emphasized text_');
                         redcloth
------------------------------------------------------------------
 <p><strong>strong text</strong> and <em>emphasized text</em></p>
(1 row)

PL/Ruby meets ShortURL

CREATE FUNCTION rubyurlize(text) RETURNS text AS '

  require "rubygems"
  require "shorturl"

  return ShortURL.shorten(args[0])

' LANGUAGE 'plruby';

…which allows for

rb=# SELECT
rb-#   rubyurlize('http://www.robbyonrails.com/') as link1,
rb-#   rubyurlize('http://moulon.inra.fr/ruby/plruby.html') as link2;

      link1           |         link2
--------------------------+------------------------
 http://rubyurl.com/lyoKm | http://rubyurl.com/dTo
(1 row)

PostgreSQL meets DRb

Okay, this is one of the reasons why I wanted to play with PL/Ruby a bit more. Distributed Ruby Objects… from PostreSQL?

What is DRb?

If you don’t know already… per the description in RDOC, “dRuby is a distributed object system for Ruby. It allows an object in one Ruby process to invoke methods on an object in another Ruby process on the same or a different machine.”

It basically allows you to share an object to other machines… at the same time!

mmm…distributed objects…

DRb Object

Here is a simple ruby script that you would run from the shell. It creates a DRb object which accepts connections at localhost:9000.

#!/usr/bin/ruby

require 'drb'

class MyRemoteObject
  def say(str)
    return "You say #{str}. I say #{str.reverse.upcase}!"
  end
end

server = MyRemoteObject.new

DRb.start_service('druby://localhost:9000', server)
DRb.thread.join

Start me up!

$ ruby mydrb.rb

Now that we have DRb running and listening for connections…we need a client to connect to it.

DRb function in PL/Ruby

Here is a very simple DRb client script and I just drop that into a PostgreSQL function.

CREATE FUNCTION drb_test(text) RETURNS text AS '

  require "drb"

  DRb.start_service

  ro = DRbObject.new(nil, "druby://localhost:9000")

  return ro.say(args[0])

' LANGUAGE 'plruby';

The result?

rb=# SELECT drb_test('Potato');
       drb_test
-------------------------------
 You say Potato. I say OTATOP!
(1 row)

Are we having fun yet?

Okay, so how do I manage to get this to work? Well… for that, you will have to read my blog post, Installing untrusted PL/Ruby for PostgreSQL

Let’s all go get some coffee (or tea) and start playing with PL/Ruby today!

Installing untrusted PL/Ruby for PostgreSQL

August 22, 2005

This is going to be short and sweet.

“PL/Ruby is a loadable procedural language for the Postgres database system that enable the Ruby language to create functions and trigger procedures”

Method 1. The standard, safe, PL/Ruby.

Before running this, you need to have all the PostgreSQL headers installed. (se INSTALL in the postgresql directory)
make install-all-headers

To install PL/Ruby, you need to download the tarball from here. As you can see, I download it with wget and then install like I would any ruby library. (maybe plruby could become a gem?)

cd /usr/local/src
wget ftp://moulon.inra.fr/pub/ruby/plruby.tar.gz
tar zxvf plruby.tar.gz
cd plruby
ruby extconf.rb
make
make install

Method 2: The untrusted, but super cool PL/Ruby.

Guy Decoux, author of PL/Ruby, was kind enough to share a secret about the PL/Ruby install. (from his email…)

Well plruby normally run with $SAFE = 12, this value if fixed at compile time. 

Now it has an undocumented option, if you compile it with

ruby extconf.rb --with-safe-level=0 ...

 it will run with $SAFE = 0 and you have the equivalent of an untrusted language.

Pretty simple solution, eh?

On my server I was able to run the following:

cd /usr/local/src
wget ftp://moulon.inra.fr/pub/ruby/plruby.tar.gz
tar zxvf plruby.tar.gz
cd plruby
sudo ruby extconf.rb \ --with-pgsql-dir=/usr/local/pgsql-8.0 \ --with-safe-level=0 \ --with-suffix=u
make
make install

Update: the --with-suffix=u was added after someone commented on this. This allows you to install plruby and plrubyu.

Installing PL/Ruby in PostgreSQL
Up until now, you haven’t actually installed the language into the database. We’re close though!

All that you need to do is run the following commands to install it to a specific database in your server.

$ psql template1
template1=# CREATE DATABASE plruby;
CREATE DATABASE
template1=# \c plruby
You are now connected to database "plruby".
plruby=#    create function plruby_call_handler() returns language_handler
plruby-#    as '/usr/lib/site_ruby/1.8/i386-linux/plruby.so'
plruby-#    language 'C';
CREATE FUNCTION
plruby=#    create  language 'plruby'
plruby-#    handler plruby_call_handler
plruby-#    lancompiler 'PL/Ruby';
CREATE LANGUAGE
plruby=#

That should be all there is to it!

Where do we go from here?

See my post: PL/Ruby loves RubyGems and DRb

Are you a console master?

August 18, 2005

I have a few questions.

1.) Do you know what ./script/console does?

2.) If not, why not?

3.) If so, do you have any fun tips and tricks to share with the masses?

It occured to me earlier that many people, who might have came from the PHP camp, may have never really tested their object-oriented code from some sort of interactive program. (irb) If you are coming from the Python, Java, etc worlds, interactive testing isn’t anything new. Rails is nice enough to bundle a console script right within it!

I meet people online who have never even tried to run it. There are not many tutorials on the wiki that show console… and in my opinion, its one of the coolest things about Ruby and Rails. (but, I come from the php world…)

So, if you aren’t using it… why not? got a moment? try this from the root path of your Rails application.

./script/console

It start up okay? If so, what is the name of one of your models? Let’s say that I have a model structure like:

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

class Order < ActiveRecord::Base
  belongs_to :customer
end

From console, you can access your models and do all sorts of fun things.

>> y = Customer.find(16)
=> #<Customer:0x2743ea4 @attributes={"name"=>"Robby", "id"=>"16"}>
>> y.orders
=> [#<Order:0x27416b8 @attributes={"id"=>"18", "amount"=>"12.00", "customer_id"=>"16"}>, #<Order:0x274167c @attributes={"id"=>"19", "amount"=>"12.50", "customer_id"=>"16"}>] 

Pretty neat, huh?

>> o = Order.find(18)
=> #<Order:0x273da68 @attributes={"id"=>"18", "amount"=>"12.00", "customer_id"=>"16"}>
>> o.customer.name
=> "Robby"

If you are remotely a console wizard, please share some tips and tricks for those who are not sure what to do with it. I personally find myself in console all the time that I am working with Rails, testing stuff out with my models, before I move any of the code to my application.

It sure beats, hitting refresh in your browser all day. :-)

Active Record, I <3 U but I still trust my database server (a tiny bit more)

August 18, 2005

While working on a portion of my book, I found myself in ./script/console and was seeing some weird issues when I would use has_many and belongs_to.

Let’s take two simple models.

<pre>
class Order < ActiveRecord::Base
  belongs_to :customer
end
 
class Customer < ActiveRecord::Base
  has_many :orders
end
</pre>
</code>

After a few test records...

<code>
<pre>
test_dev=# SELECT * FROM customers;  
 id |      name      
----+----------------
  1 | Robby
  2 | Nigel
  3 | Linus
(3 rows)
 
test_dev=# SELECT * FROM orders;
 id | customer_id | amount 
----+-------------+--------
  1 |           1 |  12.00
  2 |           3 |  12.00
(2 rows)
</pre>
</code>

Nothing completely crazy going on, right?

<typo:code lang="ruby">
Loading development environment.
>> Customer.destroy(3)
=> {"name"=>"Linus", "id"=>"3"}
>>     

=# SELECT * FROM orders;
 id | customer_id | amount 
----+-------------+--------
  1 |           1 |  12.00
  3 |           3 |  12.00
(2 rows)

Wait a minute! I just deleted a customer with an id of 3!

So, what is wrong with this scenario? Can you think of any potential problems that could occur from data like this? The record has a customer_id for a customer that does not exist. This is why we have relational databases in the first place, right? :-)

Here is something that I learned today that I was unaware of. Active Record allows you to pass the has_method declaration the option :dependent.

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

What is this option? Well, according to the AR documentation, “:dependent - if set to true all the associated object are destroyed alongside this object. May not be set if :exclusively_dependent is also set.”

In a nutshell, this works like ON DELETE CASCADE does in PostgreSQL. So, it will through and delete the orders associated with the customer that I was attempting to destroy.

Up until today, I hadn’t broken myself out of the habit of using the built-in constraints/triggers of PostgreSQL. So, as soon as I did, this issue came up and I learned about :dependent.

test_dev# \d orders
                                Table "public.orders"
   Column    |     Type      |                       Modifiers                        
-------------+---------------+--------------------------------------------------------
 id          | integer       | not null default nextval('public.orders_id_seq'::text)
 customer_id | integer       | 
 amount      | numeric(10,2) | 
Indexes:
    "orders_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "orders_customer_id_fkey" FOREIGN KEY (customer_id) REFERENCES customers(id)
 
test_dev=# ALTER TABLE orders DROP CONSTRAINT orders_customer_id_fkey;
ALTER TABLE 
 
RobbyOnRails:~/Programming/footest robbyrussell$ ./script/console 
Loading development environment.
>> cust = Customer.create(:name => 'Jim')
=> #<Customer:0x275373c @new_record_before_save=true, @new_record=false, @attributes={"name"=>"Jim", "id"=>5}, @errors=#<ActiveRecord::Errors:0x274fa88 @base=#<Customer:0x275373c ...>, @errors={}>>
>> cust.orders.create(:amount => '25.00')
=> #<Order:0x274991c @new_record=false, @attributes={"id"=>4, "amount"=>"25.00", "customer_id"=>5}, @errors=#<ActiveRecord::Errors:0x2746dfc @base=#<Order:0x274991c ...>, @errors={}>>
>>                
 
 
test_dev=# SELECT * FROM orders;
 id | customer_id | amount 
----+-------------+--------
  1 |           1 |  12.00
  3 |           4 |  29.00
  4 |           5 |  25.00
(3 rows)

As you can see, I put myself into the hands of Active Record when I ran the DROP CONSTRAINT. Then I tried running the code at the top of the post… and it didn’t work.

According to the docs, if you use :dependent => true, it should delete the foreign table records. If not, it should set the value of the foriegn key field to NULL in the foreign table.

Basically, perform these two SQL queries:

UPDATE orders SET customer_id = NULL WHERE customer_id = 17; 

DELETE FROM customers  WHERE id = 17;

Then, the records are still in the database for those orders, but the customer is deleted. There are arguments for and against doing this sort of thing… but the ability to have the option is always nice. In any event, Active Record would not run the first query,it was just deleting from the customers table. Without my constraint, no error would be returned from PostgreSQL and I started to get some bad data.

Imagine showing a list of orders and trying to display the customer name associated with an order that has no linking customer. Doh! If Active Record sets the customer_id to NULL we can at least have some logic to work with this without having to run some fun SQL queries to figure out which orders do and dont have customers. (we want our applications to have clean data!)

Anyhow… Was this a bug? Should Active Record know to update the records to NULL in this case? I figured that is should be handling this task, especially since it was handling cascading deletes when you passed :dependent => true.

However, I didn’t want to prematurely post a bug report, so I began asking around on #rubyonrails (irc.freenode.net). People made a bunch of suggestions as to how to work around it. I could add a before_destroy method in my model, track the bug down, (re)add an ON DELETE trigger to my table (hah), etc. So, I decided that I would see if I could track down what happens when has_many is used for a model upon #destroy.

After a while of digging and making some tests, I posted a patch and a bug report. (please disregard my first patch… it did not work! heh)

Now that I figured this out, I am going to happy add my constraints back to my tables and go back to playing around. This reminded me of a post I had a few months ago when I mentioned that I thought it was best to put some constraints and logic in the database. I also agree that constraints should be put in the abstraction layer, but we cannot always put all faith in our code either. A few levels of checks doesn’t hurt. :-)

This was a fun little riddle that I took on today. The moral of the story? If you have the ability to use the builtin referential integrity features of PostgreSQL and those other databases, it might be a good idea to do so. Things get overlooked, people login to the database in many ways, and from different programs.

UPDATE: DHH responded to this post and provided a link which discusses Application Database versus Integrated Database

It should be noted that there is an important distinction between the two methods. When I said, “Things get overlooked, people login to the database in many ways, and from different programs” I was basically describing Integration Database. However, I was also thinking of the possibility of someone opening up their MySQL or PostgreSQL GUI and manually removing a record in plain SQL. According to Application Database, the moment that you do that, you basically break this model and cannot expect your application to be fully responsible for the problems that may or may not occur. At this point, you would need to look at your application in terms of Integration Database. Please do correct me if I am wrong on this. :-)

However, with this scenario, my first attempt to move to relying on AR had a minor hiccup, but it was an easy enough fix.

By performing the following command, I am moving towards an Integration Database pattern and that should be recognized when taking this into consideration.

ALTER TABLE orders ADD CONSTRAINT orders_customers_id_fkey 
    FOREIGN KEY (customer_id) REFERENCES customers (id) MATCH FULL; 

Okay, back to work!

Once again. Use constraints! (if you can)

… and thanks to DHH for providing the link and motivating me to make a note of this in my entry.

The legacy of databases with Rails

July 25, 2005

As I have had way too much experience with working with horribly ugly and outdated database schemas, I find myself wanting to add new interfaces, but can’t just drop their old schema as other applications rely upon it.

Let’s say that you have an old table that looks like this:

mysql> DESCRIBE client_comment;
+---------------------+--------+------+-----+---------+----------------+
| Field               | Type   | Null | Key | Default | Extra          |
+---------------------+--------+------+-----+---------+----------------+
| client_comment_id   | int(8) |      | PRI | NULL    | auto_increment |
| client_comment_body | text   | YES  |     | NULL    |                |
+---------------------+--------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

In this example, I took the privilege of making the example only two fields, now imagine that this table has over 20-30 fields and they all have client_comment_ in front of the actual string that is of important. Who wants to type all that out over and over? Also, we all refer to this table as the table that holds customer notes, which doesn’t really match what they originally named it. No, we can’t just renmae the table, stuff relies on this structure. But for a new Rails interface, we’re going to tweak our model quickly to interact with the same outdated table in a cleaner fashion.

The first obvious thing is that we need to create a model called customer_note.rb.

class CustomerNote < ActiveRecord::Base
end

Next, we’ll tell the model that it’s table name is client_comment, rather than customer_notes like it is going to expect it to be. While we are at it, let’s take a quick moment to define the primary key for this table, because id is not what they picked when they first made the table.

class CustomerNote < ActiveRecord::Base

  set_primary_key "client_comment_id"

  def self.table_name() "client_comment" end

end

With this, we can already start interacting with our table as if it were called customer_notes.

$ ./script/console
Loading development environment.
>> CustomerNote.create(:client_comment_body => "hello world")
=> #<CustomerNote:0xb7a02cfc @new_record=false, @attributes={"client_comment_body"=>"hello world", "client_comment_id"=>39}, @errors=#<ActiveRecord::Errors:0xb79a4508 @base=#<CustomerNote:0xb7a02cfc ...>, @errors={}>>

Okay, now we want to interact with the field client_comment_body as just body. We want to be able to get and set this value, so we’ll add the following methods to our model.

def body
    read_attribute "client_comment_body"
  end

  def body=(value)
    write_attribute "client_comment_body", value
  end

The first method allows you to access (get) the value of client_comment_body with CustomerNote.find(1).body. The second method handles when you (set) the value for body, it then provides the client_comment_body attribute with the value. Technoweenie on IRC helped me get this trimmed down from my original version.

In the end, you have this:

class CustomerNote < ActiveRecord::Base

  set_primary_key "client_comment_id"

  def self.table_name() "client_comment" end

  def body
    read_attribute "client_comment_body"
  end

  def body=(value)
    write_attribute "client_comment_body", value
  end

end

Then, you can do save yourself some typing by accessing the field with the alias that you provided. :-)

$ ./script/console
Loading development environment.
>> a = CustomerNote.new(:body => "Hello World!")
=> #<CustomerNote:0xb78c6ffc @new_record=true, @attributes={"client_comment_body"=>"Hello World!"}>
>> a.save
=> true
>> a
=> #<CustomerNote:0xb78c6ffc @new_record=false, @attributes={"client_comment_body"=>"Hello World!", "client_comment_id"=>40}, @errors=#<ActiveRecord::Errors:0xb7890d6c @base=#<CustomerNote:0xb78c6ffc ...>, @errors={}>>
>> b = CustomerNote.find(40)
=> #<CustomerNote:0xb788ccd0 @attributes={"client_comment_body"=>"Hello World!", "client_comment_id"=>"40"}>
>> b.body = "Goodbye...cruel... world."
=> "Goodbye...cruel... world."
>> b.save
=> true
>> CustomerNote.find(40)
=> #<CustomerNote:0xb7886330 @attributes={"client_comment_body"=>"Goodbye...cruel... world.", "client_comment_id"=>"40"}>
>> CustomerNote.find(40).body
=> "Goodbye...cruel... world."
>>

Feel free to send me tips if there is an even better way of doing this. :-)

Cheers… and enjoy!

Working in Portland coffee shops and cafes reviews, part 1

July 21, 2005

Since I have found myself sitting in cafes and coffee shops a lot, I thought that I would give a quick and dirty review of a few that I frequent.

Costellos Travel Caffe - My first trip here was to meet Rael Dornfest of O’Reilly for lunch. I had a vegan tomato soup that day and have been in love with that place since. Free wifi + good food = Costellos. They have a nice, short menu, with soups, sandwiches, and salads. In regards to the coffee, they have the best soy mochas out of this list of cafes. You can also enjoy a good foreign beer or glass of wine. They always run videos on the 2 large widescreens on the walls, of photographs and videos from different places around the world. It’s usually soundtracked to some instrumental music… for example, the last time I was in there, I heard Sigur Ros and Lemon Jelly while video showed. It’s a pretty cool place and I need to thank Rael for inviting me there. :-)

My only problem with working there is that it does attract a lot of traffic and finding a good seat isn’t always realistic. You can get lucky… but finding a spot with a power outlet isn’t always guaranteed…infact, you’d best charge up before getting there… as I’d be the guy in the corner with the plug in use already. ;-)

Urban Grind (NE) - This is my morning-to-noon place. They do serve food, but I haven’t actually tried their sandwiches or soups yet. I enjoy their coffee and go here the most. The place is in a big warehouse and it has many tables that are perfect for working at. My girlfriend often comes with me and we sit side by side on our laptops and have enough space to spread out a bit. Free wifi as well and tons of extension cords for people to plug in. There is more of a regulars atmosphere there. The same people show up each day and it’s very calm. My only wish is that they stayed open later than 4 PM. The one in NW has later hours, but that would require me to drive or bus to the other corner of town. I also prefer the laid back nature of NE/SE in contrast to the NW area. Music typically heard include, bjork, interpol… just to name a few. I usually have my headphones on anyways.

Fireside Coffee Lodge - Located in SE Portland, this is the farthest regular spot that I go to. Why would I go so far? They are open 24 hours. Yep, 24 hours of free wifi and coffee… how can you pass that up? When and if I get the urge to work at 2 AM, I can head there and have a good and quiet time. It has several outlets for juicing your laptop and has some tastey coffee drinks. (might I suggest the Almond Joy…) I have been going there for several years with PDXLUG, which is where we hold our monthly meetings. The seats aren’t as comfortable and the tables aren’t either.. but that doesn’t matter when you need that 3:15 AM coding fix and you want to get out of the house for a bit. I spent a lot of time there this last spring when my girlfriend was finishing up here semester in college doing homework. Music doesn’t really play here too often and if so, it’s usually one of the girls at the counter playing NPR.

Redwing Coffee & Baking - Honestly, sitting here.. this is my first time here. What provoked this entry was that I felt that someone should provide a quick and dirty list of places in Portland to work on. So maybe I will work on a site for that in the future and such… as opposed to just how good the food/coffee is… how easy is it to spend 6+ hours in it? Laptop batteries don’t last that long.. and as there seems to be only one power outlet..and I got lucky to snag it. So, I don’t know if this place is ideal for working more than a few hours in. They are currently playing Neil Young… and I’d guess that older stuff like Young, Dylan, and maybe some other 60s/70s stuff would be common here. It’s quite warm in here too as they are baking food in the back. It makes for a nice smell, but when it’s 90~ degrees F outside, it doesn’t cool you down much. They’re open to 8 PM and look like they have a good menu for vegetarians, (like me).

UPDATE: They have free iced tea refills… that’s great!

On a side note, it just started to sprinkle. My day just got a little better. :-)

So, there is my list of a few common places that I go to. I will post more in the near future, but thought that I would start off with the last 4 places that I have been to. I intend on trying more and will continue working on this list.

back to writing… and to my hummus plate.

Portlanders… do you have any places to suggest for working at? I’d like to continue my search for the perfect away-from-the-office cafe.

PostgreSQL vs MySQL with Rails

June 18, 2005

Every once in a while, there is a short debate about using MySQL or PostgreSQL with Ruby on Rails as a database server. If you know me at all, you’ll know that I am a strong proponent of using PostgreSQL. Putting some logic in the database is something that my last few jobs have completely trained me to do.

For example, I try to develop applications under the assumption that it will never be the only interface to the data set that it uses. In a way, I use the database as a part of the model and don’t put the reliance on the model in my Rails application.

For example, take the following example of updating a bunch of records that meet a certain requirement.

Items.find(:all, :conditions => "type_id='2'") do |item| 
    item.x = "foo"
    item.save 
end

Is this method quicker than running a simple UPDATE query on the database? With a smaller data set, this might not be big enough of a concern. But, what if your database has a million rows that meets this criteria? Does it make sense to find them all first and then loop through the recordset one million times and call one million updates? A few problems might occur, one big potential issue is that it is likely that your application might go beyond the timeout of your server and there is no rollback with this transaction.

So, what is the best Rails-way to solve this problem?

If the request takes too long and times out, how do you ROLLBACK your updates automatically? I know how to do this with PostgreSQL (quite simply), but am curious as to how this is addressed by MySQL proponents.

Let’s take another scenario. Perhaps you have a table called foobars. Every time you INSERT or UPDATE this table, you want to add a record into table foobarlogs that shows what was added or what fields were specifically changed. With PostgreSQL, you could build a trigger that compares the existing record with the new values and then adds the differences into the foobarlogs table. This might not be something that people encounter, but for some systems, it’s vital that you know when something happened, by whom, and what exactly happened.

Step forward into the future. Client needs a new interface built for desktop usage. Yes, you could use Ruby with wxWidgets and build a nice multi-platform application. In your code, you deal with the same database. With your trigger in place, you don’t need to do anything but call it like you did with Rails.

Yes, MySQL is getting advanced features, but its still a while before you’re going to get to use pl/Ruby for building your database functions.

Wouldn’t this follow more along the lines of the DRY principal than doing this in the Rails code?

- A curious PostgreSQL-fan

PostgreSQL, all the features you need next year, available last year.

On a side note, here is a good explanation of how PostgreSQL is useful for certain application requirements.

Playing with Rails Day projects

June 05, 2005

Woke up, Rails Day site was down. noradio on irc mentioned that the svn repos were up though. :-)

Earlier this morning, I checked out every Rails Day project and started picking random ones to try to play with. I showed people on #rubyonrails. Of about 30 that I tried to run, I had good experiences with about 5-10. It was surprising to see that a lot of people didn’t put a db schema file in db/. (which prevented me from getting too far)

I am going to tinker with more later, but had to get some of my own work done.

Some of the cool ones that I saw so far were, Sheets, Catfish, fischbowl (spelling), and there was one more but I don’t remember the name. I’ll have to look at them again. I was just picking random project #s and trying… so there are probably lots of them to see. :-)

What were are your favorites so far?
project name and #:

Extending ActionController

June 05, 2005

In my pursuit yesterday to make add the desired functionality to ActionController (render string to string), I talked to bitsweat about this and he suggested that I just extend the class in my rails app.

So, I created a file in lib, called action_controller_ext.rb (a shim as he referred to it) and put this in the file:

require 'action_controller'

class ActionController::Base

  def render_string_to_string(text = nil, type = "rhtml") #:doc:
    add_variables_to_assigns
    @template.render_template(type, text) 
  end
  
end

Then in environment.rb, I changed:

require 'action_controller'

to

require 'action_controller_ext'

Now, I can move my clients app around dev/test/live servers and not need to modify the actual Rails source code. (still would be nice if it did that though)