Stubbing Authlogic’s current_user in specs

March 10th, 2010

I’m using Rspec to test my app, and I’m doing integration tests where I want to be able to stub the currrent user. There’s supposedly a set_session_for(user) helper, but it didn’t work for me. Stubbing it by hand was easy enough though:

UserSession.stub!(:find).and_return(mock_model(UserSession, :user => user))

ActionMailer not sending mail

March 9th, 2010

I just spent a while struggling with ActionMailer to get it to actually send email through a gmail account.  Everything seemed like it was working, but the mails were silently not getting delivered.  I ended up finding this rather helpful post which pointed me at the action_mailer_tls library.  Just install the action_mailer_tls gem and throw this in your config/environments/development.rb and production.rb:

require "smtp_tls"
 
ActionMailer::Base.raise_delivery_errors = false
ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
  :address => "smtp.gmail.com",
  :port => 587,
  :domain => 'gmail.com',
  :user_name => "your_gmail_address",
  :password => "your_gmail_password",
  :authentication => :plain
}

That got me on my way, but I also was running into the problem that specifying a full name in my email address (”Erik Pukinskis “) was preventing the emails from going through. It was Dmitry Polushkin’s suggestion to monkeypatch ActionMailer that worked for me. He suggests throwing this in your environment.rb:

module ActionMailer
  class Base
    def perform_delivery_smtp(mail)
      destinations = mail.destinations
      mail.ready_to_send
      sender = (mail['return-path'] && mail['return-path'].spec) || Array(mail.from).first
 
      smtp = Net::SMTP.new(smtp_settings[:address], smtp_settings[:port])
      smtp.enable_starttls_auto if smtp_settings[:enable_starttls_auto] && smtp.respond_to?(:enable_starttls_auto)
      smtp.start(smtp_settings[:domain], smtp_settings[:user_name], smtp_settings[:password],
                 smtp_settings[:authentication]) do |smtp|
        smtp.sendmail(mail.encoded, sender, destinations)
      end
    end
  end
end

Now my mail is getting sent! The emails still aren’t getting generated properly, but at least that’s my code I can fix…

Failed Google searches: tmail angle brackets, perform_delivery_smtp, action_mailer/base.rb, activemailer angle brackets, Net::SMTPFatalError: 555 5.5.2 Syntax error, activemailer actionmailer not sending

Incorporating Delayed Job in rspec specs

March 5th, 2010

I wanted to test the results of some Delayed Job enabled methods in my specs. DJ has a nice method Delayed::Job.work_off that does all of the jobs on the queue. Unfortunately, it does them in a separate thread, so if you run it from rspec and there are errors in your jobs, rspec never hears about them. My solution was to write an even simpler, in-thread job runner:

# lib/delayed_job_spec_helper.rb
module DelayedJobSpecHelper
  def work_off
    Delayed::Job.all.each do |job|
      job.payload_object.perform
    end
  end
end

My spec might look like this:

describe Thingy do
  include DelayedJobSpecHelper
 
  it "should have been worked on if I do something that queues jobs" do
    thing = Thingy.new
    thing.method_that_queues_jobs
    work_off
    thing.should be_worked_on
  end
end

Voila.

Duplicate key weirdness

March 1st, 2010

Was getting this error whenever I tried to create a new object in my database:

DataObjects::IntegrityError: ERROR:  duplicate key value violates unique constraint "posts_pkey"

Figured out, thanks to this, the solution in DataMapper is to reset the sequence id:

select setval('contracts_id_seq', (select max(id) + 1 from contracts));

Fast update to Heroku

March 1st, 2010

I find myself repeatedly committing changes and pushing them to Heroku, so I wrote this little shell script so I can do it in one command:

#!/bin/bash
git add .
git commit -m "$1"
git push heroku master

This way I can just run hero “made some changes” and my changes are committed and heroku is updated.

datamapper + sinatra-authentication on heroku

March 1st, 2010

I’ve got a Sintra app that was working fine locally, but giving this confounding error when on Heroku:

/usr/local/lib/ruby/site_ruby/1.8/rubygems.rb:280:in `activate': can't activate addressable (~> 2.0.2, runtime) for ["dm-core-0.9.11"], already activated addressable-2.1.1 for ["data_objects-0.9.11", "dm-core-0.9.11"] (Gem::LoadError)

The problem was that Heroku by default installs a relatively old version of DataMapper (0.9.something). The solution was just to specify some specific gersions of things in a specific order in my gem manifest (.gems):

addressable --version 2.1.1
data_objects --version 0.10.1
do_postgres --version 0.10.1
dm-validations --version 0.10.2
dm-timestamps --version 0.10.2
dm-core --version 0.10.2
sinatra-authentication --version 0.2.3

Crazy that I have to go to such lengths, but it works!

Use length on your arrays, not count

February 22nd, 2010

This took me a while to figure out, but some versions of ruby don’t support the :count method on arrays, while others do. I have no idea which ones do, but the solution is simple:

Use length, not count.

Failed google searches: NoMethodError: undefined method `count’ for []:Array

String.starts_with

February 19th, 2010

Am I the only one who constantly wishes Ruby’s String object had a starts_with method? Well, here it is:

class String
  def starts_with(chunk)
    self[0,chunk.length] == chunk
  end
end

Throw that in lib/core_extensions.rb and put require ‘core_extensions’ in your config/environment.rb inside the config blog.

Importing CSV values into ActiveRecord tables

February 17th, 2010

I have been using Google Docs lately to store some of my data, and then wanting to import it into my Rails application. I poked around the web for an easy way to load CSV data into an ActiveRecord table, but the only options were using the CSV library and hard coding table names and such. Why not just a simple rake task that takes an arbitrary CSV file (with a header!) and a model name, and imports?

So, I wrote it quickly:

#lib/tasks/import.rake
desc "Imports a CSV file into an ActiveRecord table"
task :csv_model_import, :filename, :model, :needs => :environment do |task,args|
  lines = File.new(args[:filename]).readlines
  header = lines.shift.strip
  keys = header.split(',')
  lines.each do |line|
    params = {}
    values = line.strip.split(',')
    keys.each_with_index do |key,i|
      params[key] = values[i]
    end
    Module.const_get(args[:model]).create(params)
  end
end

You can then do…

rake csv_model_import[bunnies.csv,Bunny]

… to import your CSV file. Note that your CSV needs to have a header line with the attribute names:

name,age,favorite_food
tabitha,2,carrots
elijah,1,lettuce
beatrice,3,apples

Search keywords: activerecord import csv rows load database table model

How to change the width/height of Gruff’s images

February 17th, 2010

It took me a little while to figure this out, and I had to dig into the source code, but if you’re generating images with Gruff and you don’t want them to be 800 pixels wide, just pass a different width to the constructor:

g = Gruff::Line.new(400)

You can also pass a string with your desired dimensions:

g = Gruff::Line.new('400x200')

There are a few good tips here too, for showing/hiding the legend and titles and such too.

Google keywords: gruff width height output graph_width scale size pixels rendering