Category Archives: Ruby

Cool stuff you can do with rails has_one

Over the past three months has_one has shown itself to be the answer to questions that I was struggling to get an elegent answer for.

The two cases I found were:

1. Specifying a belongs_to :through
2. Accessing one item of a list of related records

The second case ends up expanding to be anytime you want to have a named scope that returns a single record.

Specifying a belongs_to :through with has_one

Say you have a model of the form:

You can see that we’ve used the standard has_many and belongs_to methods to model the relationships between the entities. We’ve also thrown in a has_many through to help model the fact that an organization has_many employees. Conceptually we also want to be able to specify the inverse of this relationship on the Employee. Something like:

The way to implement the belongs_to :through concept is to use has_one :through

Accessing one item of a list of related records

There can often be a desire to specify a scope that returns a single record. This isn’t possible in rails, as scopes by definition are chainable and will return subclasses of ActiveRecord::Relation, which is a list like object.

The way to do this is to setup a has_one with a block specifying a scope. For example:

has_one :head_of_department, -> { where role: ‘department_head’ }, class_name: ‘Employee’

For bonus points the proc and conditions can also be parameterised, so we can end up with a has_one relationship with a parameter. To see the coolness of this we can extend the model a little bit to include
a many-to-many entity and a has_many through relationship.

With the above model it would be handy to have an easy way of accessing the ProjectDepartment easily when you are working with projects. has_one to the rescue.

So with our collection of has ones all together, we end up with code something like:

 

has_one is a powerful tool to have in your rails modelling. Take advantage of it to give some really nice clean looking code.

Running Thin in a Thread to serve static files (or how to seed carrierwave images)

Published by Rob on March 27th, 2014 – in Ruby

I recently wanted to have a short-term local webserver. Specifically to be able to seed some images with carrierwave, using the handy external_image_url functionality. The project Gemfile has Thin in it, so it made a bunch of sense to use it. Another important property is that I want to be able to run this simple server from within a rails process. There are three bits of information that I learnt and particulary want to highlight

  • starting a thin server to serve a directory
  • running thin in a thread
  • the CarrierWave remote_#{attribute_name}_url (where attribute name is the name of the attribute you have CarrierWave uploadified – used as remote_image_url throughout the rest of this post)

Here is the code that I ended up with for the thin server:

For the carrierwave I ended up with:

Then at the end I clean up with:

So all in one spot the code is:

The above code is a nice little script for programatically uploading images to your carrierwave models in rails code.

Options for getting JRuby 1.6 to use Ruby 1.9 Syntax

In 2012 and beyond you really want to be using Ruby 1.9 syntax (as per the standard ruby implementation KRI). JRuby 1.6 uses Ruby 1.8 syntax by default, but this can be changed to be 1.9. There are a bevy of different ways to do this. I’ll outline these here, and give you my recommendation on what to do.

Command Line parameter

The first way to set the ruby syntax version is to call ruby with a –1.9 parameter thusly:

This I don’t like at all because it doesn’t work with irb, and you have to type different things when using KRI and JRuby.

RUBYOPT Environment variable

A second option is to set the RUBYOPT environment variable to –1.9

This works for irb, but will actually prevent KRI from starting up as KRI doesn’t support the –1.9 parameter (KRI is Ruby 1.9 so the parameter doesn’t make sense).

JRUBY_OPTS Environment variable

Another option is to set the JRUBY_OPTS environment variable.

This works great for JRuby , irb in JRuby, and KRI.

.jrubyrc file

The next useful option is in a user specific .jrubyrc file. This gets called before JRuby starts up. Keep it in ~/.jrubyrc

This works well if you are working in an environment where you will always be running 1.9 compatible code. It’s what I currently do.

rvm

If you are using rvm there are a number of ways to do things.

First you can use a .rvmrc and set the JRUBY_OPTS variable, or a PROJECT_JRUBY_OPTS environment variable.

The second option is to enable rvm jruby hooks.

hooks live in $rvm_path/hooks.

In rvm 1.14.3 there are a series of after_use hooks, including some after_use_jruby hooks. Inspect these to see what they do (after_use runs all the other after_use hooks, and the after_use_jruby scripts will get some JRuby magic happening). You could put one of the earlier options here to help make JRuby work.

Conclusion

In conclusion my recommendations for getting JRuby 1.6 to use Ruby 1.9 syntax are:

  1. use a .jrubyrc file wherever possible
  2. use a .rvmrc for situations where you need different versions of JRuby.

Writing Beautiful RSpec Matchers

thoughtbot have created a really nice set of custom matchers for RSpec.  The Shoulda matchers make writing tests for rails models beautiful and clean.

Shoulda matchers make it possible to write specs of the form:

It’s easy to do this for yourself using the friendly matcher DSL that ships with RSpec. Let’s take a look at how.

In the simplest form, all you need to do is to call the define method, passing a name, and a block which in turn calls out to match. The simple case might be:

We’ve just defined a matcher :be_less_than which allows us to do the following:

If we use the describe auto subject feature of RSpec we can also write:

and

With that example we can see that we are getting close to the shoulda matcher syntax.  There’s still an extra level that helps make the shoulda matchers nice, chaining. Happily this is easy to do as well. The dsl provides a chain method.  The chain methods are called before the match, so you can use the chain calls to collect up additional information to validate.  Using our example above, we might want to add in an :and_greater_than chain.

This now will give us the ability to write:

Unfortunately the default descriptions don’t quite work as nice when there are chains in place. You’ll find that you’ll want to write a description in the matcher definition.

Unfortunately the description doesn’t automatically get used in the error messages when the matcher fails, so you’ll want to specify a failure_message_for_should. Basing it off the description is an ok starting point.

Happily RSpec does the right thing with the should not description, so with the details above the matcher will be good. There might be a case where you want a different failure_message_for_should_not, which can also be specified.

That covers how to write simple reusable RSpec matchers to make your test code look as beautiful as your production code. Go ahead and try it yourself.  I’d love to see comments or questions you might have on this.

Backbone.JS on Rails

A while ago I made a post Two tricks for getting Backbone.js to play well with Ruby on Rails. It was good at the time, but probably not the place you really want to be reading.

For the best information go to quora, and read the answer to the question
How well does backbone.js work with rails? by Jeremy Ashkenas, the creator of Backbone.JS. It’s the best article on the topic, and deserves all the google juice it can get.

In particular the pick function approach mentioned is useful – and would have gone a decent way to preventing the github mass assignment vulnerability.

How to get OpenSSL in Ruby 1.9.3 working on OSX 10.7 (fixing the Segmentation Fault with Ruby OpenSSL)

update – this needs to have a recent version of RVM – it works with rvm 1.10 but not with 1.6 – do an rvm update first.

When using the mighty cobweb web crawler on my OSX 10.7 with Ruby 1.9.3 I was getting a seg fault in net http:

net/http.rb:799: [BUG] Segmentation fault

A bit of googling and isolation in IRB showed that this can be caused when hitting HTTPS urls using net http.

I saw a few different solutions to the problem, primarily talking about Ruby 1.9.2.Surprisingly it took me a while to end up at the RVM documentation about the problem: https://rvm.beginrescueend.com/packages/openssl/. This didn’t quite work out of the box for me, so I used the solution in the following gist.

View the code on Gist.

and now I can happily crawl https urls.

Two tricks for getting Backbone.js to play well with Ruby on Rails

Backbone.js is a great library for creating single page applications that consume RESTful JSON services. Ruby on Rails does well at generating RESTful APIs and speaking JSON. In order to get the Rails working really well with Backbone, there are two tricks to do.

First, add the following line to the application controller to make the output look like what backbone expects.

Second take advantage of the : only option in to_json to limit the attributes included in the serialised json object. The documentation for this isn’t quite there in the latest rails, but the 2.3 to_json method describes it. http://apidock.com/rails/ActiveRecord/Serialization/to_json.

With these two simple tricks rails will generate the json that backbone wants, and you’ll have a happy front-end developer.

Updating RubyGems in OSX 10.5.7

.7When recently trying to install Sinatra via RubyGems, I got a message that RubyGems was out of date. I figured that gem would be smart enough to have an easy upgrade command, so there had to be a command to easily upgrade. Naturally there is:

gem update --system

I only found this when looking through google, and I got a series of pages warning to be careful when using gem update --system as it can kill existing gems (http://puctuatedproductivity.com/2007/11/01/unistalling-ruby-installed-by-source-on-os-x, http://thenoobonrails.blogspot.com/2008/06/doing-gem-update-system-might-lose-all.html) so I was a bit nervous.  Since I have a periodic use of ruby and I'm lazy enough to make Larry Wall proud, I figured I'd take a punt on just using gem update --system.  Turns out it just works, and I've kept all my old gems.  Hooray.  Given that the posts talking about issues are old, I'm either assuming that they've done things differently to me, or things have been fixed since then… so… if you need to update gems due to a message:

ERROR: Error installing sinatra:
fastthread requires RubyGems version >= 1.2

or similar, just use gem update --system