Programming

Testing for a redirect using Capybara and Selenium WebDriver

0

I just spent the better part of 8 hours trying to figure out how to do this. The Selenium WebDriver API docs are pretty bewildering especially when it comes to trying to interact with the HTTP response or request itself because those constructs are abstracted quite a bit.

Then /^I should be on the (.*) page$/ do |page_name|
  object = instance_variable_get("@#{page_name}")
  page.current_path.should == send("#{page_name.downcase.gsub(' ','_')}_path", object)
  page.status_code.should == 200
end
Then /^I should be redirected to the (.*) page$/ do |page_name|
  page.driver.request.env['HTTP_REFERER'].should_not be_nil
  page.driver.request.env['HTTP_REFERER'].should_not == page.current_url
  step %Q(I should be on the #{page_name} page)
end

Which we can use in a Cucumber feature like so:

Given I am on the homepage
When I click on the link to add a widget
Then I should be able to complete the widget form
  And I should be redirected to the widget page
  And I should see a confirmation message
  And I should see the widget listed

Setting up a Rails 3 virtual machine using Vagrant and VirtualBox

0

I recently started bringing other developers on board to help me with a project that up until then I had been the sole developer on. I already had some rudimentary installation instructions that I had updated on occasion as I was originally developing the application, but it turns out that all the developers experienced problems of one kind or another while following along on their own development machines. Although I had recommended using RVM to at least isolate the application gem bundle, it was clear that there were other per-machine libraries and dependencies that were not being accounted for. So, I decided to include instructions on setting up a virtual machine which would hopefully alleviate these issues. My problem with VMs in general though, especially ones that you want to spin up and tear down quickly, is that it’s still possible for everyone involved in the project to be using a different VM manager and linux distro, and thus a different package manager and standard lib setup, and you still need to do a lot of setup after the fact to get all the necessary components to work. Enter Vagrant. (more…)

Notes on Single Table Inheritance (STI) in Rails 3.0

8

I’m currently working on a project that calls for splitting up a single model into two similar models with slightly differing functionality. I was already familiar with Alex Reisner’s excellent article on when to use Single Table Inheritance versus the other alternatives that one might use, and after re-reading the article with a colleague it was determined that STI was probably our best bet. However, neither of us could remember seeing any recent articles on STI in Rails, specifically with Rails 3, and it’s been my experience that if people aren’t talking about a Rails feature it’s probably because it’s been recently deprecated or replaced.

Not wanting to back ourselves in a corner before we were sure it would work, I decided to spike a dummy Rails app and see what problems we would run into. There are plenty of questions on StackOverflow (1, 2, etc.), et. al., with various suggestions for working through issues related to STI, but there was no one concise guide that detailed the benefits and drawbacks of each approach. I decided to document my findings. This is my first real-life attempt at implementing an STI pattern, so please leave a comment if you feel that I omitted something or if you know of another way to approach one of these issues.

(more…)

Testing model validations in rspec the short and sweet way

2

There seems to be a divide in the Rails/TDD community over whether you should bother testing your model validations. On the one hand, it’s silly to just retest what the Rails core team has hopefully already tested — that validations work. On the other hand, I want to make sure that my models only accept the data that I design them to accept. I also tend to use my RSpec unit tests as blueprints for building out my models, in true TDD fashion, so I start out by defining what values they should accept.

(more…)

Named redirect routes in Rails 3

0

I didn’t see this mentioned anywhere in the Rails Guide or in my admittedly cursory Google searches, but apparently it’s possible to create named redirect routes in Rails 3. For example:

1 2 3 4
Myapplication::Application.routes.draw do
match "/facebook" => redirect("http://www.facebook.com/pages/MarkZuckerbergFanClub/12345678"), :as => 'facebook'
match "/twitter" => redirect("http://twitter.com/TweetyMcTweet"), :as => 'twitter'
end
view raw routes.rb This Gist brought to you by GitHub.

Then you can use those in your layouts like so:

1 2 3 4
<ul class="social-links">
<li class="facebook"><%= link_to "Like us on Facebook", facebook_path %></li>
<li class="twitter"><%= link_to "Follow us on Twitter", twitter_path %></li>
</ul>

It Should Include Only One Of – An RSpec Matcher

0

I know RSpec tests should typically be implementation/data agnostic, but I ran into a situation in a unit test where I needed to make sure that the results of a query returned only one of the two records that were created during the setup but without knowing which record that would be ahead of time. This was due to the fact that the scoped finder returned a random record. So, I wrote a little matcher that lets me assert that a given array contains only one of a set of specified elements.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# Inspired by http://blog.nicksieger.com/articles/2011/01/20/rspec-2-matcher-fun
RSpec::Matchers.define :include_only_one_of do |*elements|
match do |container|
@included = []
elements.flatten.each do |e|
@included << e if container.include?(e)
end
@included.count == 1
end
 
failure_message_for_should do |container|
"expected array of #{container.length} elements to include only one member.\n" +
"Found #{@included.flatten.inspect}"
end
end

You can use it like so:

1 2 3 4 5 6 7 8 9
require 'include_only_one_of'
 
describe "SomeTest" do
it "should return only one wide format promotion if available" do
first_wide_promotion = Factory(:promotion, :brand => @brand, :format => Promotion::FORMATS[:wide])
second_wide_promotion = Factory(:promotion, :brand => @brand, :format => Promotion::FORMATS[:wide])
@brand.featured_promotions.should include_only_one_of(first_wide_promotion, second_wide_promotion)
end
end

Join (implode) an Array of String Values with Formatting

1

In programming, I often need to join values together from an array. Typically this will be to do something on the backend, like join a list of integers together in a comma-delimited string for use in a SQL statement. For those times, the native join/implode functions work fine. Occasionally however, we need to finesse the resulting string to look a little more readable. I wrote a small function to do so. It’s called pretty_join()

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
<?php
function pretty_join($array, $intermediate_separator = ', ', $final_separator = ' & ')
{
if (!is_array($array)) return null;
switch (sizeof($array))
{
case 0: return null; break;
case 1: return reset($array); break;
case 2: return implode($final_separator, $array); break;
default:
$end = array_pop($array);
// This second call prevents the last two elements from being reversed
$end = array_pop($array) . $final_separator . $end;
array_push($array, $end);
return implode($intermediate_separator, $array);
}
}
?>

Given an array of 0 or more values, pretty_join() will concatenate all of the values together using a common delimiter (a comma by default) except for the last two values which will be joined by the final separator (an ampersand by default).

Examples:

1 2 3 4 5 6 7 8 9 10 11 12 13 14
<?php
//pretty_join with 0 elements
echo pretty_join(array());
// =>
//pretty_join with 1 elements
echo pretty_join(array('Big Tires'));
// => Big Tires
//pretty_join with 2 elements
echo pretty_join(array('Big Tires', 'Pretty Houses'));
// => Big Tires & Pretty Houses
//pretty_join with 3 elements
echo pretty_join(array('Big Tires', 'Pretty Houses', 'Fat Wives'));
// => Big Tires, Pretty Houses & Fat Wives
?>

Writing the First Cucumber Feature

0

I’m currently working on my first BDD project, but after reading through the Cucumber wiki for what felt like the 100th time I was still not sure where to start. I tried generating a boilerplate feature file as the documentation suggests (even though the documentation then tries to dissuade you from taking that approach in the next paragraph), but the generated file didn’t really provide much guidance so I was back to square one. Finally I started asking for advice on the freenode #cucumber channel. It seemed like a shot in the dark, knowing that every project is different and there isn’t really a single pattern that would work for everyone. The initial responses were less than illuminating, but after a few short minutes someone offered the following advice:

msassak: auth features are not very valuable, imo
msassak: you need to do them, but i would implement almost anything first
msassak: err anything else
cbloom: So assume every user is registered for now. Then start hiding stuff after the other features are complete?
msassak: that's what i would do
cbloom: OK, that makes a lot of sense.
msassak: imagine you are going to present this to someone who is going to pay you for it
msassak: do they want to see that users can log in, or that users can do something cool on the site?
cbloom: they want to see that users can print coupons
cbloom: so I'll start with that
msassak: yup, exactly
cbloom: so simple, yet so abstract

It seems so simple now. Now to see if that actually cures my writers block.

Find the longest common substring using PHP

1

I recently found a need to find the longest common substring in an array of strings in PHP. A couple of Google searches didn’t return any relevant solutions, so I decided to roll my own. I haven’t benchmarked this yet for large strings and/or arrays, but it does what I needed it to for my own purpose.

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 26 27 28 29 30 31 32 33 34 35
<?php
function longest_common_substring($words)
{
$words = array_map('strtolower', array_map('trim', $words));
$sort_by_strlen = create_function('$a, $b', 'if (strlen($a) == strlen($b)) { return strcmp($a, $b); } return (strlen($a) < strlen($b)) ? -1 : 1;');
usort($words, $sort_by_strlen);
// We have to assume that each string has something in common with the first
// string (post sort), we just need to figure out what the longest common
// string is. If any string DOES NOT have something in common with the first
// string, return false.
$longest_common_substring = array();
$shortest_string = str_split(array_shift($words));
while (sizeof($shortest_string)) {
array_unshift($longest_common_substring, '');
foreach ($shortest_string as $ci => $char) {
foreach ($words as $wi => $word) {
if (!strstr($word, $longest_common_substring[0] . $char)) {
// No match
break 2;
} // if
} // foreach
// we found the current char in each word, so add it to the first longest_common_substring element,
// then start checking again using the next char as well
$longest_common_substring[0].= $char;
} // foreach
// We've finished looping through the entire shortest_string.
// Remove the first char and start all over. Do this until there are no more
// chars to search on.
array_shift($shortest_string);
}
// If we made it here then we've run through everything
usort($longest_common_substring, $sort_by_strlen);
return array_pop($longest_common_substring);
}
?>

Example:

1 2 3 4 5 6 7 8 9 10
<?php
$array = array(
'PTT757LP4',
'PTT757A',
'PCT757B',
'PCT757LP4EV'
);
echo longest_common_substring($array);
// => T757
?>
Go to Top