Archive for January, 2010

Undefined method table_exists error in Sequel

Thursday, 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

Friday, 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

Tuesday, 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

Thursday, 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

Wednesday, 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.