Blog

Saturday, December 24, 2011

Your Rails Application is Missing a Domain Controller

The mantra of Skinny Controller, Fat Model reminds us to keep our business logic in our models, not in Rails Action Controllers. We know Action Controllers, sub-classes of ActionController::Base, are only responsible for delegating service requests to the domain layer. These models, which encapsulate this business logic, forming the domain layer, represent entities such as a person, place, event or thing. They are often, but not always, mapped directly to database tables through the inheritance of ActiveRecord::Base. When we develop our domain layer for our complex Rails application, purely with models representing entities, we encounter two problems:

Incoherent domain API

When Action Controllers interact with model entities directly, the API to the domain layer becomes clouded. It is unclear what services the domain layer offers and how the UI should request those services. Rail’s ActiveRecord exasperates the issue, for example, there are several ways to create and update model entities and their associations.

Bloated domain models

Business logic that is workflow-oriented involving multiple entities is assigned to a single entity, bloating it’s responsibilities. It becomes difficult to differentiate the entities in the domainrepresenting what the system is, from the use cases or workflow representing what the system does1.

The solution is a Domain Controller. A Domain Controller is responsible for co-ordinating service requests from your Rails Action Controllers. A Domain Controller can come in two flavours, a facade or a use case.

A clarification on terminology: Throughout this blog post I will refer to the typical Rails model as a Model Entity, meaning a model that represents a person, place, event or thing.

Facade Controller

A Facade Controller represents the overall system that encapsulates the domain layer. For example a Catalog object can act as facade for the domain layer containing taxonomies, taxons, product groups, products and variants.

Without the Facade Controller, our service requests to the domain typically look like this:

Product.active
Taxon.active.find(1)
Product.create(:name => 'Ruby Meta-Programming')

With a Facade Controller instance, in this case, a catalog object, service requests appear as the following, delegating to the appropriate Model Entities:

catalog.fetch_products
catalog.fetch_taxon(1)
catalog.create_product(:name => 'Ruby Meta-Programming')

The Facade Controller provides a clear, explicit interface into the catalog domain layer that a programmer can grok within seconds.

Use Case Controller

A Use Case Controller is useful for more complex workflows. They are also helpful when a Facade becomes bloated and you wish to split the incoming service requests across multiple Domain Controllers. It’s important to note, you can use more than one Domain Controller for your application.

Let’s look at an example. The code below represents the processing of a Payroll2. Often this type of workflow logic gets placed in a Model Entity that it doesn’t belong to or worst, left in a Rails Action Controller.

date = Date.today
employees = Employee.active
employees.each do |e|
  if e.pay_date?(date)
    pc = PayCheck.new(e.calculate_pay(date))
    e.send_pay(pc)
  end
end

So what object is responsible for this workflow logic? We know a Rails Action Controller isn’t a candidate. Its responsibility is to handle HTTP requests and delegate to the domain layer. Neither the models Employee or PayCheck are valid candidates. They represents the entities in our domain layer. Therefore we, require a new object PayDayService to encapsulate the logic, a Use Case Controller.

class PayDayService
    def initialize(date=Date.now)
      @date = date
    end

    def call
      Employee.active.each do |e|
        if e.pay_date?(@date)
          pc = PayCheck.new(e.calculate_pay(@date))
          e.send_pay(pc)
        end
      end
    end
  end

The benefit of this approach is that we have encapsulated this workflow logic without bloating existing Model Entities and allows the reuse of this logic in different contexts.

Domain Controllers in a Rails Application

When an application has multiple Domain Controllers I place them in a dedicated directory under app called services to keep them separate from the Model entities in app/models. This helps communicate that Rails Action Controllers should delegate to the Domain Controllers, not directly to Model Entities. The Domain Controllers and Model Entities together, represent the domain layer of the system. I have also discussed extracting the entire domain layer from the Rails framework, but that’s another discussion. Let’s keep this blog post civil for now!

I hope the Domain Controller pattern provides you with another tool for modelling your domain, reduces the coupling with the UI, and provides a clean API to your application logic.

Further Reading

If you are interested in learning more about Domain Controllers and Services, check out the following resources:

  • Applying UML and Patterns by Craig Larman. Craig includes the Controller pattern as one of the General Responsibility Assignment Software Patterns or Principles (Grasp).
  • Architecture the Lost Years a presentation by Robert Martin discusses modelling your application using Interactors and Entities. Interactors_ (which I have used the name Domain Controller) contain application specific logic, and Entities (which I have use the term Model Entities) contains application independent logic. Martin choses to use the term Interactors over Controllers to avoid confusing with Model-View-Controller (MVC). I prefer to use Domain Controller or Service to differentiate from Rails Action Controllers as I just can’t get my head around the term Interactors.
  • Object-Oriented Software Engineering—A Use Case Driven Approach by Ivar Jacobson introduced the concept of interface, entity (Model Entity) and control (Domain Controller) objects over two decades ago. Robert Martin often refers to Ivar Jacobson when discussing application architecture.
  • Patterns of Enterprise Application Architecture by Martin Flower discusses the concept of a “Service Layer” to give the domain layer an explicit API.
  • Domain Driven Design by Eric Evans. Evans discusses the concept of Services for when “some concepts from the domain aren’t natural to model as objects”.

Footnotes:

  1. “What-the-system-is” and “What-the-system-does” terminology is from the book Lean Architecture by James O. Coplien and Gertrud Bjørnvig.
  2. Logic based on the Payroll case study in Robert Martin’s Agile Software Development.

Wednesday, December 21, 2011

An Example using RSpec double, mock, and stub

This is a follow-up post for RSpec double, mock, and stub from earlier this year. A reader asked for an example code to illustrate the various double aliases in RSpec.

For this example we will spec a Transfer class that encapsulates the use case of transferring an amount between two accounts, the source account and destination account. The Transfer is the subject of our examples, while the source and destination accounts are the collaborators.

In the spec below, the first example "should decrease source amount by 10", specifies the interaction for the source account, hence the use of the mock to generate the test double. In this example, the destination account is treated as a secondary collaborator, as we are focusing on the role of the source account. Any object can play the role of the source account, as long as it responds to the #decrease method.

In the second example "should increase destination account by 10", the destination account is the primary collaborator. The use of mock to generate the source account communicates this intent.

describe Transfer do
  context "transfer with amount of 10" do
    it "should decrease source account by 10" do
      source_account      = mock('source account')
      destination_account = stub('destination_account').as_null_object
    
      source_account.should_receive('decrease').with(10)
    
      transfer = Transfer.new(source_account, destination_account, 10)
      transfer.call
    end

    it "should increase destination account by 10" do
      source_account      = stub('source account').as_null_object
      destination_account = mock('destination_account')
    
      destination_account.should_receive('increase').with(10)
    
      transfer = Transfer.new(source_account, destination_account, 10)
      transfer.call
    end
  end
end

However, there is some duplication in this spec which can be eliminated by moving the test doubles to let blocks. It's appropriate to use double here to generate the source and destination accounts as both play primary and secondary collaborators in the following examples. Below we stub the methods for each collaborator, then set expectations on those methods for the appropriate examples.

describe Transfer do
  context "transfer with amount of 10" do
    let(:source_account) { double('source account', :decrease => nil) }
    let(:destination_account) { double('destination_account', :increase => nil) }

    it "should decrease source account by 10" do
      source_account.should_receive('decrease').with(10)
    
      transfer = Transfer.new(source_account, destination_account, 10)
      transfer.call
    end

    it "should increase destination account by 10" do
      destination_account.should_receive('increase').with(10)
    
      transfer = Transfer.new(source_account, destination_account, 10)
      transfer.call
    end
  end
end

Update: Radoslav Stankov provides a cleaner refactoring of the spec.

The implementation of the transfer class may look something like this:

class Transfer
  def initialize(source_account, destination_account, amount)
    @source_account      = source_account
    @destination_account = destination_account
    @amount              = amount
  end
  
  def call
    # In a complete implementation, it would make sense to have the following 
    # lines wrapped in a transaction, but I wanted to keep this example simple
    #
    @source_account.decrease(amount)
    @destination_account.increase(amount)
  end
end

It's important to remember that double, mock, and stub all return an instance of RSpec::Mocks::Mock. While the concepts of mocking, (i.e. setting a method expectation), and stubbing are "method-level concepts"[1], the use of mock and stub can communicate which collaborator you are specifying the behaviour for.

[1] For a more complete discussion on this, checkout The RSpec Book.

Recent Launch: Yellow Bird Project Redesign

Earlier this year, I upgraded the Yellow Bird Project, a Spree store, from a forked version pre v0.90.0 to v0.50.x. For for my final project of the year, I upgraded Yellow Bird Project to v0.70.x, along with the implementation of a UI redesign. Jenna Holcombe (Dynamo) did a great job moving the YBP look to a grid-based design, which Daniel Wright (Dynamo) implemented this in Sass/Compass.
Since the redesign initiative included an upgrade to the latest version of Spree, I decided to upgrade the existing site and deploy that to production, before launching the redesign. This allowed me to upgrade our custom extensions to work with 0.70.x and iron out any kinks in the new version. While this was a smoother process than the upgrade earlier this year, it was the first time I had deployed to Heroku's Cedar stack using Rails 3.1 and the asset pipeline. I'm a big advocate of breaking down a project, separating major changes, and getting changes pushed to production early, even it there is a little duplication in work. The separate pushes to production for the upgrade and the redesign reduced the risk of something really going haywire with pushing both of these at once.
The redesign benefited the application from a platform, merchandising, and coding perspectives:
  • Platform: While this initiative did not include a mobile version, the new grid-based design will allow us to cleanly develop a responsive design for mobile platforms in the future using media queries. Replacing hacks like Cufon with more modern technologies like web fonts just makes the UI code cleaner and performance snappier.
  • Merchandising: The store now fully utilizes Spree's powerful Taxonomy and Product Group features. This allows YBP to respond to different marketing initiates such as seasonal events, for example Warm Winter Wear.
  • Code: One of the cool things with this upgrade was the chance to refactor the code base. Shifting from ERB to Haml and plain CSS to Sass/Compass was a definitely a plus, however implementing a data model that capitalized Spree's catalog management was the biggest win. I was able to remove unnecessary extensions which simplified managing the products. YBP's Matthew Stotland is a code-savvy lad and appreciated the clean implementation. It's great to work on a project where the client appreciates the front-end as much as the code that drives it.
You can checkout the new design below, but better yet, visit the Yellow Bird Project and support a great cause.
01 home
Yellowbird Project Product

Thursday, November 17, 2011

Software Craftsmanship Goes Beyond Code

Often the discussion of Software Craftsmanship is focused on code and tests. But don't forget about the other components that support your project:

  • Make sure your source control repository is organized. Don't leave dead branches lying around, left for another developer to work out if they have been merged or not; if they should be merged or not. Add a reference to your branch with the issue or story id from your tracker so a developer can read more about the intention of the branch.
  • And don't write commit messages that suck.
  • Keep your tracker up-to-date and lean. Don't mark stories as started when they haven't been. In reality, there should only be one story marked as started per developer on the project. Don't drag stories into the backlog just because you think they are a good idea. Keep the backlog lean, you only need a couple of weeks worth of stories to keep you going. Keep the rest in the icebox. Priorities are going to change.
  • Make sure it's easy for a developer to get started with your project. Have a README that guides a developer to get the dependencies and database setup, and remind them a test suite exists and how to run it. Obviously the more automated things are the better.

Caring needs to go beyond the code, it needs to include all the supporting components of your project. Of course there are other facets of professionalism we can list, but these are some practical details I have experienced recently. What components of a project, beyond code, that you wish developers would give more care to? Let me know in the comments.

Saturday, November 12, 2011

Recent Launch: Mr. B's Gentlemen's Boutique for ALDO

Back in September, I had the pleasure working with Alex Nemroff (Interactive Designer) and Daniel Wright (Front-end Developer) at Dynamo on Mr. B's Gentlemen's Boutique, a new product line for ALDO Shoes. A tribute to Aldo Bensadoun, this project is dear to everybody's hearts at ALDO and I think we have made them proud. I was responsible for the setup and customizations to Refinery CMS, including the development of an extension to manage the catalog.

I always have a great timing working on projects Alex leads. He always gets us involved in all aspects of the project and the end result really does feel like a team effort. My favourite times throughout the project is sitting down together at the end of an iteration, reviewing what we have done, and what we can do to improve it in the next iteration. And it doesn't hurt to have a power house like Daniel on the front-end. He really knows his stuff.

Below is a video of the post-mortem at Dynamo, where Alex and myself talk about lessons learned throughout project. Unfortunately, we didn't capture the screen when recording this session (whoops, working on that), but I think you will find the discussion insightful. Please checkout the screenshots below, better yet, visit the site and checkout some beautiful shoes.

Post-Mortem at Dynamo

 

Screenshots

Home Page

Product Detail

 

Saturday, October 22, 2011

Rails is Not Your Application

Background: The Beginnings of My Obsession with Application Architecture and Domain Modelling

Last year I was involved in my most complex Ruby on Rails application to date that is now 23K lines of model code, 14K lines of controller code, and 4.5K lines of lib code. You get the point, let's now worry about the view code. It was during this project that I observed the pain of working within the bounds of how we typically build Rails applications. Did I mention it was slow to develop and test? During that contract and ever since, I have been obsessing about application architecture and domain modelling.

Establish an Application Interface with a Service Layer

During the time I was working on said application, I introduced the concept of Services (in the early stages I called them managers). Although a lot of domain logic was pushed into the models, there was too much application logic in the controllers. Services, co-ordinating domain models, allowed me to extract that application logic to really keep the controllers thin. I'm not sure exactly sure what prompted me to start using Service objects, but after the fact I found references to them in Martin Fowler's Patterns of Enterprise Application Architecture (P of EAA). Other frameworks such as Grails also use Services, it even has a generator for them. Services resolves the discussion (started here) on where to trigger email notifications. Add them to your Services.

In P of EAA, Randy Stafford defines the Service Layer as:

"Defines an application's boundary with a layer of services that establishes a set of available operations and coordinates the application's response in each operation."

And in a way, this definition helped me recognize another frustration I was having with how I (and most of the Rails community) was developing with Rails. There was no explicit application. Or rather, it was hard to define what the application was and hard to know how to interact with it. The application had no interface. My application was a ball of ActiveRecord objects.

Lots of Activity in the Rails Community Regarding Domain Modelling

I haven't been the only one thinking about application architecture and domain modelling. I'm not a unique snowflake. Others in our community have too: Mike Dietz from ThoughtWorks introduce me to DCI at RailsConf 2011Andrzej Krzywda has been blogging about it before that, and Jim Gay has recently been blogging about it on this side of the pond. On another tact, Corey Haines has been been selling fast tests over the last few months. Hidden in that sales pitch of course, is a way to extract domain logic. Talking of extracting domain logic, Steve Klabnick has illustrated some practical examples.

These guys have kept me busy! I've been quietly researching this topic for over a year now. You can check out some of my tags on Delicious:

Extracting the Application from the Framework

Ok, time to finish up this post. All of the efforts describe above have been with the purpose of managing the application and domain logic in the software we build. It benefits us with faster tests and code that clearly communicates it's intent. And although the Service Layer was helping me define an interface to my application, I was only using them when my controllers methods/actions were getting heavy with application logic. Then last night, I watched the latest release of Clean Code from Uncle Bob that highlights the need to extract your application from the framework you use (he's been teasing me for a while on this topic). With my previous experience with Services, and my interest in DCI, Uncle Bob's guidance was the piece I was missing.

After taking his example pseudo code, and turning it into some Ruby/Rails example (more like snippet) I gleefully tweeted:

"Rails is not your application. It might be your views and data source, but it's not your application. Put your app in a Gem or under lib/."

I really like this approach a lot, the ability to test your application outside of the Rails stack is huge, and viewing Rails as a method to deliver my application will change the way I write code. Anyway here is the code that triggered the Tweet (see below). It's not polished, it doesn't execute, it's not 100% right, but boy it's got me thinking. It uses Services to represent Use Cases of the application, and roles containing domain logic that is mixed in contextually, extracted into a Gem, delivered via Rails. If you not a fan of the Gem idea, keep it name spaced under your lib directory.

Update: A clarification on putting your application in lib. I certainly don't mean to put it directly in lib. Name space it, lib/your_application; e.g. lib/pay_roll.

Now that I have let the code out of the bag, expect some more posts on this topic in the future where I work through and describe this code (and related ideas) in more detail.



Written by .

Monday, October 17, 2011

References and tools for Memory Consumption in Rails

It's not often that I need these, but when there's a Memory Consumption issue in a Rails application, these references and tools definitely come in handy:

Rails 3 References and Tools

Some Older References and Tools

Saturday, October 15, 2011

Recent Launch: Media Experts on Refinery CMS

Media Experts is a top Canadian media planning and buying agency. During the summer, I was tasked with the first iteration of their website, integrating it with Refinery CMS (thanks Dynamo!). One of the joys of using Refinery, is the ease of extending it with engines to support custom content types. For example the experts page seen below contained structured, repetitive data that was not suited for a page tree hierarchy:

Media Experts - People

By generating a custom engine, I was able to easily integrate this structured data into the website, without any impact on the original design or the website's navigation. You can view how the individual experts are edited in the screen shot below:

RefineryCMS

Please checkout the Media Experts' website and view additional screenshots below:

Home Page

Media Experts Home

Portfolio Index

Media Experts Portfolio

Sunday, October 9, 2011

Yellow Bird Project Spree Upgrade

During the spring, Dynamo asked me to upgrade the Yellow Bird Project to the latest version of Spree (at the time this was v0.50.2). The challenge for this project was managing the upgrade from a forked version of Spree, pre v0.9.0 back in 2009. One tool that was really useful was using Max OS X's FileMerge to compare database schemas, allowing me to determine what the new schema would and determine any naming conflicts with custom tables added previously.

Filemerge schema

The upgrade resulted in an application that can now be easily upgraded to future version of Spree and runs on a more stable, scalable platform thanks to Heroku.

The Yellow Bird Project is pretty cool - they work with a range of indie rock musicians to create some neat t-shirts that then benefit a charity chosen by the musicians themselves. So put away that ugly university hoodie and go get yourself some cool threads.

Yellow bird project home

Saturday, October 1, 2011

Recent Launch: de Gaspé Beaubien Foundation

OK, hardly a recent launch, de Gaspé Beaubien Foundation was actually launched in April, but I'm a wee bit behind in posting some of the neat projects I have worked on this year. I'm determine to get this resolved over the next couple of weeks.

de Gaspé Beaubien Foundation's website provides a platform to communicate the families contribution to their communities and the broader society. I worked with the great team at Dynamo on this one: Bob Beck, creative director was responsible for brand identity and video direction, Jenna Holcombe site design, and I was responsible for front-end development and CMS integration.

This is the first project I have used RefineryCMS, a Ruby on Rails-based Content Management System. While I have been a big fan of Radiant CMS, I like RefineryCMS for it's polish integrated interface. It worked great for this project, but I would use Radiant when a project has more complex requirements. The front-end was developed using HTML5 and CSS3. CSS was generated using Compass and Sass. Compass' CSS3 helpers are a real help abstracting away the mess of vendor extensions, and the CSS3 PIE integration giving older version of IE CSS3 capabilities is invaluable. All video is presented using HTML5, with a Flash fallback, all handled seamlessly by JW Player.

Check out the screenshots below and please visit the site to find out the great work de Gaspé Beaubien Foundation is doing.

de Gaspé Beaubien Foundation

de Gaspé Beaubien Foundation

de Gaspé Beaubien Foundation

de Gaspé Beaubien Foundation

Saturday, August 6, 2011

My Ruby on Rails Development Environment

My Development Environment

Click image to enlarge

Saturday, July 30, 2011

Gotcha with testing expected params with Bourne/Mocha in Rails Controller

This is something that always trips me up using Bourne (a fork of Mocha, a Ruby mocking and stubbing library) to test expected params in a Rails Controller. Take this spec:

context "with filter" do
  before do
    get :index, :search => {:brand_id => '1'}
  end

  it 'should find latest search results' do
    SearchResult.should have_received(:latest).with('brand_id' => '1')
  end
end

This test fails, but what if I tried this:

context "with filter" do
  before do
    get :index, :search => {:brand_id => '1'}
  end

  it 'should find latest search results' do
    SearchResult.should have_received(:latest).with(:brand_id => '1')
  end
end

This will fail. Note I am now checking the parameters passed using symbols for the keys. I receive the following error:


Failure/Error: SearchResult.should have_received(:latest).with(has_entry(:brand_id => '1'))
     expected exactly once, not yet invoked: SearchResult(id: integer, search_id: integer, body: text, source: text, url: string, created_at: datetime, updated_at: datetime).latest(has_entry(:brand_id => '1'))

This is because the params that are passed to the controller have keys as strings rather than symbols:

{'brand_id' => '1'}

So what's the solution? I could actually use HashWithIndifferentAccess which gives access to a Hash using strings or symbols for keys. This is in fact the class that is used for the params hash in the controller:

it 'should find latest search results' do
    SearchResult.should have_received(:latest).with(HashWithIndifferentAccess.new(:brand_id => '1'))
  end

Or, as a standard practice, when dealing with parameters passed to a controller within a spec, always use strings:

context "with filter" do
  before do
    get :index, 'search' => {'brand_id' => '1'}
  end

  it 'should find latest search results' do
    SearchResult.should have_received(:latest).with('brand_id' => '1')
  end
end

I think this is a lot simpler, cleaner. Interestingly, I didn't pass the brand_id as a Fixnum:

before do
    get :index, 'search' => {'brand_id' => 1}
  end

I would have got the same error:

Failure/Error: SearchResult.should have_received(:latest).with('brand_id' => 1)
     expected exactly once, not yet invoked: SearchResult(id: integer, search_id: integer, body: text, source: text, url: string, created_at: datetime, updated_at: datetime).latest('brand_id' => 1)

As the brand_id is present in the hash as a String, not a Fixnum.

Upgrade RVM and Ruby 1.9.2p290

I've been a little lazy and haven't updated my RVM installation (version 1.1.3, now 1.6.31) for a while and have been stuck on Ruby 1.9.2p0. This morning I upgraded, here's what I did:

$ rvm get head
$ rvm reload
$ rvm install 1.9.2-p290
$ rvm upgrade 1.9.2-p0 1.9.2-p290

Hmm… Got some errors, here's the output:

Are you sure you wish to upgrade from ruby-1.9.2-p0 to     ruby-1.9.2-p290? (Y/n): y
Migrating gems from ruby-1.9.2-p0 to ruby-1.9.2-p290
Are you sure you wish to MOVE gems from ruby-1.9.2-p0 to ruby-1.9.2-p290?
This will overwrite existing gems in ruby-1.9.2-p290 and remove them from ruby-1.9.2-p0 (Y/n): y
Moving gemsets...
Moving ruby-1.9.2-p0 to ruby-1.9.2-p290
Making gemset ruby-1.9.2-p290 pristine.
ERROR: Error running 'rvm gemset pristine' under ,
please read /Volumes/Data/Users/nicholas/.rvm/log//gemset.pristine.log
Moving ruby-1.9.2-p0@brandizzle to ruby-1.9.2-p290@brandizzle
Making gemset ruby-1.9.2-p290@brandizzle pristine.
ERROR: Error running 'rvm gemset pristine' under ,
please read /Volumes/Data/Users/nicholas/.rvm/log//gemset.pristine.log
Moving ruby-1.9.2-p0@default to ruby-1.9.2-p290@default
Making gemset ruby-1.9.2-p290@default pristine.
ERROR: Error running 'rvm gemset pristine' under ,
please read /Volumes/Data/Users/nicholas/.rvm/log//gemset.pristine.log
Moving ruby-1.9.2-p0@global to ruby-1.9.2-p290@global
Making gemset ruby-1.9.2-p290@global pristine.
ERROR: Error running 'rvm gemset pristine' under ,
please read /Volumes/Data/Users/nicholas/.rvm/log//gemset.pristine.log
Moving ruby-1.9.2-p0@peters-guide to ruby-1.9.2-p290@peters-guide
Making gemset ruby-1.9.2-p290@peters-guide pristine.
ERROR: Error running 'rvm gemset pristine' under ,
please read /Volumes/Data/Users/nicholas/.rvm/log//gemset.pristine.log
Moving ruby-1.9.2-p0@refinery to ruby-1.9.2-p290@refinery
Making gemset ruby-1.9.2-p290@refinery pristine.
ERROR: Error running 'rvm gemset pristine' under ,
please read /Volumes/Data/Users/nicholas/.rvm/log//gemset.pristine.log
Moving ruby-1.9.2-p0@shoedazzle to ruby-1.9.2-p290@shoedazzle
Making gemset ruby-1.9.2-p290@shoedazzle pristine.
ERROR: Error running 'rvm gemset pristine' under ,
please read /Volumes/Data/Users/nicholas/.rvm/log//gemset.pristine.log
Moving ruby-1.9.2-p0@spree to ruby-1.9.2-p290@spree
Making gemset ruby-1.9.2-p290@spree pristine.
ERROR: Error running 'rvm gemset pristine' under ,
please read /Volumes/Data/Users/nicholas/.rvm/log//gemset.pristine.log
Moving ruby-1.9.2-p0@sproutcore to ruby-1.9.2-p290@sproutcore
Making gemset ruby-1.9.2-p290@sproutcore pristine.
ERROR: Error running 'rvm gemset pristine' under ,
please read /Volumes/Data/Users/nicholas/.rvm/log//gemset.pristine.log
Moving ruby-1.9.2-p0@storeworks to ruby-1.9.2-p290@storeworks
Making gemset ruby-1.9.2-p290@storeworks pristine.
ERROR: Error running 'rvm gemset pristine' under ,
please read /Volumes/Data/Users/nicholas/.rvm/log//gemset.pristine.log
Do you wish to move over aliases? (Y/n): y
Updating alias default to point to ruby-1.9.2-p290@default
Do you wish to move over wrappers? (Y/n): Y
Do you also wish to completely remove ruby-1.9.2-p0 (inc. archive)? (Y/n): Y
ERROR: Error running 'rvm remove ruby-1.9.2-p0 --archive --gems' under ,
please read /Volumes/Data/Users/nicholas/.rvm/log//rvm.remove.log
Successfully migrated ruby-1.9.2-p0 to ruby-1.9.2-p290
Upgrade complete!

Note that I opted to move over aliases, wrappers and completely remove my old ruby-1.9.2-p0.

Looking at the gemset.pristine.log I had the following errors for each gemset:

[2011-07-30 09:08:04] rvm gemset pristine # under ruby-1.9.2-p290@brandizzle
/Volumes/Data/Users/nicholas/.rvm/scripts/functions/environment: line 235: rvm: command not found

So for each gemset I executed the following:

rvm gemset pristine 

This seemed to work fine. Next, I checked out the errors in rvm.remove.log:

[2011-07-30 09:08:32] rvm remove ruby-1.9.2-p0 --archive --gems # under ruby-1.9.2-p0
/Volumes/Data/Users/nicholas/.rvm/scripts/functions/environment: line 235: rvm: command not found

Looks like the remove of my old 1.9.2 install failed, so I ran it manually:

rvm remove ruby-1.9.2-p0 --archive --gems 

Boom! Everything is updated and working.

Thursday, July 28, 2011

Basic Heroku addons I always use for production websites


heroku addons

cron:daily
custom_domains:basic
logging:expanded
memcache:5mb
newrelic:standard
pgbackups:auto-month
sendgrid:basic
shared-database:5mb

Tuesday, July 26, 2011

Git: Push a local branch to a remote master

git push heroku yourbranch:master 
Credit Heroku

Run a SQL query within Ruby on Rails

ActiveRecord::Base.connection.execute(your_sql_statement)

Ruby Script to Duplicate a S3 Bucket


Thanks Josh Nussbaum.

Tuesday, June 21, 2011

Access the last argument for a UNIX command to use in your next command

You can access the argument using the !$ variable. For example:

Monday, May 16, 2011

"Building Web Apps with HTML5: Beyond the Buzzword" Follow-up

Just completed the Building Web Apps with HTML5: Beyond the Buzzword at RailsConf. The tutorial was well organized, had a quick pace and finished early, which is a good sign in my book. I'm not a fan of having a mad rush at the end to get everything finished. The tutorial itself was mostly self-directed with some discussion throughout so I'm not sure how much value was added by the instructor or doing it as a group.

Overall, well worth the time to get your feet wet with these emerging technologies. You can complete the tutorial yourself at: https://github.com/subelsky/html5tutorial. Thanks Mike Subelsky for your efforts.

One useful resource referenced throughout the tutorial is the website Dive into HTML5. Check it out.

Friday, May 6, 2011

What Git revision is deployed to Heroku?

Updated: Does not work on Heroku's Cedar stack.

If you want to know which revision has been deployed to Heroku execute the following command in your project:

heroku console "ENV['COMMIT_HASH']"

Credit: http://stackoverflow.com/questions/2281772/view-remote-git-revision-on-heroku/4609925#4609925

Tuesday, May 3, 2011

Compare Git Branches, Compare Two Files in Different Branches

Git offers a couple of great commands for comparing branches. To get a comparison of branches in a "status" type format:

git diff --name-status branch1..branch2

Will give you output something like:

M       config/boot.rb
M       config/database.yml
M       config/deploy.rb
M       config/environment.rb
M       config/environments/development.rb
M       config/environments/production.rb
M       config/environments/staging.rb

Now that you have a list of files, you may wish to get a diff of a specific file:

git difftool branch1:config/environment.rb branch2:config/environment.rb

On OSX, this will open the awesome FileMerge.app allowing you to compare both files.

File merge

Saturday, April 16, 2011

Installing RubyGems with no Rdoc/RI

Finally took the step today of not generating RDoc and Ri when installing Ruby Gems by default by adding the following to ~/.gemrc.

install: --no-rdoc --no-ri
update: --no-rdoc --no-ri

Saturday, April 9, 2011

Code examples from Associative Arrays with James Edward Gray II

I watched David Brady's pod call with James Edward Gray II discussing Associative Arrays. There are definitely some gems (no pun intended) in this video. While watching the video I transcribed the code examples below.

Associative Arrays with James Edward Gray II from David Brady on Vimeo.

Monday, April 4, 2011

Looking for a Montréal-based Ruby on Rails developer?

Admittedly, I have been booked for a while now and haven't had any time to take on any projects. So where does one go if they are looking for Ruby on Rails developers located in Montréal? I would recommend checking out Working with Rails.

You might like to do a keyword search for Montréal or browse for developers located in Canada. I hope this helps your search for developers.

Saturday, April 2, 2011

A script for a Ruby on Rails Blog in 15 minutes

Early in the new year I made the switch to Vim from Textmate. I needed a lot of practice so I replicated the Rails screen-cast for a blog in 15 minutes produced by Ryan Bates over and over again. It was a great way to get familiar with Vim after years of Textmate editing. I wrote up a script based on that screen-cast to aid my practice, and I have also found it useful in quickly demoing Rails to a newbie. The script itself won’t make sense without viewing the screen-cast, but a good reminder of the steps if you find yourself in the same situation.

  • Create a new rails application
  • Start and verify server is running
  • Generate Post (title, body) scaffold
  • Demonstrate adding, updating Posts
  • Add validation rule to Post
  • Demonstrate adding an invalid post
  • Refactor posts/show view into partial
  • Refactor posts/index to use partial
  • Demonstrate in browser
  • Demonstrate XML (curl http://localhost:3000/posts.xml)
  • Add JSON format for Posts
  • Demonstrate JSON (curl http://localhost:3000/posts.json)
  • Add atom format (posts/index.atom.builder)
  • Add auto_discover_link_tag to layout
  • Add basic authentication to PostsController
  • Demonstrate in browser
  • Add Comment scaffold (body)
  • Don’t forget to update routes
  • Demonstrate routes (rake route)
  • Add list of comments to posts/show
  • Create comments partial
  • Add comments form to posts/show
  • Clear out CommentsController
  • Add create action (but use #build instead of #create!)
  • Create does not save, show off debugger
  • Demonstrating save comment in debugger
  • Change build method to #create!
  • Update comments form to use AJAX
  • Update comments controller to use AJAX
  • Demonstrate fall back without Javascript enabled
  • Create automated test for posting comments
  • Review with broken test
  • Review console by updating a post title, add comment

Here are the various 15 minute blog screen-casts for the different versions of Rails:

Friday, April 1, 2011

Rails server hangs on startup with Dalli Gem and Memcached

If your using Dalli and Memcached, ensure you are running the latest version of Memcached (at least 1.4 or greater) otherwise when starting Rails, the server will hang. You can upgrade Memcached easily enough with MacPorts (if that's what you're using):

sudo port upgrade memcached

If you haven't installed memached using MacPorts before and just have the version shipped on OSX, then do an install:

sudo port install memcached

Reference: http://www.mikeperham.com/2010/08/30/dalli-memcached-for-ruby/

Saturday, March 5, 2011

Trigger Cucumber Features from Vim

I use rstakeout to automatically run my Cucumber features when a feature changes (yes I probably should be using watchr). I use the following command:

rstakeout "rake cucumber:wip" "features/**/*"

But sometimes I want to run the features manually. However, I don't want to leave my editor to do this. A mapping in Vim to trigger the run saves the day:

map <Leader>c :call system("touch features/support/env.rb")<CR>

Sunday, February 6, 2011

4 Things I Assert in Rails Controller Tests

  1. ActiveRecord Calls (using mocking)
  2. Assigns
  3. Flash
  4. Responses

And if the response content type is not going to be HTML I will test that as well.

Saturday, February 5, 2011

Cucumber Rails: undefined local variable or method `node'

I've been stung by this a couple of times so it's time to add it to my blog. This exception is raised when Cucumber follows a link using the click_link Capybara method. An example of the error:

When I follow "Add brand"                      # features/step_definitions/web_steps.rb:33
      undefined local variable or method `node' for # (NameError)
      ./features/step_definitions/web_steps.rb:35:in `block (2 levels) in '
      ./features/step_definitions/web_steps.rb:14:in `with_scope'
      ./features/step_definitions/web_steps.rb:34:in `/^(?:|I )follow "([^"]*)"(?: within "([^"]*)")?$/'
      features/manage_brand.feature:14:in `When I follow "Add brand"'

This has been report in the following places:

The solution is to either remove the following line from env.rb:

require 'cucumber/capybara-javascript-emulation'

or better yet, simply bundle the Gem from the 'master' branch. Add this to your Gemfile:

group :development, :test do
  gem 'cucumber-rails', :git => 'git://github.com/aslakhellesoy/cucumber-rails.git'
  # other gems...
end

Important Note: You must regenerate your env.rb using rails g cucumber:install otherwise you will receive the following error:

no such file to load -- cucumber/rails/active_record (LoadError)

Saturday, January 29, 2011

TextExpander stopped working

I can't live without TextExpander. But apparentely Firefox and Chrome are not playing nicely with it. TextExpander suddenly stopped working for. I don't use these browsers very often, most for browser testing. Anyway, here is an explanation from TextExpander support:

Most likely, you're being affected by the bug in Firefox and Chrome where they enable secure input but don't disable it. This bug is particularly infuriating because it doesn't seem clear to the end user what causes it. However, it does have a cause, a workaround, and it does seem to be getting some traction from the Mozilla folks. Switching product probably won't help, as the other text expansion applications observe input in the same way as TextExpander and thus are subject to deprivation by secure event input being left enabled. When these browsers display a password field, they turn on secure event input so that no one, including TextExpander, can peek at your passwords. Problem is, if you use the Return key to submit a form from within its secure field, they won't turn secure event input off. This appears to be a bug they've inherited from some Firefox code they use. The workaround is to use the submit button rather than using Return in the password field. 1Password is similarly affected by this bug. The workaround there is to turn off auto-submit and just use auto-fill then press the button to submit.

This is referenced on Mozilla's bug tracker.

Good quote on the misunderstandings of software development

Much of present-day software acquisition procedure rests upon the assumption that one can specify a satisfactory system in advance, get bids for its construction, have it built, and install it. I think this assumption is fundamentally wrong, and that many software acquisition problems spring from that fallacy. (Brooks 1987 cited Larman and Basili 2003, p.52).

Source: http://www.sebastiangreger.net/writings/concept-design-in-agile-environment/

Reminder: Restful controllers do not need to map one-to-one to models (in Rails)

The central concept of REST is the resource, which is a datastructure representing one or more business objects.

Source: http://nicksda.apotomo.de/2010/10/rails-misapprehensions-crud-is-not-rest/

A reminder for why to use ems for font-size, line-height and space in CSS

The advantage to using ems for font size, line height, and spacing between elements is that as text size is adjusted, those measurements will adjust proportionately.

Source: http://www.slideshare.net/LRyder/best-practices-and-css

Monday, January 24, 2011

Upgrading Git via MacPorts (1.6.6 to 1.7.3.5)

I upgrade Git this morning to the latest version available via MacPorts. I ran into a few issues, but mostly painless. Here is the run down:

sudo port selfupdate
sudo port upgrade git-core

First upgrade attempt resulted in the following error:

--->  Dependencies to be installed: readline
Portfile changed since last build; discarding previous state.
--->  Activating readline @6.1.002_0
Error: Target org.macports.activate returned: Image error: /opt/local/lib/libreadline.5.2.dylib already exists and does not belong to a registered port.  Unable to activate port readline. Use 'port -f activate readline' to force the activation.
Error: Failed to install readline
Log for readline is at: /opt/local/var/macports/logs/_opt_local_var_macports_sources_rsync.macports.org_release_ports_devel_readline/main.log
Error: The following dependencies were not installed: readline
Error: Problem while installing sqlite3

Executing the following command resolved this issue:

sudo port -f activate readline

Try upgrading again:

sudo port upgrade git-core

Resulted in the following error:

Configuring db46¬ 23 Error: db46 requires the Java for Mac OS X development headers.¬ 24 Error: Download the Java Developer Package from: ¬ 25 Error: Target org.macports.configure returned: missing Java headers¬ 26 Log for db46 is at: /opt/local/var/macports/logs/_opt_local_var_macports_sources_rsync.macports.org_release_ports_databases_db46/m    ain.log¬
 27 Error: Problem while installing db46¬
 28 To report a bug, see 

I downloaded and installed the Java Developer Package.

Another attempt:

sudo port upgrade git-core

Success!

git --version
git version 1.7.3.5

Sunday, January 16, 2011

Minitest raising error for Cucumber generate command in Rails 3/Ruby 1.9.2

I mistaken included the "shoulda" gem in the "development" group. When generating cucumber with the following options I receive the following error:

rails g cucumber:install --capybara --rspec --spork
/Volumes/Data/Users/nicholas/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/minitest/unit.rb:566:in `block in process_args': invalid option: --capybara (OptionParser::InvalidOption)
 from /Volumes/Data/Users/nicholas/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/minitest/unit.rb:545:in `new'
 from /Volumes/Data/Users/nicholas/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/minitest/unit.rb:545:in `process_args'
 from /Volumes/Data/Users/nicholas/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/minitest/unit.rb:576:in `run'
 from /Volumes/Data/Users/nicholas/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/minitest/unit.rb:492:in `block in autorun'

Excluding "shoulda" from the "development" group (i.e. just in test) resolved the error.

References

Google Groups

Friday, January 14, 2011

Stub called with unexpected arguments fixed in RSpec2 Mocks

In RSpec 1.3 the following would pass:

describe Person do
 describe "#greeting" do
   context "using #stub with correct parameters" do
     before(:each) do
       subject.stub(:greeting).with("Nicholas")
     end

     specify { lambda{ subject.greeting("Nicholas") }.should_not
raise_error(NoMethodError) }
   end

   context "using #stub with incorrect parameters" do
     before(:each) do
       subject.stub(:greeting).with("incorrect parameter")
     end
     specify { lambda{ subject.greeting("Nicholas") }.should
raise_error(NoMethodError) }
   end
 end
end

From the example above you can see that calling a stuff with a different parameter would raise a NoMethodError. A bit confusing.

Fortunately in RSpec 2 it fixed. The following error is raised:

1) Person#greeting using #stub with incorrect parameters 
     Failure/Error: specify { lambda{ subject.greeting("Nicholas") }.should raise_error(NoMethodError) }
       expected NoMethodError, got ##<RSpec::Mocks::MockExpectationError: #<Person:0x0000010216fb68#> received :greeting with unexpected arguments
         expected: ("incorrect parameter")
              got: ("Nicholas")>

Related links:

  • My post to RSpec mailing list
  • http://github.com/rspec/rspec-mocks/issues/20
  • http://groups.google.com/group/rspec/browse_thread/thread/ab3519f98597815c

RSpec double, mock, and stub

RSpec uses double to create a test double. However, there are two aliases for this method mock and stub. When do we use which alias? It depends on what role the test double is fulfilling.

If the test double is the focus of the test, then you will be setting a message expectation on the double, which takes the "mock" role.

If the test double is not the focus, and you are simply stubbing out methods on an object, then this takes the "stub" role. You can often eliminate the number of method stubs by ignoring method calls using #as_null_object.

Radiant, Cucumber and Globalize2 Extension

After installing the Globalize2 extension and creating Cucumber features for a dependent extension, I needed to remove the dataset class method to get features running since the models no longer matched the dataset factories:

# /Library/Ruby/Gems/1.8/gems/radiant-0.9.1/features/support/dataset.rb
require 'dataset'

Cucumber::Rails::World.class_eval do
  include Dataset
  datasets_directory "#{RADIANT_ROOT}/spec/datasets"
  self.datasets_database_dump_path = "#{Rails.root}/tmp/dataset"
 #dataset :users, :config, :pages, :layouts, :pages_with_layouts, :snippets, :users_and_pages, :file_not_found, :markup_pages
end

Concept of collapsing margins

CSS is a strange beast, and typically the behaviour of margins can be a little strange to beginners. Over seven years old, this article from Andy Budd, No Margin for Error, is still a good read for the CSS newbie:

At it's core, margin collapsing is very easy to understand. Basically when two vertical margins meet up, instead of adding together, the largest margin takes precedent and the other one "collapses" to nothing.

Never use rescue blindly

On a recent project I was horrified to see various inline rescues. Here are three examples:

# Example 1
def friend_recommended_picture
  friend.recommended_picture rescue ""
end

# Example 2
params[:search][:skip_conversion] = true rescue nil

# Example 3
item_image = Product.find_by_id(product_id).images.find(:first, :conditions => 'attachment_file_name like "%example.jpg"').attachment.url(:mini) rescue ''

In all of these examples I the author is protecting themselves from a NoMethodError with a NilClass.

My preference is to always use the try method (provided in Rails 2.x and standard in Ruby 1.9):

# Example 1
def friend_recommended_picture
  friend.try(:recommended_picture) # returns nil if friend is nil
end

In Rails, this can be cleaned up using the delegate class method:

delegate :recommended_picture, :to => :friend, :allow_nil => true, :prefix => true

For the second example I would prefer this, although there is a little more code involved (clarity over cleverness):

# Example 2
params[:search][:skip_conversion] = true if params[:search]

And for the final example, well this is a bit of a mess. Let's clean up the call:

item_image = item_image(Product.find(product_id))

And encapsulate the various scopings within the correct classes.

# products_helper.b
def item_image(product)
 product.example_image.try(:attachment) {|attachment| attachment.url(:mini) }
end

# models/post.rb
def example_image
  images.examples.first
end

# models/images.rb
named_scope :examples, :conditions => 'attachment_file_name like "%example.jpg"'

This last example illustrates well that the careless use of rescue nil is a symptom of other issues such as poor encapsulation.

There are plenty of examples of using rescue such as on Ruby Inside:

h = { :age => 10 }
h[:name].downcase                         # ERROR
h[:name].downcase rescue "No name"        # => "No name"

This still makes me feel dirty inside. Yes it is working on a Hash, but what if h becomes a more complex object, then that rescue could be obscuring other exceptions. My preference would be:

h[:name].try(:downcase) || "No name"

Jay Fields also has an interesting use for inline rescue. One of the commenters mentions "its important to use them judiciously." I suspect the inline rescue is a victim of cargo culting and 99% of the time there is a better solution.

Thursday, January 13, 2011

Interfacing with Web Services? Checkout Tammer Saleh's "Coding for Failure"

Last year when interfacing with several Web services for a project I found Tammer Saleh's "Coding for Failure" indispensable. Although it was presented two years ago, it's far from out of date.

You can check it out on the Confreaks website and download the slides from here (the link on Tammer's website is broken).

Specifically I found Tammer's summary of different exceptions helpful which I have included here:


See slides for handling in controllers and rake tasks and notification using HopToad.

Capture HAML to yield in a layout

Rails has the content_for method which allows you to yield content into a layout later in the rendering phase of a view. Often I need the same functionality when using StaticMatic. Since I'm using Haml this is easier to do.

Tuesday, January 4, 2011

Applying OO principles to CSS

 

One of the frustrating aspects of coding CSS is the ad-hoc approach in crafting styles. It felt all my software development practices went out the window. Compass, a stylesheet authoring framework, along with Sass, a stylesheet language, has alleviated most of my pain. However, implementation still varies from developer to developer.

I have refined my approach to focus on styling content elements first (e.g. H1, ul, p tags), the grid, and finally the chrome (e.g. backgrounds). While this approach has worked quite well, I'm still not completely satisfied on the reusability of the "chromed" elements. This is where Nicole Sullivan comes in, developer of the OO CSS framework. While a Compass implementation is in the works, I'm quite happy adapting the philosophy of the framework to may current workflow. Specifically the 10 Best practices she outlines in her presentation Object Oriented CSS:

  1. Create a component library
  2. Use consistent semantic styles
  3. Design modules to be transparent on the inside
  4. Be flexible
  5. Learn to love the grid
  6. Minimize selectors
  7. Separate structure and skin
  8. Separate container and content
  9. Extend objects by applying multiple classes
  10. Use reset and fonts from YUI

Practices 7 and 8 need more explanation. Below are comments from Nicole's blog post announcing the framework hosted on Github.

Separate structure and skin

Abstract the structure of the block from the skin which is being applied.

Separate structure from skin isn’t about HTML and CSS. Within the CSS, have one class that takes care of all of the little presentational elements, browser differences, basically all the complicated bits. Then build on that class with multiple skin classes, which then only need to contain simple things like border colors, background images, etc. The skins become super predictable.

 

Separate container and content

Break the dependency between the container module and the content objects it contains.

A glance at the CSS of most sites will tell you no one is doing this properly. At best we manage to separate by module, or sandbox individual components. Unfortunately, each of the modules has container and content completely tied together. This makes the CSS grow over time and the site not scale or perform well.

Her nine pitfalls are also worth noting:

  1. Location dependent styles
  2. Avoid specifying what tag a class applies
  3. Avoid IDS to style inside the main content areas
  4. Avoid drop shadows and rounded corners over irregular backgrounds
  5. Don't sprite every image together (unless your site has very few pages)
  6. Avoid height alignment
  7. Text as text, not as images
  8. Redundancy
  9. Avoid premature optimization

Nicole's presentation is well worth watching if you intend to adopt such a framework, or simply wish to improve you CSS authoring skills. I have included the video of the presentation below along with the slides. Here are some helpful links if you wish to research further:

Object Oriented CSS

Slides

Please note this blog is no longer maintained. Please visit CivilCode Inc - Custom Software Development.