Undefined method table_exists error in Sequel

January 28th, 2010

I’m trying to set up a Scanty blog, using Christopher Swenson’s scanty_wordpress_import script to import my wordpress entries. I was getting a strange error, that Google didn’t recognize:

./lib/post.rb:7: undefined method `table_exists?' for Post:Class (NoMethodError)

I found the answer in a few Japanese language posts, but since it was a little difficult to decipher, I’m posting the deets here. The solution is simply to install the schema plugin in the Sequel model (Post, in this case):

class Post < Sequel::Model
  plugin :schema
 
  ...

DataMapper required columns error

January 22nd, 2010

If you’re getting an “ArgumentError: options :required are unknown” error when trying to use required columns in DataMapper (i.e. property :name, String, :required => true), you need to upgrade your DataMapper to version 0.10.2 or later.

Fancy dates

January 19th, 2010

The software I’m writing uses lots of dates, and I got tired of typing Date.parse over and over again, so I tried to write a little module that would let me create dates more simply:

module FancyDates
  (1..12).each do |mo| 
    t = Time.mktime(Date.today.year,mo)
    three_letter = t.strftime("%b")
    t.instance_eval do
      def [](d)
        t = Time.mktime(1999,month,d)
        t.instance_eval do
          def [](y)
            Time.mktime(y,month,day)
          end
        end
        t
      end
    end
 
    const_set(three_letter.to_sym, t)
  end
end

This lets me just type Jan[19][2010] or even Jan[19] and get a date back. It’s sort of messy looking, but I couldn’t think of a cleaner way to do it. If you have any suggestions for refactoring, submit them here.

Update: Pavel Gorbokon posted a much simpler way to do this on RefactorMyCode. Thanks Pavel!

Optional validation for ActiveRecord objects in Rails

January 14th, 2010

Sometimes in rails I want to validate objects, but only sometimes. Particularly in my specs, sometimes I want to put an object in the database without validating because I know I’m not going to need some of the parameters, and it’d pollute my specs to include them.

Here’s how I do it:

class Outfit < ActiveRecord::Base
 
  def validate
    errors.add_on_empty :pants unless lazy_validation?
  end
 
  def lazy
    dup.instance_eval { @lazy_validation = true; self }
  end
 
  def lazy_validation?
    @lazy_validation == true
  end
end

That way if I use the object normally (Outfit.create!) I’ll get an error, but in my specs I can just do…

it "should be ok" do
  o = Outfit.new.lazy
  o.save!
  o.should be_valid
end

And everything works hunky-dory. You can also do it the other way, where you set the object to be strict, and only validate if you’ve done that.

Rake tasks with parameters in Rails apps

January 13th, 2010

This took a bit of excessive Googling to figure out, so I thought I’d post a wrap-up here. If you want to create a Rake task that has access to your Rails app’s ActiveModel objects and all the other good Railsy bits, you write it like this:

desc "Prints out the names of all users"
task :print_user_names => :environment do
  User.all.each do |user|
    puts "#{user.first} #{user.last}"
  end
end

If you put that in a .rake file in your RAILS_ROOT/lib/tasks folder, you can run it from your RAILS_ROOT by running “rake print_user_names”.

Easy enough, but the :task_name => :environment bit is a little tricky. But now what if you want to pass some parameters/arguments to your task? Say to print out the name of a specific user? That looks like this:

desc "Look up the name for a particular user id"
task :get_name, :id, :needs => :environment do |task, args|
  user = User.find(args[:id])
  puts "#{user.first} #{user.last}"
end

Then you can look up users by running “rake get_name[14]“, where 14 is the id of the user you’re looking up.

Simple enough but took me a little while to find.

Finding ActiveRecords by time

September 30th, 2009

This was a bit of a head scratcher. I was trying to look up some ActiveRecord rows created after a certain time, but the comparison seemed to be off by several hours. If there was a record created at 1pm, it’d show up even if I was asking for records created after 7pm.

There’s a bunch of discussion about this issue, but in the end the solution for me was just to explicitly convert the time I was comparing against to UTC (the timezone used for storing dates in the database). Like so:

Entry.find(:all, :conditions => ["created_at > ?", time.utc])

Not so hard.

Failed google keywords: activerecord, timezone, ruby, datetime, off by, bug, comparison, rails

undefined method ‘use_transactional_fixtures’

September 28th, 2009

I was upgrading some of my gems (rails, etc), and I got this error when I ran cucumber:

undefined method `use_transactional_fixtures' for Cucumber::Rails:Module (NoMethodError)
./features/support/env.rb:11

I poked around but none of the google solutions worked exactly. I ended up just running

script/generate cucumber

again, which regenerated my features/support/env.rb and everything, and it seems to have solved the issue.

Migrating up and down quickly

August 27th, 2009

I frequently make a migration, migrate, run my tests and realize there’s a bug with my migration, or I forgot something, or whatever. It’s kind of annoying to have to type:

rake db:migrate
rake db:migrate RAILS_ENV=test
# run tests, watch tests fail
rake db:rollback
rake db:rollback RAILS_ENV=test
# fix code and repeat

… over and over and over. So I wrote a couple little rake tasks:

task :mig do
  dev_and_test("migrate")
end
 
task :roll do
  dev_and_test("rollback")
end
 
def dev_and_test(what)
  ["development", "test"].each do |env|
    system "rake db:#{what} RAILS_ENV=#{env}"
  end
end

Now I can just do:

rake mig
# run tests, fail
rake roll
#fix code, rinse, repeat

Much nicer.

Strip leading zeros in string formatting

August 26th, 2009

There is lots of talk out there about how to strip leading zeros from dates and times in Ruby and PHP. Ruby’s documentation on the subject is woefully inadequate.

The problem is that many of the format tokens they list have leading zeroes. So if I format todays date like so:

Date.today.strftime("%m/%d")

… It will tell me it’s “08/26″. Note the leading zero.

Some people will tell you to use %j and %e instead of %m and %d, which seems to work in newer versions of Ruby. Other people use elaborate regular expressions to clean up their dates after formatting them.

But the best advice I’ve found is in the comment on this post: Just put a -1 in each format token like so:

Date.today.strftime("%-1m/%-1d")

That expression will return “8/26″. The -1 basically means “print this number, but strip off up to 1 zero before you do.”

Seems like a more proper way to do things.

Search bait: zeroes, sprintf, format, padding, date, time, datetime, rails

Gem doesn’t install executables

April 17th, 2009

I was very confused about where Gem was installing executables, since my gems weren’t available from the command line. I would do gem install rspec, and then when I try to run spec, get:

bash: spec: command not found

Same for rails, cucumber, everything. Turns out gem puts executable scripts into /var/lib/gems/1.8/gems/rails-2.3.2/bin, which means all I had to do was add:

export PATH=$PATH:/var/lib/gems/1.8/gems/rails-2.3.2/bin

to my ~/.bashrc and I was good to go. Sort of a strange situation, and I wasn’t able to get any love on the internet. Had to figure it out myself which ended up taking maybe a month of poking around every now and then. I would’ve hoped an apt-get install rubygems would’ve made this unnecessary.