Atwam

I do stuff, and write about it

Using Rspec with inherited_resources helpers and inherited views

I have updated a rails app I have been working on recently to a more recent version of rails 3.2, and all my tests where failing. Finally managed to have that working, figured I’d show how.

Mocking inherited_resources helpers in views specs.

I know I shouldn’t be using inherited_resources anymore (see here and here) but I want to release my app before I change everything to use responders.

So, my tests where failing because I was using the resource, collection and resource_class helpers from some views I was using. So first my tests are failing because resource_class isn’t available in my views. I would have thought that the controller helpers were available in the views, but they aren’t. The solution is easy. Let’s add the following to our spec/support directory :

spec/support/view_resource_macros.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
module ViewResourceMacros
  def has_resource(name, &block)
    before do
      # Creates the resource
      @resource ||= yield
      # Assign to the symbol we wanted, so it's available in the view
      assign(name, @resource)
      # Assigns to @name so that we can use that in our assertions
      instance_variable_set("@#{name}", @resource)

      # If we pass an array, it's for stubing a collection, if not it's for stubbing a single object
      if @resource.is_a?(Array)
        view.stub(:collection) { @resource }
        view.stub(:resource_class) {@resource.first.class}
      else
        view.stub(:resource) {@resource}
        view.stub(:resource_class) {@resource.class}
      end
    end
  end
end

RSpec.configure do |config|
  config.extend ViewResourceMacros, :type => :view
end

And see how to transform our old (failing) test :

spec/views/cars/edit.html.haml_spec.rb
1
2
3
4
5
6
7
8
9
10
11
12
require 'spec_helper'

describe "cars/edit.html.haml" do
  before(:each) do
    assign(:car, @car = Factory.create(:car))
  end

  it "renders the edit view" do
    render
    rendered.should contain(@car.name)
  end
end

becomes :

spec/views/cars/edit.html.haml_spec.rb
1
2
3
4
5
6
7
8
9
10
require 'spec_helper'

describe "cars/edit.html.haml" do
  has_resource(:car) { Factory.create(:car) }

  it "renders the edit view" do
    render
    rendered.should contain(@car.name)
  end
end

Using shared inherited partial in our views specs

Rails 3.1+ offers views inheritance, so I changed my code to have the following :

1
2
3
4
5
6
7
8
9
10
11
class BaseController

end

class CarsController < BaseController
  inherit_resources
end

class PlanesController < BaseController
  inherit_resources
end

Then I just created a base/new.html.haml and a base/edit.html.haml views, to use the views inheritance.

base/new.html.haml
1
2
%h1 Create #{resource_class.model_name.human}
= render :partial => "form"
base/edit.html.haml
1
2
%h1 Edit #{resource}
= render :partial => "form"

And I have two _form.html.haml partials, one for each controller. Now the next issue is that our edit and new views are shared, but we still want to test the _form.html.haml partial.

spec/views/cars/_form.html.haml_spec.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
require 'spec_helper

describe "cars/_form.html.haml" do
  {
    new: -> { Car.new }
    edit: -> { Factory.create(:car) }
  }.each do |name, block|
    context "when called in ##{name}" do
      has_resource(name, block)

      it "renders the form" do
        render
        rendered.should have_selector("form")
      end
    end
  end
end

Shared partial

Finally, when testing for example cars/index.html.haml which uses a partial toolbar.html.haml that actually exists in base views, the following lines are necessary :

1
2
3
before do
  views.lookup_context.prefixes << "base"
end

This was raised as an issue to the rails team, but they commented (rightly I think) that the inheritance is related to the controller, not the views, so the test case shouldn’t know about it and you’ll have to declare it manually using the lines above.

Now let’s go back and make these tests green again.

From pow to a deployed rails app using chef, capistrano and vagrant - Part 1

So, let’s be honest, I’ve been quite lazy here. My latest rails application was deployed with Heroku. Lots of fun, a very pleasant experience. But now I have this new shinny application that I don’t want to deploy using Heroku :

  • Because I am worried that if I start with Heroku, I’ll be too lazy to switch later.
  • Because I know that at some point, my application is going to need plugins and binaries that I can’t get on Heroku.
  • Because I’d rather have a portable application that I can deploy easily on any type of server.

Building dep_selector on mac os x

Just a quick post, having finally figured out how to install dep_selector on mac os x. The issue is that having xcode installed which configures clang as the default compiler, some native gems break.

It took me some time, but at long least I can now build a native gem using gcc instead of clang on mac os x. And you’ll see it’s not very easy to have ruby change its compiler for gems native extensions compilation.

Multiple persistent stores and seed data with core data

I haven’t posted anything for a while now, and after hours of trying to find a solution to my problem, I thought I should share. So here we go.

The problem

Your nice and shiny iOS app is supposed to have two data components : User data and Seed data. For example, you want to have some (seeded) list of postcodes. The size of data is too big to be shipped with your app, and we assume that the model is too complex to be just filled by your application at runtime from a downloaded csv/txt file.

So, you start thinking that hey, you’ll generate a sqlite database (persistent data store as they say), put it on a server and have your app download and use it. You can either duplicate the whole stack (NSManagedObjectContext, NSPersistentStoreCoordinator and NSManagedObjectModel) or, according to apple :

You typically use configurations if you want to store different entities in different stores. A persistent store coordinator can only have one managed object model, so by default each store associated with a given coordinator must contain the same entities. To work around this restriction, you can create a model that contains the union of all the entities you want to use. You then create configurations in the model for each of the subsets of entities that you want to use. You can then use this model when you create a coordinator. When you add stores, you specify the different store attributes by configuration. When you are creating your configurations, though, remember that you cannot create cross-store relationships.

Well, that’s pretty much all the doc you’ll get from apple. There are a few mentions of this problem there or there but not in a clear enough form for me. So, here’s how it works…

Spell checking should be part of your view tests

So it all started when I asked a friend to test this new app I’m building : “On your main page, garantee. You should really check your spelling, people will know you are French !”.

So here I went, naively googling for “website spell checker”, with either pricey reports or simple websites where I’d have to copy-paste my text from all my pages. Then, I found AfterTheDeadline. It looks great, open-source, recently bought by wordpress.com, and they even provide an API.

So, spent my evening doing stuff, and here we are with a new gem : Merimee (github).