RubyNation 2012 on the Horizon

Planning activities began today for RubyNation 2012, which will be the 5th year anniversary for the conference. We start planning more than 8 months before the conference, commencing with a planning meeting and kick-off dinner for the organizers.

Up to 16K Page Views

It looks like KeenerTech.com has hit a new mark in monthly page views — more than 16 thousand page views for the month of June, 2011. Many, many thanks to all the visitors!

Confident Code

Avdi Grimm’s Rubynation 2011 talk on “Confident Code” is now available online. Check it out online at Blip.tv!

Ignoring Files with Git

When you’re doing software development, not every file in your working directory tree is an end product that you’d like to check in with git. Git allows you to specify certain files to be ignored.

To have git ignore certain files, simply include a .gitignore file in the top-level directory of your git repository. You should check the file in so that’s shared with everybody on your development team.

Here’s a list of the files that my team has identified as files that should be ignored when developing Rails applications:

   .bundle
   .DS_Store
   *.log
   log/*
   *.db
   db/*.sqlite3
   public/system/*
   *.swp
   *~
   tmp/**/*
   dump
   *.lock
   tmp/*
   coverage/*
   spec/coverage/*
   rails_best_practices_output.html
   schema.rb
   solr/data
   spec/models/coverage
   spec/controllers/coverage
   spec/views/coverage
   .redcar
   *redcar*
   vendor/cache
   vendor/ruby

Boom Goes the Dynamite!

I was educated today by a junior developer: “Boom! Goes the dynamite.” can be used in place of “I made my Rails controller smaller.” So now you know, too.

Recipe: Detecting Required Fields in Rails

It’s a familiar problem. You’re creating a form and you want to mark certain fields as required. You’d rather not hard-code which fields are required, because this might change over time. Plus, you’ve already got validations in your model that check for the presence of required fields, and you’d really rather not duplicate any of that logic. So, how can you tell whether a field associated with an ActiveRecord model is required?

The Problem

Let’s assume that we have a model called Author, with required fields of first_name and last_name. The model looks like this:

   class Author < ActiveRecord::Base

      validates_presence_of :first_name
      validates_presence_of :last_name

   end

The validations ensure that the first_name and last_name attributes of the model will have values. The bottom line is that the model has information about which fields are required. We need to be able to interrogate the model to determine if a field is required.

The Solution

After a little bit of research, it turns out that ActiveRecord has a validators_on method. Let’s fire up the Rails console and see how it works:

      console>  Author.validators_on(:first_name)
      => [#<ActiveModel::Validations::PresenceValidator:0x45c4770 
      @attributes=[:first_name, :last_name], @options={}>]

OK, that gives us an array of validations for the specified field, where each validation is an instance of some type of validation class. That’s somewhat useful, but we can do better.

      console> Author.validators_on(:first_name).map(&:class)
      => [ActiveModel::Validations::PresenceValidator]

That’s even better. Now we have an array of classes, where each element is the class of a validator that has been placed on the specified attribute. The “&:class” argument to the map method causes the class method to be executed for each element in the array.

Now that we know how to get a list of the validations that are on a particular field, we can write a method that will return TRUE or FALSE based on whether a field is required. I’m going to throw in one wrinkle, though. I’d like to be able to call the method using either a class or an instance of a class.

   def required?(obj, attr)
      target = (obj.class == Class) ? obj : obj.class
      target.validators_on(attr).map(&:class).include?(
         ActiveModel::Validations::PresenceValidator)
   end

I can put this method in my application_helper.rb file for my Rails application. Then I can call it from a view in two ways:

      required?(Author, :first_name)

Or, assuming that the controller has passed an instance of the Author model to the view as @author:

      required?(@author, :first_name)

By the way, this call works just fine, as well:

      required?(@author, “first_name”)

Now my view logic can easily check whether a field is required.

   <%= form_for(@author) do |f| %>
      <p><%= f.text_field :first_name %>
      <% if required?(@author, :first_name) %>*<% end %></p>

Reception

[May 5, 2026] This article was quite well received back in the day. Since I can’t easily port the comments from the old version of the KeenerTech.com website, I pulled some screenshots instead:

First Batch of comments...
Second Batch of comments...
Third Batch of comments...

Interview for the EngineYard Podcast

EngineYard will be interviewing me next week for their Cloud Out Loud podcast. They’re specifically interested in my experiences with Ruby on Rails in the government arena. In the DC area, the presence of Rails within government agencies has been growing dramatically.

Changing the Domain of a WordPress Site

You’ve got a WordPress site, and you’ve had to change the domain name where it’s hosted. Suddenly none of the links on the site work. How do you fix it?

Well, you’ve got some manual database updates ahead of you. WordPress comes with a MySQL database. You’ll need to log in and run a few SQL statements to make the necessary changes.

Don’t worry if you don’t know the login information for your WordPress site’s database. That information can be found in one of the WordPress source files, which can be found at:

      <wordpress-dir>/wp-config.php

Armed with this information, you can login and (carefully) make the necessary changes. You should seriously consider backing up the database before you make any changes. See my earlier article on doing MySQL database dumps.

OK. First, we’ll need to change two settings in the WP_OPTIONS table, “siteurl” and “home”:

UPDATE wp_options
   SET option_value = 'http://yourdomain.com'
 WHERE option_name = 'siteurl';

UPDATE wp_options
   SET option_value = 'http://yourdomain.com'
 WHERE option_name = 'home';

Next, there is the WP_POSTS table. The “guid” column of this table lists the full URL of a revision of a post. There can be a lot of rows in this table, and every row needs to have the domain name portion of its “guid” updated.

It’s tedious, but doable.

By updating these two settings in the WP_OPTIONS table and the URL’s in the WP_POSTS table, you can successfully move your WordPress site to a different domain name.

Deploying KeenerTech From Git

I just published my first KeenerTech.com update from my shiny, new Git repository. But I still have all of my old history from my original Subversion repository. How cool is that?

(OK, maybe you really have to be a techie to appreciate this.)

The Empty String Code Smell in Rails

Sometimes you look at some source code and it just doesn’t look right. The code might seem inordinately complex for the simple task being accomplished. Or the developer might be performing certain actions repeatedly, such as checking variables for nil values. This is what is known as a code smell..

Code smells should be corrected at the earliest possible opportunity. In this article, I’ll talk about some real-world coding issues that my friend, Robb Kidd, and I recently encountered.

The Repetitive Value-Checking Code Smell

Here’s a code smell that I found in a Rails view:

   <% if @item.summary.nil? || @item.summary == ” %>
      <p>Not Defined</p>
   <% else %>
      <p><%= @item.summary %></p>
   <% end %>

This type of code was provided for every field associated with an “item.” Not good. Not surprising, though. This is a pretty common code smell from Ruby newbies.

Here’s a slightly better modification:

   <% if @item.summary.blank? %>
      <p>Not Defined</p>
   <% else %>
      <p><%= @item.summary %></p>
   <% end %>

The blank? method checks for both nil and empty strings in one method. It even works on arrays:

   arr = []
   arr.blank?

If the array is empty, as it is in the code above, then blank? returns true.

The blank? method is awfully convenient for these types of checks. It also has a companion method, present?, that does the inverse check, i.e. — it checks if a value is present (ensuring that the value is not blank).

We can shorten the original code even further:

   <p><%= @item.summary.blank? ? ‘Not Defined’ : @item.summary %></p>

Now we’ve got the original code sample down to one line using what amounts to an inline if-statement. That’s pretty good.

But we’re still repeating that if-statement for every field displayed. To DRY the code up even further, we could extract that statement into a helper method:

   def format_text(txt)
      txt.blank? ? ‘Not Defined’ : txt
   end

In the view, the code then becomes:

   <%= format_text(@item.summary) %>

Now the view is simple. Just the way I like it.

The Empty String Code Smell

I still wasn’t happy though. You see, the developer had told me that the reason he needed to check for empty strings everywhere was because empty strings were being physically stored in the database.

This was something that Robb Kidd and I began investigating immediately.

To me, this code smell was far worse than the original view-related one that had triggered this deep dive into the codebase. I was appalled that empty strings were being stored in the database.

This might not seem like a big deal to many Rails developers. But with the types of high-end enterprise systems that I typically build, high-quality data is vital. Relational databases represent empty fields as NULL. Once you start putting empty strings into database fields, you have compromised the usefulness of NULL to represent the absence of information. You’ve also doomed everybody who ever works with that database to check for both NULL’s and empty strings if they want to determine whether a valid value is present.

You’ve stored a code smell in the database for all eternity. Not good.

Even worse, the database may be an underlying component of a Rails application, but there’s nothing in an enterprise setting that ties it exclusively to the Rails application. If the Rails application is successful, then much of the application’s value derives from the integrity of the data that has been stored. Other applications, sometimes implemented in other languages, may be built on top of that database.

By pushing a code smell into the database, we’re forcing all future developers, not just Rails developers, to deal with the compromised usefulness of NULL. We may very well hear this from some future Python developer, “Jeez. Those Rails dweebs were amateurs. This wouldn’t have happened if they’d used Django.”

We should definitely deal with this problem. But first, how does it happen?

The application allows users to enter data via forms. Upon submission, Rails collects all submitted values into the standard params hash that is made available to controllers. Any form field that is a text field or text area will be assigned the empty string as a value. the following controller code perpetuates the empty string into the database:

   Item.create!(params[‘item’])

Whoa. So I can hear you asking: “So this is a Rails problem?”

Yes. It is a Rails problem, and one that in my humble opinion should never have slipped through the cracks.

But we still need to correct it in our application. So, Robb and I started researching possible solutions.

The best solution we came across was from Henrik Nyh, a Ruby developer in Stockholm, Sweden. He published an excellent code snippet on GitHub’s gist sub-site. This is a site at gist.github.com that allows developers to publish short snippets of code that solve problems.

His code is a mix-in module that updates ActiveRecord’s write_attribute method to properly handle empty strings.

   module NullifyBlankAttributes

      def write_attribute(attr_name, value)
         new_value = value.presence
         super(attr_name, new_value)
      end

   end

Note the use of the presence method, which takes an argument and returns either the argument itself or nil if the argument was blank.

Now what? What do we do with the module?

First, drop the module in the lib directory of the Rails application. Second, create an initialization file in the config/initializers directory of the Rails application. Let’s call it active_record_fixes.rb. The contents of the file will be:

   class ActiveRecord::Base
      include NullifyBlankAttributes
   end

We have just monkey-patched Rails to correct our empty string code smell.

Conclusions

We discovered a code smell in our view code that masked a more pernicous underlying code smell. We got rid of both code smells with the help of a developer from Sweden that we’ve never met.

There are a few lessons to be learned from all this. First, code smells increase the maintenance profile of your application over time, making it more difficult to add new features and maintain existing ones. Code smells are an indication of a coding problem, and should be fixed as soon as feasible, even if the code is functionally working just fine.

Second, when you have a problem, don’t re-invent the wheel. We’re an international coding community. Somebody may very well have solved the problem already. Spend some time researching using Google in case somebody’s already developed a solution. In this case, Henrik solved the problem nicely a few years ago.

Finally, give back to the community. If you solve a problem that might reasonably impact others in the community, post a solution. Write a blog entry (as I have done). Or post a code snippet on gist.github.com, or answer a question posed on sites like Stack Overflow. Coding is hard enough as it is. Let’s share some solutions to make it easier on all of us.

Reception

This article was well received and generated a number of excellent comments. Since I don’t have a way of porting them in smoothly from the old website, I’ve included snapshots of the comments…

First Batch of comments...
Second Batch of comments...
Third Batch of comments...
Fourth Batch of comments...