Missing host to link to! Please provide :host parameter

If you’ve followed my version of the authlogic account activation tutorial or the original version by Matt Hooks you might have run into this error:

Missing host to link to! Please provide :host parameter or set default_url_options[:host] when sending emails

When authlogic sends e-mails with the account activation link, it uses a url_for helper to build that link. Because the “Notifier” mailer is an instance of ActionMailer::Base and not ActionController::Base it doesn’t know what the host parameter of the URL should be, so you have to tell it explicitly.

Put the following into your environments/development.rb and environments/test.rb:

1
2
# This assumes you're running your local development server on port 3000 via script/server
config.action_mailer.default_url_options = { :host => "127.0.0.1:3000" }

Put this into your environments/production.rb:

1
2
# Replace example.org with your actual domain name
config.action_mailer.default_url_options = { :host => "example.org" }

RSpec Shared Example before(:each) Gotcha

Shared example groups are a great feature of Rspec that help you simplify your tests and keep your code DRY. You setup shared example groups almost exactly like you would a regular set of specs, but these similarities can be slightly misleading.

Below we have an example model, spec and shared example group. Our Dog model has its own set of functionality, but as a mammal it should still have some aspects of being a mammal. We’ve got some specs in a shared example group that we use for testing all of our mammal models to make sure things don’t get too out of whack in the universe.

Our Example Model

1
2
3
4
5
6
7
8
9
10
11
12
13
class Dog
 
  attr_accessor :name, :mammal
 
  def initialize
    self.mammal = true
  end
 
  def greet
    "Hi, I'm #{self.name}, woof woof!"
  end
 
end

Our Example Spec

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
describe Dog do
 
  before(:each) do
    @animal = Dog.new
    @animal.name = "Bruno"
  end
 
  it_should_behave_like "a mammal"
 
  describe "Greet" do
    it "should respond with its name and a greeting" do
      @animal.greet.should == "Hi, I'm Bruno, woof woof!"
    end
  end
 
end

Our Shared Spec

1
2
3
4
5
describe "a mammal", :shared => true do
  it "should really be a mammal" do
    @animal.mammal.should be_true
  end
end

A Typical before(:each)

Typically, when you’ve got a describe block, you might use before(:each) to setup some scenario that is used for each spec in that describe block, pretty normal RSpec stuff. We’re using it above in our example spec to create a new Dog object and set that dog’s name.

Using before(:each) in a shared spec

What if you wanted to use a before(:each) in your shared spec? Expanding on our example above we can do something like this.

1
2
3
4
5
6
7
8
describe "a mammal", :shared => true do
  before(:each) do
    @animal.stub!(:has_body_hair?).and_return(true)
  end
  it "should really be a mammal" do
    @animal.mammal.should be_true
  end
end

Based on typical RSpec behavior, one would think that the stubbing of the has_by_hair? method on the instance of an animal, would only apply to the specs inside of the describe block of the shared example group. However, by specifying in the Dog spec that a dog “should behave like” a mammal, and thus using the shared spec, that stub will apply to all subsequent “it should” blocks in your model spec.

What if, for example, we had the following in our Dog spec.

  describe "Mutate into Lizard Dog" do
   # dog.mutate will remove body hair and make the dog cold blooded
    it "should mutate into a new species" do
      @animal.mutate
      @animal.has_body_hair?.should be_false
    end
  end

If we include this in our Dog spec, below the inclusion of the shared example spec, our test will fail. We’ve already stubbed out the has_body_hair? method as part of our shared example group, when we call it down here in this completely separate describe block, RSpec is just using the stub we setup previously.

It might be a design problem if…

Now while I’m considering this a gotcha, it may be that this is expected behavior, I couldn’t find anything specifically when researching this “bug” originally. It is also possible that stubbing behavior in shared example groups is frowned upon, and I’m just “doing it wrong”.

Ultimately, I tried using patterns that made sense to me and seemed to be in line with how RSpec works in general. A stubbed method inside the before(:each) of a describe block is usually only applicable to the specs and nested describes contained within. When I realized that this is not the case with shared example groups, it seemed like a gotcha.

Using RSpec to Test system calls with %x and backticks (grave accents)

I’ve been working on a project that requires a call to the shell from inside a controller. I knew that I would need the output of the shell command, in this case a rake task, so that I could display the result to the user. However, when I went to implement the spec, I wasn’t sure how to setup the expectation.

Our Controller

1
2
3
4
5
6
7
8
InfoController < ApplicationController
 
  def index
    flash[:notice] = `cat /home/clayton/info` # sets the notice to "clayton@lengelzigich.com"
    redirect to people_url
  end
 
end

Our Spec

1
2
3
4
5
6
7
8
describe InfoController do
  describe "index" do
    it "should set the contents of the flash notice to clayton's contact info" do
      controller.should_receive(:'`').with("cat /").and_return("clayton@lengelzigich.com")
      get :index
    end
  end
end

The important part of the spec is line 43. We tell the controller to expect a call to '`' with our shell command and return the contents of the file. The '`':, backtick1, is a method in the Kernel class2. It is also possible to use @%x@ to run commands in the shell from ruby, the two are the same.

`cat /etc/motd`
# is the same as
%x[cat /etc/motd]

If you are using %x@, and need a way to write a spec, consider changing @%x to @“@ and using the above approach.

1 Some people call backticks “grave accents”, some people are dumb.

2 The @`@ method that comes from Kernel isn’t actually called on the Kernel class, it’s mixed into your Object at run time. Or so I’ve read.

3 Some credit for this discovery goes to my straight up ballin’ pair.

Ruby Gotcha Using case to Compare Classes

I was working on some code today that makes use of the activerecord-activesalesforce gem to connect to SalesForce and pull records for processing in my rails app. I needed to handle some types of records differently than others, so I decided to use a case statement to process the different SalesForce records accordingly.

I ran into a problem comparing classes, my code looked something like the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
[Array, String, Integer].each do |klass|
  case klass
  when Array
    puts "Array here!"
  else
    puts "No Array here."
  end
end
 
# Resulted In
# No Array Here.
# No Array Here.
# No Array Here.

Not exactly what I expected. Luckily, my genius rock-star-programmer pair realized that Ruby’s case must be using = rather than .

Changing the code to the following solved my problem.

1
2
3
4
5
6
7
8
9
10
11
12
13
[Array, String, Integer].each do |klass|
  case klass
  when klass == Array
    puts "Array here!"
  else
    puts "No Array here."
  end
end
 
# Results
# Array here!
# No Array here.
# No Array here.

Next up is figuring out why === behaves like this when comparing classes.

1
2
3
4
Array === Array #false
Array == Array #true
 
#why?

Learning Rails: Namespaced Controllers

A common requirement of a visitor facing web application is that the administration component of the app is behind a login with a different layout, style sheet and feel. Rails 2.0 makes this very simple with namespaced controllers. On a recent project the specs called for the administration to live under an /admin path, simple enough.

Creating the Admin Interface

1
$> script/generate controller admin/employees index show new create edit update

Perfect, now I’ve got my new controller and some views.


  /app/controllers/admin/employees_controller.rb
  /app/views/admin/employees/
    /app/views/admin/employees/index.html.erb
    /app/views/admin/employees/show.html.erb
    /app/views/admin/employees/new.html.erb
    /app/views/admin/employees/edit.html.erb

We’ll need to create a new layout and style sheet for our admin interface:

1
2
$> touch app/views/layouts/admin.html.erb
$> touch public/stylesheets/admin.css

A quick edit to our routes file and everything is in place:

1
2
3
map.namespace :admin do |admin|
  admin.resources :employees
end

In a few short steps we’ve got everything we need for our /admin area. Now we just have to build out all of the controller actions, write all of our tests, add the markup to the views… and then we have to do it all over again for the public facing controller.

The Drawbacks

At this point I realized how un-sexy this technique is. For each Model that I want to display to the public and edit in the admin I have to create two controllers, two views, two layouts, two style sheets and twice as many bugs, typos and frustrations. GAH. By the time you write all of the specs for each controller you’ve got some ridiculous code:test ratio and you never want to look at TextMate again.

The Expense of “Keepin’ it DRY

As a rails developer you should always think about “Keepin’ it DRRRYYYY” but sometimes the pursuit of DRY just isn’t worth it. As far as I can tell, keeping the admin and public controllers, views and tests separate and DRY adds way more complexity and confusion when you use namespaced controllers. I just don’t think it’s worth it

Alternatives

  1. You can create named routes to satisfy the “/admin” requirement
  2. Write an application controller method to determine which template to render (based on admin/public visitor status)

That’s it really, it doesn’t take much to keep things simple® and avoid a bunch of duplicate-in-concept code. The next time you reach for namespaced controllers to satisfy this type of functionality, think twice, it might save you a lot of trouble.