Code Snippets

Small snippets of code that I find interesting or useful. Generally my own work, but I will cite sources if not.

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

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
?>

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