Pivotal Labs

Main menu

Skip to primary content
Skip to secondary content
  • About
  • Case Studies
  • Team
    • Executives
    • Locations
      • San Francisco (HQ)
      • Boston
      • Boulder
      • Denver
      • London
      • Los Angeles
      • New York
  • Community
    • Blogs
    • Tech Talks
    • Events
  • Careers
    • Lifestyle
    • Principles & Practices
    • Benefits
    • FAQ
    • Apply
  • Contact
    • Press Room
    • Press Releases
    • In The News
    • Press Kit
  • All
  • Labs
  • Standup
  • Tracker
Robbie Clutton

Testing strategies with RSpec, NullDB and Nosql

Robbie Clutton
Sunday, February 3, 2013

Recently I had posted about a few testing strategies that can be applied with RSpec. One of the patterns I mentioned was using something like NullDB to ensure your unit tests were not hitting the database. I had a few conversations about what I’d written, notably from my colleague Ian Lesperance. We discussed, and I conceded, that it’s preferable to have tests related to one class in one spec file. In particular I had split out the tests for the unit level and the integration with the database tests. So, here are my experiments on how I brought those tests back while keeping the same integrity of using a database for some test and forcing the null object pattern on other tests.

I had some issues having those tests in the same file, but with a little help from another colleague, JT Archie, we managed to figure it out.

Consider this rspec test:

  describe Widget do
    describe "#higest_selling", :db do
      it "uses the 'highest_selling' scope" do
        ...
      end
    end

    describe "#display_name" do
      it 'concats the widget name and manufacturer' do
        ...
      end
    end
  end

The ‘higest_selling’ method is a scope and has the ‘:db’ tag associated to the block, while the ‘display_name’ test has no tags applied. I wanted this to be the case, no tags means no database but if you want to hit the database, you need to explicitly call it out.

One trick you might have missed above was no longer needing to do ‘db: true’ in the RSpec tag. With the following setting in the spec helper, you can apply a symbol directly like ‘:db’.

config.treat_symbols_as_metadata_keys_with_true_values = true

Testing with NullDB

To get this working, I had to use the HEAD revision of NullDB:

gem 'activerecord-nulldb-adapter', git: 'git://github.com/nulldb/nulldb.git'

Using NullDB within the same file, we can use the ‘nullify’ and ‘restore’ helpers, but I found it worked best using the ‘around’ configuration. Using ‘before’ and ‘after’ I was having issues with changing the connection adapter during a transaction. This way, it appears to get around that issue.

We run the configuration block around each test that has the ‘type: :model’ tag. RSpec-Rails applies these automatically to any tests in the ‘spec/models’ directory. We look to see if the example has the ‘:db’ tag and if it does, we restore the default connection adapter, and run the example. If the example does not have the ‘:db’ tag applied, we apply the NullDB adapter, run the example and then restore the default adapter.

Within the ‘spec_helper.rb’ file:

  config.around(:each, type: :model) do |example|
    if example.metadata[:db]
      NullDB.restore
      example.run
    else
      NullDB.nullify
      example.run
      NullDB.restore
    end
  end

Testing using stubs

There are other options and with a sizable amount of help from JT, we created a simple way to achieve a similar outcome. Under ActiveRecord there are two methods which actually hit the database, ‘exec’ and ‘exec_query’. These methods can be stubbed out much like any method on any object in an application codebase.

In the ‘spec_helper’ file, we replace the NullDB configuration with the following. We again check for the ‘db’ tag and if it’s not there we stub ‘exec’ and ‘exec_query’.

  config.around(:each, type: :model) do |example|
    unless example.metadata[:db]
      ActiveRecord::Base.connection.stub(:exec).
        and_raise("You're not allowed to do that")
      ActiveRecord::Base.connection.stub(:exec_query).
        and_raise("You're not allowed to do that")
    end
  end

Testing using Nosql

We took this concept one step further and created a Gem that wasn’t RSpec specific. We couldn’t believe our luck when RubyGems showed there was no Gem called ‘nosql’, so with that problem solved we created the Nosql gem. When included in a test suite, any call to the database will raise an exception.

With the around configuration block Nosql is disabled and enabled accordingly.

  config.around(:each, type: :model) do |example|
    if example.metadata[:db]
      Nosql::Connection.disable!
      example.run
    else
      Nosql::Connection.enable!
      example.run
      Nosql::Connection.disable!
    end
  end

All three of these options force unit tests to not hit the database. Database calls will either be ignored (NullDB), or will raise an error (Nosql). This should result in decreased execution time for tests as it will encourage the developer to stub out those interactions with the database.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Robbie Clutton

Introducing Simple BDD

Robbie Clutton
Saturday, February 2, 2013

Simple BDD is a way to bring structured natural language BDD syntax into any test framework, but why is this necessary?

Have you ever looked back a test you wrote several months ago, or even the several hours ago and wondered what you were thinking and what you were trying to achieve? Behaviour Driven Development (BDD) attempts to resolve this with the structured language or ‘given’, ‘when’ and ‘then’ and natural language describing how an application should behave.

There are a growing number of tools to assist using BDD in Ruby and Rails today, notably Cucumber. Cucumber extracts the behaviour of the application into plain text files using natural language and uses a parser to translate these into methods which should be executed in relation to the natural language.

What if you’ve already got a good test suite, but you just want some of the structured language that something like Cucumber gives you? Well, recently I created a tiny Ruby library to do just this, Simple BDD. Simple BDD allows use of natural language within any executable code, be that RSpec or any flavour of test library.

Given "an authenticated user"
When "that user submits a message less than 140 characters"
Then "that message is displayed to the users followers"
And "is also shown in the users timeline"

These natural language statements are translated into method calls which are executed in the current scope of the test.

an_authenticated_user
that_user_submits_a_message_less_than_140_characters
that_message_is_displayed_to_the_users_followers
is_also_shown_in_the_users_timeline

My colleague Matt Parker recently wrote about how Cucumber steps as teleportation devices and that same thinking applies here. To make the most of this these wordy methods should be considered jumping points into your testing DSLs.

For a more detailed example, check out the Simple BDD example project.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Grant Hutchins

Refactoring the Deeply-Nested Hash Antipattern

Grant Hutchins
Saturday, January 26, 2013

On a few different Ruby projects, I have seen an antipattern emerge involving nested hashes.

For example, consider this simple question-and-answer command-line script:

QUIZ = {
  question_1: {
    prompt: "What is your name?"
  },

  question_2: {
    prompt: "What is your favorite color?"
  }
}

answers = {}

QUIZ.each do |name, question_hash|
  print question_hash[:prompt], " "
  answers[name] = gets.chomp
end

p answers

The QUIZ constant isn’t too hard to understand. The keys (question_1 and question_2) each point to a value that is itself another hash. Let’s call that a question_hash. For now a question_hash has only one key-value pair, the prompt.

The answers hash simply accumulates answers. The key is the key from the QUIZ constant, and the value is the answer the user typed in.

At the end of the script, the program calls Kernel#p to print out the inspect string for the answers hash.

Sure enough, the program works.

$ ruby quiz.rb 
What is your name? Grant
What is your favorite color? orange
{:question_1=>"Grant", :question_2=>"orange"}

Take a look at the QUIZ.each block up there. Notice that the inside of the block assumes that the question_hash will have a :prompt key.

That’s not too complicated. But let’s add some more features to our script. Now we will add a multiple-choice question to the QUIZ hash:

QUIZ = {
  question_1: {
    prompt: "What is your name?"
  },

  question_2: {
    prompt: "What is your favorite color?"
  },

  question_3: {
    prompt: "What is your favorite integer between 1 and 5?",
    choices: %w[1 2 3 4 5]
  }
}

Now we want to treat a question_hash differently if it has a choices key. One way to do this is to write two different methods that take the question_hash as an argument and ask the question. The methods will return the answer that the user inputs.

def simple_answer(question_hash)
  print question_hash[:prompt], " "
  gets.chomp
end

def multiple_choice_answer(question_hash)
  choices = question_hash[:choices]
  answer = nil

  until choices.include?(answer)
    print question_hash[:prompt], " "
    answer = gets.chomp
    puts "You must pick an answer from #{choices}" unless choices.include?(answer)
  end

  answer
end

Now we simply update our block to call the appropriate method for each question_hash.

QUIZ.each do |name, question_hash|
  answer = if question_hash[:choices]
    multiple_choice_answer(question_hash)
  else
    simple_answer(question_hash)
  end

  answers[name] = answer
end

p answers

This all still works fine.

$ ruby quiz.rb 
What is your name? Grant
What is your favorite color? orange
What is your favorite integer between 1 and 5? 7
You must pick an answer from ["1", "2", "3", "4", "5"]
What is your favorite integer between 1 and 5? 3
{:question_1=>"Grant", :question_2=>"orange", :question_3=>"3"}

But the code is very quickly getting more complex. Before long, we will have questions with sub-questions, conditional follow-up questions, and even more complicated features. Here’s an example that supports a Proc for formatting the user’s answer.

QUIZ = {
  question_1: {
    prompt: "What is your name?"
  },

  question_2: {
    prompt: "What is your favorite color?",
    display_proc: ->(color) { "The color is #{color}." }
  },

  question_3: {
    prompt: "What is your favorite integer between 1 and 5?",
    choices: %w[1 2 3 4 5]
  }
}

answers = {}

def simple_answer(question_hash)
  print question_hash[:prompt], " "
  gets.chomp
end

def multiple_choice_answer(question_hash)
  choices = question_hash[:choices]
  answer = nil

  until choices.include?(answer)
    print question_hash[:prompt], " "
    answer = gets.chomp
    puts "You must pick an answer from #{choices}" unless choices.include?(answer)
  end

  answer
end

QUIZ.each do |name, question_hash|
  answer = if question_hash[:choices]
    multiple_choice_answer(question_hash)
  else
    simple_answer(question_hash)
  end

  answers[name] = answer
end

display_answers = Hash[
  answers.map do |name, answer|
    if display_proc = QUIZ[name][:display_proc]
      [name, display_proc[answer]]
    else
      [name, answer]
    end
  end
]

p display_answers

The output now looks like this

$ ruby quiz.rb 
What is your name? Grant
What is your favorite color? orange
What is your favorite integer between 1 and 5? 6
You must pick an answer from ["1", "2", "3", "4", "5"]
What is your favorite integer between 1 and 5? 3
{:question_1=>"Grant", :question_2=>"The color is orange.", :question_3=>"3"}

And the code will keep growing and growing, making it harder for the next developer to understand exactly how the big Hash will translate into the user’s experience.

Take a look at those answer methods. Whenever I see a bunch of methods that accept the same argument, I suspect that there is an object missing in my system. Let’s create a new Question object. Imagine that we have it in that QUIZ.each block, and that we can simply ask the Question for its answer directly.

class Question
  def initialize(question_hash)
    @question_hash = question_hash
  end

  def answer
    if @question_hash[:choices]
      multiple_choice_answer(@question_hash)
    else
      simple_answer(@question_hash)
    end
  end

  private

  def simple_answer(question_hash)
    print question_hash[:prompt], " "
    gets.chomp
  end

  def multiple_choice_answer(question_hash)
    choices = question_hash[:choices]
    answer = nil

    until choices.include?(answer)
      print question_hash[:prompt], " "
      answer = gets.chomp
      puts "You must pick an answer from #{choices}" unless choices.include?(answer)
    end

    answer
  end
end

QUIZ.each do |name, question_hash|
  question = Question.new(question_hash)
  answers[name] = question.answer
end

Notice that simple_answer and multiple_choice_answer are now completely private. That’s good, because it hides away the internal details of how a Question works. We are now free to start doing some refactoring, without worrying about the rest of the code in the system breaking.

Our first refactor will be to remove the arguments from the private methods, since it’s now possible to get at the @question_hash directly from within the Question object.

class Question
  def initialize(question_hash)
    @question_hash = question_hash
  end

  def answer
    if @question_hash[:choices]
      multiple_choice_answer
    else
      simple_answer
    end
  end

  private

  def simple_answer
    print @question_hash[:prompt], " "
    gets.chomp
  end

  def multiple_choice_answer
    choices = @question_hash[:choices]
    answer = nil

    until choices.include?(answer)
      print @question_hash[:prompt], " "
      answer = gets.chomp
      puts "You must pick an answer from #{choices}" unless choices.include?(answer)
    end

    answer
  end
end

Next, notice that the only reason we are passing the question_hash into the Question is to get out the prompt and the choices. When a constructor takes a hash with expected keys, you can swap the hash out for multiple arguments instead.

class Question
  def initialize(prompt, choices)
    @prompt = prompt
    @choices = choices
  end

  def answer
    if @choices
      multiple_choice_answer
    else
      simple_answer
    end
  end

  private

  def simple_answer
    print @prompt, " "
    gets.chomp
  end

  def multiple_choice_answer
    answer = nil

    until @choices.include?(answer)
      print @prompt, " "
      answer = gets.chomp
      puts "You must pick an answer from #{@choices}" unless @choices.include?(answer)
    end

    answer
  end
end

Now the object is easier to understand. But there’s still a problem. To use this new object, the each block needs to be updated:

QUIZ.each do |name, question_hash|
  prompt = question_hash[:prompt]
  choices = question_hash[:choices]
  question = Question.new(prompt, choices)
  answers[name] = question.answer
end

This is uglier than what we had before. But there’s a quick fix that makes our code much nicer. Let’s change the QUIZ hash so that its values are already Question objects:

QUIZ = {
  question_1: Question.new("What is your name?", nil),
  question_2: Question.new("What is your favorite color?", nil),
  question_3: Question.new("What is your favorite integer between 1 and 5?",
                           %w[1 2 3 4 5])
}

This makes our each block much nicer!

QUIZ.each do |name, question|
  answers[name] = question.answer
end

But there’s still one problem. Our QUIZ no longer holds the display_proc, so this code from before fails:

display_answers = Hash[
  answers.map do |name, answer|
    if display_proc = QUIZ[name][:display_proc]
      [name, display_proc[answer]]
    else
      [name, answer]
    end
  end
]

So let’s put that proc into the Question object and make it available via an attr_reader. While we’re at it, we can give default values of nil for both choices and nil.

class Question
  attr_reader :display_proc

  def initialize(prompt, choices = nil, display_proc = nil)
    @prompt = prompt
    @choices = choices
    @display_proc = display_proc
  end

  # ...

Now our QUIZ looks like this:

QUIZ = {
  question_1: Question.new("What is your name?"),
  question_2: Question.new("What is your favorite color?",
                           nil,
                           ->(color) { "The color is #{color}." }),
  question_3: Question.new("What is your favorite integer between 1 and 5?",
                           %w[1 2 3 4 5])
}

And our display_answers code looks like this:

display_answers = Hash[
  answers.map do |name, answer|
    if display_proc = QUIZ[name].display_proc
      [name, display_proc[answer]]
    else
      [name, answer]
    end
  end
]

Now let’s move the logic for deciding how an answer should be formatted into the Question object. (We can remove the attr_reader for display_proc at this time as well, to keep things nicely hidden away.)

class Question
  # ... 

  def display_answer(answer)
    if @display_proc
      @display_proc[answer]
    else
      answer
    end
  end

  # ...

Which gives us:

display_answers = Hash[
  answers.map do |name, answer|
    question = QUIZ[name]
    [name, question.display_answer(answer)]
  end
]

At this point, it seems like the question name could also easily be put into the Question object as a new first argument. Let’s replace the QUIZ constant with a QUESTIONS constant that holds an array of Question objects.

QUESTIONS = [
  Question.new(:question_1,
               "What is your name?"),
  Question.new(:question_2,
               "What is your favorite color?",
               nil,
               ->(color) { "The color is #{color}." }),
  Question.new(:question_3,
               "What is your favorite integer between 1 and 5?",
               %w[1 2 3 4 5])
]

answers = {}

QUESTIONS.each do |question|
  answers[question.name] = question.answer
end

display_answers = Hash[
  QUESTIONS.map do |question|
    answer = answers[question.name]
    [question.name, question.display_answer(answer)]
  end
]

p display_answers

Now the code is much cleaner. There are definitely more places the code could be refactored. choices and display_proc could be moved into an options hash argument since they are truly optional. Maybe there could be a SimpleQuestion superclass and a subclass called MultipleChoiceQuestion with all the choices-related code.

The most important thing to realize is that now the conversation that future developers might have about this code has shifted.

Before, the conversation would probably have centered around how complicated the code looked and confusion about how the structure of the QUIZ hash affects the control flow of the rest of the program. What is the easiest way to make a small change to add a new feature without breaking the whole big complex structure?

Now, the conversation can be about whether the current object model makes sense or should be tweaked in some small way. And with the full power of a Ruby class instead of the limited behavior of a Hash, the developers will have more options.

This code example is available on GitHub with a full Git history of the working code at each stage. Here’s the final code:

class Question
  attr_reader :name

  def initialize(name, prompt, choices = nil, display_proc = nil)
    @name = name
    @prompt = prompt
    @choices = choices
    @display_proc = display_proc
  end

  def answer
    if @choices
      multiple_choice_answer
    else
      simple_answer
    end
  end

  def display_answer(answer)
    if @display_proc
      @display_proc[answer]
    else
      answer
    end
  end

  private

  def simple_answer
    print @prompt, " "
    gets.chomp
  end

  def multiple_choice_answer
    answer = nil

    until @choices.include?(answer)
      print @prompt, " "
      answer = gets.chomp
      puts "You must pick an answer from #{@choices}" unless @choices.include?(answer)
    end

    answer
  end
end

QUESTIONS = [
  Question.new(:question_1,
               "What is your name?"),
  Question.new(:question_2,
               "What is your favorite color?",
               nil,
               ->(color) { "The color is #{color}." }),
  Question.new(:question_3,
               "What is your favorite integer between 1 and 5?",
               %w[1 2 3 4 5])
]

answers = {}

QUESTIONS.each do |question|
  answers[question.name] = question.answer
end

display_answers = Hash[
  QUESTIONS.map do |question|
    answer = answers[question.name]
    [question.name, question.display_answer(answer)]
  end
]

p display_answers
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
John Barker

Facebook and GooglePlus Javascript SDK sign in with Devise + RoR

John Barker
Friday, January 18, 2013

Recently I added a modal sign in and sign up dialog to a Rails application that allowed for sign in using Facebook or Google as well as via email. This dialog can appear any time a user attempts to perform a protected action, allowing them to sign in and continue without losing any data.

To make this work I had to implement Google and Facebook sign in using the new javascript SDK provided for both platforms. The old style authentication redirects when successful which means any in memory session state is completely lost. This means forms are cleared, event handlers are rebound and any work in progress has to be done again.

Before I explain the difficulties we had getting this to work with I’ll explain briefly how OAuth works with respect to devise.

Typical OAuth workflow

Most sites implement this kind of workflow by opening a popup window pointing at their oauth request url (e.g: /oauth/facebook/). This sets up the initial state of the session using a cookie and redirects to the login page providing a url to it to redirect the user again once they’ve authenticated.

If authentication is successful, an oauth token is generated and stored in a cookie and the user is redirected to the callback url. The callback url hits the devise stack and verifies that the token is real by asking Facebook to verify it. If everything checks out execution dips into your application code and the user is created or looked up by some identifiable piece of information.

Client Side workflow

The new SDKs provided by Facebook and Google have changed this and allow for much greater flexibility. Facebook documents its new login workflow here http://developers.facebook.com/docs/howtos/login/getting-started/ and Google documents theirs here: https://code.google.com/p/google-api-javascript-client/wiki/Authentication.

Both APIs have a simple method which expects a callback. The callback is executed indicating whether authentication was successful and it’s up to you what you do with that information. This allows for greater flexibility and smoother transitions into an authenticated step.

Getting it to work with Devise

There are a number of gotchas with using the client side approach, some of them related to possible bugs and my difficulty in interpreting just how the OAuth devise gems work.

OAuth Gem Version

Omiauth OAuth2 version 1.1 recently introduced CSRF validation for the authentication workflow. Unfortunately this breaks client side validation since there is no request component.

For now I suggest downgrading those gems like so:

# NOTE: omniauth-oauth2 breaks client authentication, see here:
# https://github.com/intridea/omniauth-oauth2/issues/20
gem 'omniauth-oauth2', '~> 1.0.0'
# NOTE: omniauth-facebook 1.4.1 breaks SDK authentication, see here:
# https://github.com/mkdynamic/omniauth-facebook/issues/73
gem 'omniauth-facebook', '= 1.4.0'

The comments will give any future reader of your Gemfile an indication of what they need to do to lift the version restrictions on the omniauth dependencies.

Google OAuth2 Token Validation

The current omniauth-google-oauth2 gem will try to validate your access token with a different server and request format to the one required by the new javascript SDK. For the time being you can use our the forked version (here)[https://github.com/pivotal-geostellar/omniauth-google-oauth2/tree/client_login].

Performing Authentication

For the Facebook SDK I authenticate like so:

FB.login(function(response) {
  if(response.authResponse) {
    $.ajax({
      type: 'POST',
      url: '/users/auth/facebook/callback',
      dataType: 'json',
      data: {signed_request: response.authResponse.signedRequest}
      success: function(data, textStatus, jqXHR) {
        // Handle success case
      },
      error: function(jqXHR, textStatus, errorThrown {
        // Handle error case
      })});
  }
, scope: 'email'});

For Google:

var scope = 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile';
gapi.auth.authorize({client_id: 'client id', scope: scope}, function(result) {
    if(result && !result.error) {
      $.ajax({
        type: 'POST',
        url: '/users/auth/google_oauth2/callback',
        data: {code: result},
        dataType: 'json',
        success: function(data, textStatus, jqXHR) {
          // Handle authorized case
        },
        error: function(jqXHR, textStatus, errorThrown) {
          // Handle error case
        }
      });
    } else {
      // Handle unauthorized case
    }
});

Both of these calls hit the OAuth callback endpoint to verify the access tokens obtained by the user. If authentication succeeds you’ll get the typical devise+OAuth workflow and a session omniauth.auth cookie with the appropriate details.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Robbie Clutton

Testing within an ActiveRecord block

Robbie Clutton
Thursday, July 19, 2012

Following on from the article about ActiveRecord blocks and a similar topics at the office book club, I’ve been trying to put some of these concepts into my code. I did find it difficult to figure out how to test within the block. Below I’ll outline what we did to test the code within the block.

Say we’ve got a Foo class which inherits from ActiveRecord.

class Foo < ActiveRecord::Base end 

When create a new foo, we can use a block to mutate the object.

Foo.create(args) do |foo| foo.x = 1 end 

In the test, we want to return a stub, but we can’t assert that x was called on that stub as the block won’t be executed.

Foo.should_receive(:create) { foo_stub } foo_stub.should_receive(:x=) # assertion fails 

We can use a block after the ‘should_receive’ call to get the block as a Proc and call it with the stub we want to run assertions on.

Foo.should_receive(:create) do |args, &block| block.call(foo_stub) end 

Now we can successfully test inside the block.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Glenn Jahnke

iOS Acceptance and Ruby Keywords

Glenn Jahnke
Wednesday, July 11, 2012

Helps

  • acceptance testing for iOS: Frank?

We’d like to do happy path end-end testing for an iOS project. What’s the state of the art?

We saw frank: https://github.com/moredip/Frank

Interestings

  • then is a keyword in ruby

If you want your ruby to read like bash:

if true then
  puts "For Sure"
end
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Mark Rushakoff

A Great Example of Vendor-Library Abstraction in ActiveSupport

Mark Rushakoff
Monday, June 18, 2012

Depending on what you’re working on, you may have been bitten at least once by a heavy dependency on a third-party library.
This happens when you become very dependent on the API of someone else’s library, and suddenly you can no longer use that library or its API.

When this is a possibility, the defensive approach to this problem is to write your own API to wrap that API, so that if you need to drop that vendor library, you only have to reimplement the way your wrapper works.

You might think that you only need to worry about this in large, complicated APIs, but it can be worthwhile to do even for a simple API.

ActiveSupport::JSON uses MultiJSON behind the scenes.
Even though ActiveSupport::JSON has really only two publicly available “normal-use” methods (encode and decode which transform Ruby hashes back and forth with JSON objects), the Rails developers were wise enough to even wrap the specific error class that MultiJSON raises, as ActiveSupport::JSON.parse_error.

# File activesupport/lib/active_support/json/decoding.rb, line 50
def parse_error
  MultiJson::DecodeError
end

This way, you can write something like

begin
  obj = ActiveSupport::JSON.decode(some_string)
rescue ActiveSupport::JSON.parse_error
  Rails.logger.warn("Attempted to decode invalid JSON: #{some_string}")
end

And then if/when Rails switches from MultiJSON, you won’t have to change anything in your code to deal with exception handling around JSON.

(PS.
I wrote the documentation for that method recently, so that’s why I had to link to the Edge Guides.
If you haven’t seen it, check out my article on how easy it is to contribute to the Rails documentation.)

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Mark Rushakoff

We’re finally getting destroy! in Rails 4

Mark Rushakoff
Friday, June 8, 2012

Unlike create!, save!, and friends, the destroy! method didn’t exist in Rails 3.
It took me a while to get used to destroy instead of destroy! from the Rails console and from test code, but Rails 4 will provide destroy!, which is different from destroy in the following ways:

  • Instead of returning false on failure, it will raise ActiveRecord::RecordNotDestroyed
  • If you have a before_destroy callback that returns false, it will still raise ActiveRecord::RecordNotDestroyed

There’s going to be a lot less cycles of “write a test that calls destroy!, see a NoMethodError, change destroy! to destroy, and re-run the test” once Rails 4 is released. I know I’ve lost a few minutes of my life doing that :)

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Mark Rushakoff

Testing mass assignment with RSpec-Shoulda

Mark Rushakoff
Monday, May 28, 2012

If you’re new to Rails, or if you’ve been using Rails 2 for a long time, you might not be aware that Shoulda offers an allow_mass_assignment_of matcher that works just like it sounds. Here’s the example from the source code:

it { should_not allow_mass_assignment_of(:password) }
it { should allow_mass_assignment_of(:first_name) }

Having explicit tests for whether fields should be mass-assignable is probably safer than letting developers arbitrarily add or remove fields from the attr_accessible declarations — at least when they break a test they’ll have to think twice about it.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Mark Rushakoff

RSpec: Asserting arrays’ content without regard to order

Mark Rushakoff
Monday, May 21, 2012

Sometimes I want to make assertions about the content of an array when the order of its content is not guaranteed:

nums = [1,2,3].shuffle
nums.length.should == 3
nums.should include 1
nums.should include 2
nums.should include 3

(Of course this is a contrived example, and we could just write nums.sort.should == [1,2,3]. But sometimes we are working with objects that aren’t already sortable.)

I recently found out that RSpec has an array matcher that is specifically intended for this use case, via the =~ operator:

[1,2,3].shuffle.should =~ [1,2,3]
  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Topics

  • agile (778)
  • rails (113)
  • testing (87)
  • ruby (83)
  • ruby on rails (70)
  • jobs (62)
  • javascript (54)
  • techtalk (44)
  • rspec (38)
  • activerecord (29)
  • productivity (29)
  • gogaruco (29)
  • ironblogger (29)
  • git (28)
  • nyc (27)
  • rubymine (25)
  • mobile (22)
  • bloggerdome (21)
  • cucumber (20)
  • process (19)
  • pivotal tracker (19)
  • jasmine (19)
  • design (18)
  • ios (18)
  • webos (17)
  • objective-c (17)
  • android (16)
  • palm (16)
  • "soft" ware (16)
  • fun (15)
  • tracker ecosystem (15)
  • ci (15)
  • cedar (15)
  • rails3 (14)
  • performance (14)
  • bdd (14)
  • gem (13)
  • tdd (13)
  • selenium (12)
  • css (12)
  • goruco (12)
  • bundler (12)
  • meetup (11)
  • railsconf (11)
  • nyc-standup (11)
  • capybara (10)
  • mac (10)
  • mojo (10)
  • chef (10)
  • api (10)
Subscribe to ruby Feed
  1. ←
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8. 7
  9. 8
  10. 9
  11. →
  • About
  • Case Studies
  • Team
  • Community
  • Careers
  • Contact
  • Labs
  • Events

Contact Us

contact@pivotallabs.com
+1 415-77-PIVOT
TwitterLinkedInFacebook

Pivotal Tracker

Tracker is the award-winning agile project management tool that enables real-time collaboration around a shared, prioritized backlog.
Visit pivotaltracker.com >