Less Work

When I receive a feature request or a bug to solve, I start thinking how I will design and implement a solution. Many developers have this tendency.

But it is better to check first if a solution is actually needed. Sometimes there is a way to remove the problem entirely. And it may be easier than implementing a solution.

At work my current project is a complex and massive data migration. In particular the migration of a specific set of objects requires deep changes in the code to accommodate the new data format for them.

Before I started to implement those changes, my boss suggested that I count how many of those objects would need to be migrated. What a good idea! It turned out that a only a dozen - out of thousand of records - had a content structure requiring them to migrate.

We found an easy way to adjust their content so that they no longer had to migrate. Thus I no longer had to change the code to deal with the migration of this set of objects. Big problem solved just by removing it :)

Elasticsearch

I presented an introduction about Elasticsearch at the Ruby Peru meetup of December 2014. It explains how it differs from a traditional SQL database, and details how is performed a full text search. Here are the slides: http://bit.ly/es-rubyperu

Rails anti patterns

I presented a few Rails anti patterns at the Ruby Peru meetup of April 2014. Here are the slides:

Handling Requests in Parallel in Rails Applications

I presented an introduction about handling requests in parallel in Rails applications during the Ruby Peru meeting of August 2013.

If you want to know more I highly recommend the book Working With Ruby Threads, from Jesse Storimer.

Here are the slides:

Easier Usage of attr_accessible

attr_accessible is the recommended method to protect your attributes from mass assignments in Rails. It lists for a model the attributes that can be mass assigned, other attributes will be protected. But it is tedious to build and update this list of accessible attributes while developing an application.

Fortunately there are two mechanisms which facilitate the usage of attr_accessible.

First you can configure your application to create an empty whitelist of attributes available for mass-assignment for all the models. This forces you to explicitly list the accessible attributes of each model, without the risk of forgetting a model or an attribute. To do this just add config.active_record.whitelist_attributes = true in the configuration application.rb.

When a protected attribute is mass assigned, the attribute value is not modified and by default Rails logs a warning. This makes sometimes hard to realize that some attribute isn’t set or modified through a create or update action because it is protected. Since the version 3.2 it is possible to have an exception raised when a protected attribute is mass assigned. Thus it is much easier to detect attributes that should be made accessible. For that just add config.active_record.mass_assignment_sanitizer = :strict to your application configuration, or only in development.rb and test.rb if your prefer.

By combining those two mechanisms it is easy to discover progressively the attributes you want to make accessible while developing your application.

Control Over Standards

The Measure of All Things is a great book about the invention the metric system during the French revolution.

The following passage in particular caught my attention:

Each act of measurement in the Ancien Regime referred to a particular physical standard, held in local hands and safeguarded by local officials. A town’s measure for the length of building materials, for instance, might derive from an iron fathom mortised into the wall of the town’s market hall. (…)

Not only did the physical standards differ from community to community, but the technique of measurement depended on local custom. One district measured grain heaped high in its bushel; another measured grain after it had been leveled off; still another, after the bushel had been struck to settle its contents. (…)

This meant that measurements standards were potentially open to dispute, negotiation, and change (…) Outsiders, of course, did no understand these measures, but local buyers and sellers did - which suggests one of the main advantages of local diversity. They kept outsiders out. Distinctive measures protected small-town traders from big-city merchants, or at least forced the latter to pay the equivalent of a fee before the could enter the local market. Artisanal guilds took charge of their own measures so that they might define their goods in a unique way, identify interlopers, and drive them out of business with ruinous lawsuits. This was as true of gunsmiths and milliners then as it is true of the computer industry today. Control over standards is control over the local rules of economic life, and Ancien Régime standards were everywhere local.

This is still true in the Peruvian Andes where the “quintal” weight measurement may differ from village to village.

I learned that standards wars are not specific to our modern age. Googling a bit more about this, I found this article (PDF) which presents a few other historical examples of standards wars and identifies strategies for companies fighting in such battles.

An ActiveRecord Plugin to Prevent Destroy if Associations Are Present

I’ve just released a small plugin that adds ActiveRecord models a way to prevent destroy if specified has_many, has_one and/or belongs_to associations are present. This is achieved by adding a before_destroy callback that aborts the destroy and adds a base error on the instance when detecting associations.

It’s inspired from this stackoverflow answer and was created to factorize this solution when you need it for various models in an application.

PostgreSQL Geometric Types in Ruby and Rails

PostgreSQL supports several geometric types natively (point, line, rectangle, circle…) and operations and operators on these types. Thus PostgreSQL can calculate the distance between 2 points, the diameter of a circle, check if 2 lines intersect or not, if a point is contained in a polygon…

Let see how to leverage these capabilities in Rails with a small demo application that stores the coordinates of different nodes in a 2D plane.

First create the application by choosing PostgreSQL for the database: rails new demo-geo-pg -d postgresql

and create the development database: rake db:create

Then generate the Node model: rails g model Node name:string coordinates:point

The coordinates attribute will store the abscisse and ordinate values of the nodes, it has the PostgreSQL point type. Rails has generated a migration containing the line t.coordinates :point to generate the corresponding column. However if we run the migration as it is, it will fail because point is not a native Rails migration type. We need to change this line into t.column :coordinates, :point. We can now run the migration: rake db:migrate

Now use the the Rails console (rails c) to create a few Node records:

> Node.create! : Name => “Node # 1”: coordinates => “(1.1)” > Node.create! : Name => “Node # 2”: coordinates => “(2.2)” > Node.create! : Name => “Node # 3”: coordinates => “(-2, -2)” > Node.create! : Name => “Node # 4”: coordinates => “(4, -2)”

In Ruby we handle PostgreSQL geometric values with strings following a defined syntax: for the point type it is (x,y) (these syntaxes are described in the PostgreSQL documentation). If this syntax is not respected, PostgreSQL returns an error when trying to save the record in the database:

> Node.create! : Name => “Node # 5”: coordinates => “1”

ActiveRecord:: StatementInvalid: PGError: ERROR: invalid input syntax for type point: “1”

We could validate the format of the coordinate attribute with: validates_format_of: coordinates, :with => /\(-?\d+(?:.\d+)?,-?\d(?:.\d+)?\)/

Now let’s use the PostgreSQL geometric operators on our nodes. Here’s how to get all the nodes located in the circle with center (2,2) and radius 2, using the contains @> operator:

> Node.where(“circle ‘<(2,2),2>’ @> coordinates”) => [#<Node id: 1, name: “Node #1”, coordinates: “(1,1)”, created_at: “2011-05-28 15:00:38”, updated_at: “2011-05-28 15:00:38”>, #<Node id: 2, name: “Node #2”, coordinates: “(1,1)”, created_at: “2011-05-28 15:00:48”, updated_at: “2011-05-28 15:00:48”>]

Implementation of an instance method to find the closest node, using the Distance Between <-> operator:

def nearest where(“id <> #{id}”).select(“*, coordinates <-> point ‘#{coordinates}’ as distance”).order(“distance asc”).limit(1).first end

> Node.first.nearest => #<Node id: 2, name: “Node #2”, coordinates: “(1,1)”, created_at: “2011-05-28 15:00:48”, updated_at: “2011-05-28 15:00:48”>

In some cases the native PostgreSQL geometry types with their functions and operators are adequate and very useful for representing and processing spatial data. When this is not the case, you should use a dedicated tool like PostGIS (there is an adapter for ActiveRecord). See this entry on stackoverflow for more information.

A RSS Feed Listing Every Day New Gems and Updated Gems

The RubyGems feed and Twitter stream do not distinguish between new gems and updated gems, and announce each new version of a gem.

It was hard for me to follow. That’s why I created Gems Summary. It generates everyday a feed post listing separately the new gems released on RubyGems and the updated gems. If a gem is updated several times during a single day, it is mentioned only once in the post.

The source code is on GitHub.

Improve Your Rails Development Workflow

Here the slides of a presentation I gave for the Ruby Peru group on March 26, 2011: Improve Your Rails Development Workflow.

It’s about gems and plugins I use to ease the development of my Rails applications, not processes or programming techniques.

A Single Task to Migrate, Redo Migration, Prepare Test Db and Annotate

Hi!

My first blog post to announce my first gem: migrate-well. It’s a very simple one, it adds a rake task db:migrate:well that runs the tasks db:migrate, db:migrate:redo, rake db:test:prepare and annotate. I was tired to type all those commands each time…

To install: add gem “migrate-well” in your Gemfile and run bundle install.

To run: rake db:migrate:well

Options (updated February 15, 2011):

  • redo=false: don’t run the db:migrate:redo task
  • test=false: don’t run the db:test:prepare task
  • anno=false: don’t run the annotate command

Examples:

  • run without annotating: rake db:migrate:well anno=false
  • run without annotating and without redoing the migration: rake db:migrate:well anno=false redo=false

That’s all!