Mastodon

Does your predicate return what you think it does?

def has_query?
  self.param_search_query && self.param_search_query != "Eventname"
end

I found this in some code I was working on today. This is a pretty standard “predicate method”, which, by convention, should always return either true or false. Strangely, as I was exploring the code with Pry, I noticed the method return nil.

It turned out that param_search_query was actually nil, which, when mixed with the logical AND (&&) operator returns something the author clearly did not expect:

mike@sleepycat:~☺  irb
irb(main):001:> nil && true
=> nil

This was actually surprising to me too. I would have thought that nil would have been falsey and that the expression would return false. Definitely something I am going to remember next time I am using the && operator.

So the next question is, what to do about it.
One way to ensure a boolean return value that I have seen is to use the bang operator twice. This works because !nil is true and !!nil is false:

irb(main):003:0> !!nil
=> false

So we could use that to fix the method like so:

def has_query?
  !!(self.param_search_query && self.param_search_query != "Eventname")
end

I’m not a fan of this because I think it obscures the intention of the author.
In the end, since this was in a Rails app I went with the present? method:

def has_query?
  self.param_search_query.present? && self.param_search_query != "Eventname"
end

The tests pass and I’m back to hunting bigger game…

Factory not registered

I have been working on adding tests to an existing Rails app for one of my clients. The app was written by some well intentioned person who included tonnes of testing libraries but just never got around to writing tests.

group :development, :test do
  gem 'capybara'
  gem 'cucumber'
  gem 'cucumber-rails', :require => false
  gem 'database_cleaner'
  gem 'factory_girl'
  gem 'factory_girl_rails'
  gem 'rspec-core'
  gem 'rspec-expectations'
  gem 'rspec-mocks'
  gem 'rspec'
  gem 'rspec-rails'
  gem 'ZenTest'
end

As I started adding specs I needed to create factories, and when I started to do that I started to get errors. First “Factory already registered” errors and then “Factory not registered” errors. Very annoying.
The root of the problem seems to be that factory_girl_rails and factory_girl both look for factories when loaded. The solution for me was to remove factory_girl and let factory_girl_rails do the right thing.
This triggered a major purge of unneeded gems which left me with a Gemfile that looks like this:

group :development, :test do
  gem 'factory_girl_rails'
  gem 'rspec-rails'
  gem 'capybara'
end

It also left me with passing tests and no further errors.

I think the take away for me here is to let bundler/rubygems dependency management system do the right thing. Over-specifying stuff is a recipe for trouble. Over-specifying stuff in the Gemfile might look like explicitly including factory_girl when it will obviously be a dependency of factory_girl_rails. I’ve also seen problems arise from habitually including version numbers in the Gemfile, which makes things so specific that Bundler no longer has the latitude to figure out something that works.

In any case its a good reminder that less is more.

Rake tasks with arguments

After a little digging and a little time to RTFM, I finally have a working rake task with arguments. The interesting thing about it is that Rake will not pass arguments to a task that is not expecting them. “Expecting them” takes the form of actually passing them as an argument to the task method right after the name. If you want to have defaults you will have to call with_defaults on the incoming args hash. Its a little weird but that’s how it works.

namespace :mike do
  desc "Playing with Rake arguments"
  task :test, [:arg1, :arg2] do |task, args|
    args.with_defaults(arg1: "foo", arg2: "bar")
    puts args.inspect
  end
end

That task can be invoked from code like this:

Rake::Task["mike:test"].invoke("Fizz", "Buzz")

Unfortunately the space between the arguments means that running it from the command line requires quotes:

rake "mike:test[Fizz, Buzz]"

As nice as it is to have figured this out, I think the real question at this point is “Why am I not making this thing a class in my application?”, which of course I should be…

Ahh well, at least this will be here for some future project when I have a convincing answer to that.

Finding methods in a Ruby codebase with Pry

Pry has been becoming a bigger and bigger part of my Ruby development workflow lately. Test not working? Pry. Debugging production from the console? Pry. Rake task doing something incomprehensible? Pry. But for finding stuff within a codebase my goto solution is still grep:

grep -ri def\ my_method .

Recently I grepped for a method called param_search_query in a project I am working on and came up with nothing.
After some head scratching and digging through some gems I thought I would try ctags.
Nothing. So I decided to see if Pry could help.

    30:   def has_query?
 => 31:     binding.pry
    32:     self.param_search_query && self.param_search_query.present? && self.param_search_query != "Eventname"
    33:   end
    34: 
    35:   def tickets
    36:     @tickets = Ticket.with_min_price
pry(#<Search:0x7fa5ea6f59e0>)> show-method self.param_search_query

It pry’s show-method function revealed the source of the confusion (pardon the pun), the method was being dynamically generated:

From: /home/mike/projects/frontend-server/app/models/search.rb @ line 20:
Number of lines: 7

define_method "param_#{psp}" do
  if self.search_params && self.search_params[psp].present?
    self.search_params[psp]
  elsif self.project
    self.project.get_param(psp)
  end
end

How did I get any work done without this?

Another look at creating Rails users in Postgres

Three years (!) has passed since I first wrote about setting up users for your Postgres development database. This does not come up often for me, but every time I see my own list of instructions I shudder and think there must be a better way. This morning I figured it out.

Here is what I have in my config/database.yml:

development:
adapter: postgresql
encoding: unicode
database: myapp_development
pool: 5

Omitting the username and password from the database.yml means that postgres will try to log using your operating system username using the peer method. Since I am logged in as “mike” that is the username that will be used to authenticate. With this in mind I am just going to create a database user with that name.

mike@sleepycat:~/projects/myapp$ sudo -u postgres createuser --interactive mike
Shall the new role be a superuser? (y/n) y

Notice that used sudo -u to switch to the existing “postgres” user (created by default) and created a superuser that matched my operating system account username.
After that, everything works. Even rake commands.

mike@sleepycat:~/projects/myapp$ rake db:create
mike@sleepycat:~/projects/myapp$ rake db:migrate
==  CreateWidgets: migrating ============================================
...
mike@sleepycat:~/projects/myapp$ rails dbconsole
psql (9.1.9)
Type "help" for help.

myapp_development=# 

Now that is far more civilized.

EuRuKo 2013

Some of the talks from Eururko sounded really good but I missed most of them because of the time difference. Fortunately the live stream was saved and posted, so now I can watch them whenever!

Update: Ustream has thoughtfully decided to ignore the autoplay=false parameter that WordPress adds to all the videos to prevent them autoplaying. So rather than embeding them and having them all play at the same time everytime the page loads I am just going to link to them. Thanks Ustream.

Day 1 Part 1

Day 1 Part 2

Day 1 Part 3

Day 2 Part 1

Day 2 Part 2

Day 2 Part 3

Including helper methods in javascript

I’m working on an app and found myself needing set an initial position for a map.
The most reasonable thing seems to be to geocode the IP in the controller and use it in my javascript.
So in my controller I tried creating a method that did what I needed. I figured declaring it as a helper_method and adding a .erb to the file name so it would be preprocessed would be all I would need to do.
For some reason it was not so simple…

If you call in your javascript file you get a decendent of Sprockets::Context. For reasons I don’t understand, Rails helper menthods don’t seem to be included in it.
My need was just to pass in my geocoded lat/long values, and using a gem felt like a little much so created a JsVars module that behaves like a hash and included it in the context class with an initializer:

config/initializers/sprockets_helpers.rb 

Rails.application.assets.context_class.class_eval do
  include AssetMethods
end

My little hash module looks like this:

module AssetMethods
  module JsVars
    @vars = {}

    def self.[]=(k, v)
      @vars[k]=v
    end

    def self.[](k)
      @vars[k].to_json
    end
  end
end

And that lets me do this in my whatever.js.erb:

var test = ;

which comes out as:
var test = {“fizz”:”buzz”};

I think I would have to take a hard look at json escaping if/when I start using that for user supplied data, but for now it fits the bill nicely. While I am happy to have figured out a workable solution, I have a suspicion there was a much easier way to have done it.
For the moment… onwards!

Remote Debugging Chrome on Ubuntu

Between AngularJS and some work on responsive design, I’ve been using Chrome Dev Tools more and more lately. One of the things that has really impressed me is Chrome’s remote debugging. Getting it going on Ubuntu is extra easy since it turns out that the Android Debug Bridge tool is in the repos already:

sudo apt-get install android-tools-adb

And then you can fire up the debug bridge and open the debug tools in Chromium in one shot with this:

adb forward tcp:9222 localabstract:chrome_devtools_remote; chromium-browser localhost:9222

And when you’re done:

adb kill-server

That adb command is a pretty good candidate for an alias, since I don’t use is that often and need to google for it every time.

If you think that’s cool, Chrome’s Dev Tools have plenty more features to explore…

Getting Thomas was alone working on Ubuntu 13.04 64bit

I just bought the Humble Bundle 8 mostly because I liked the looks of “Thomas was alone”.
Sadly the download is just a tar file, which I always find a little off putting. It took a little tinkering to get it going so I thought I would save someone else the searching by writing it here.

Extract the contents of the tar file in whatever way makes you happy.

mike@sleepycat:~/Downloads/thomasLinuxStandalone$ ls
thomasWasAlone  thomasWasAlone_Data
mike@sleepycat:~/Downloads/thomasLinuxStandalone$ chmod +x thomasWasAlone

My problem was that I got an error when I tried to run it:
mike@sleepycat:~/Downloads/thomasLinuxStandalone$ ./thomasWasAlone
./thomasWasAlone: error while loading shared libraries: libGLU.so.1: cannot open shared object file: No such file or directory
[/code]

But its easy enough to fix:

mike@sleepycat:~/Downloads/thomasLinuxStandalone$ sudo apt-get install ia32-libs-multiarch:i386
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following extra packages will be installed:
...lots of packages and installation stuff...

And finally it works:

mike@sleepycat:~/Downloads/thomasLinuxStandalone$ ./thomasWasAlone
Set current directory to /home/mike/Downloads/thomasLinuxStandalone
Found path: /home/mike/Downloads/thomasLinuxStandalone/thomasWasAlone
Mono path[0] = '/home/mike/Downloads/thomasLinuxStandalone/thomasWasAlone_Data/Managed'
Mono path[1] = '/home/mike/Downloads/thomasLinuxStandalone/thomasWasAlone_Data/Mono'
Mono config path = '/home/mike/Downloads/thomasLinuxStandalone/thomasWasAlone_Data/Mono/etc'

Happy gaming!

The difference between Feature Specs and Request Specs

Rspec has two different types of tests that are very similar to integration tests; request specs and feature specs. The difference between them has never been particularly clear to me and seems to be a point of confusion for many others as well.

Feature specs and Request specs are both are part of rspec-rails and are built on a similar foundation.

Request specs are built on top of Rails integration tests, which offer an API with methods that mirror what you find in HTTP: “get”, “put”, “post”, etc.
It gives you a “response” object for you to make your assertions against.

Feature specs are built on top of Capybara. The goal of Capybara is to offer an API that “simulates user behaviour”. To that end their API employs language that is not far from what you would use when directing someone to use a website over the phone:

visit '/sessions/new'
fill_in 'Login', :with => 'user@example.com'
fill_in 'Password', :with => 'password'
click_link 'Sign in'
page.should have_content 'Success'

Under the covers “visit” is just calling Rack::Test methods but there is no low-level, HTTP oriented language (request, response, get, put, etc…) used in the API itself. Capybara is consciously omitting them as Jonas Nicklas (Capybara’s author) explains on his blog.

Feature specs exist to provide a place for the type of high level testing that Capybara enables. The Relishapp site describes them as “high-level tests meant to exercise slices of functionality through an application. They should drive the application only via its external interface, usually web pages.” This unfortunately jargon-laden description, really only made sense after some digging.

Which brings us to Request specs. These are for those moments when the details of HTTP are exactly what you care about; like when you are testing an API.

get "/todays-forcast"
expect(response.body).to have_content "sunny"

Here the details of HTTP are front and centre, because in an API they matter. This is why request specs are referred to as ” a thin wrapper around Rails’ integration tests”, the focus is on providing just some Rspec sugar to use with the existing HTTP oriented methods.

The confusion around these things seem to stem from the early days of the project. When Capybara was first created it was intended to be used within request specs. That created a bunch of confusion because of the competing syntaxes ( get/visit, response/page) which resulted in the creation of feature specs to give a proper home to this type of testing.

Unfortunately people are still following old instructions and this usage is still common which muddies the water when trying to understand which is which. Hopefully this adds a little clarity.