Posts Tagged ‘activerecord’

hacking native UUID support into Schema:Dump

Monday, February 11th, 2008

Want to use PostgreSQL’s native UUID datatype but AR won’t let you use it with migrations?

/Library/Ruby/Gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/postgresql_adapter.rb:

# insert into
def simplified_type
  # UUID type
  when /^uuid$/
  :uuid
# insert into
def native_database_types
  :uuid      => { :name => "uuid" },

Well, that’ll get your data OUT of the database, but AR will throw a fit when you try to load it back in unless you also add uuid into the range of column types TableDefinition will accept:

in /Library/Ruby/Gems/1.8/gems/activerecord-2.0.2
/lib/active_record/connection_adapters/abstract/schema_definition.rb:

# insert into
def column(name, type, options = {})
 
%w( string text integer float decimal datetime timestamp time date binary boolean uuid ).each do |column_type|

Now you can do this:

    t.uuid     "uuid",   :null => false

About the nastiest possible hack you can do but works in/out. Here’s a patch if you don’t want to do it yourself, but no guarantees.

UPDATE:

And don’t forget to write your migrations like this to stop AR from inserting its “helpful” id columns with autoincrementing serials which your DB doesn’t need and can’t use:

  def self.up
    create_table :transactions, :id => false do |t|
      t.uuid     "id",  :null => false
      t.timestamps
    end
  end

UPDATE 2:

I now do not recommend doing this. It’s more trouble than it’s worth. There is very little you gain in forcing native UUID type in Postgres, and the complexity, hacks, loss of cross-platform compatibility and general annoyance you face are just not worth it.

Just use a string class for any UUIDs. Of course, the final hint on this page – the no-id switch for migrations – is still useful and you should use that.

ActiveRecord::Base.find(:last) in Rails 2

Thursday, January 17th, 2008

I don’t know about you, but when I see find(:first) I also expect there to be a find(:last). This hack was working in Rails 1.x but broke in Rails 2. So I fixed it. Paste this into environment.rb or wherever:

module ActiveRecord
  class Base
    def self.find_with_last(*args)
      if args.first == :last
        options = args.extract_options!
        find_without_last(:first, options.merge(:order => "#{primary_key} DESC"))
      else
        find_without_last(*args)
      end
    end
 
    class << self # Needed because we are redefining a class method
      alias_method_chain :find, :last
    end    
  end
end

I wouldn’t rely on this in actual production code (for a variety of reasons) but it’s a useful convenience method for script/console, which is where I tended to want this functionality anyway.

>> MyTable.find(:all).length
=> 2076
>> MyTable.find(:first).id
=> 1
>> MyTable.find(:last).id
=> 2076
>> puts "1337"
1337
=> nil