Friday, August 8, 2014

building a live search feature using Ajax: Part 1 (the model)

I am building a reddit-like social network for Tealeaf Academy's Ruby on Rails course.

Each post on my site describes an online resource. Each post consists of a title, a URL, a brief description, and a list of categories under which the resource falls. Other users may comment and vote on posts.

The categories are created by the users, so they can get numerous. To make navigating through categories easier, I implemented a search feature. A user may have to run many searches before finding the category she wants, and I didn't want to make her click a submit button for every search. Instead, I wanted a "live search", which is run automatically every time the text in the corresponding input element is modified.

I liked building this feature in Rails, because the implementation involves all three parts of the Model-View-Controller pattern, as well as some client-side processing. For the most part, I followed the implementation suggested by Ryan Bates in his Railcasts series. In this post, I will describe the model side of that implementation and comment on a couple of details of ActiveRecord queries.

Model:


On the model side, we need a method on the Category class that will do the actual searching. Here it is. I want to comment on two aspects of this code. The first, not immediately apparent (to me), is that it doesn't actually return an array of Category objects. ActiveRecord query methods, like where and all, generate SQL queries but don't run them directly. Instead, they return an ActiveRecord::Relation object. It is only when a kicker method like each is called on the ActiveRecord::Relation that the records are loaded from the database into memory. This approach, called lazy loading, conserves memory by not loading records until the instant they are needed. It also improves performance by pushing tasks down to the database, which is faster than the Ruby interpreter at things like sorting and summing. For example, generates the following SQL query This is faster than pre-loading all the records and then sorting them in memory.

If we had wanted the opposite of lazy loading, eager loading, we would have called load on the ActiveRecord::Relation returned by where and all. The records would then have been retrieved and stored in an array instance variable on the ActiveRecord::Relation.

The second point I wanted to comment on is illustrated on line 11. That code would also have worked if we had constructed a SQL statement directly and passed it to where However, this is a bad idea, because we would be passing unsanitized user input to the database, leaving it vulnerable to a cross-script injection attack.

In the following posts, I will tackle the controller, view, and client-side parts of my live search implementation.

Saturday, August 2, 2014

Twitter ERD

I was curious if there are tools that can automatically generate entity relation diagrams (ERDs). I found three (schemacrawler, rails-erd, and railroady). In general, however, it doesn't seem like that many people are interested.

In any case, I applied these tools to the mock Twitter (https://github.com/misha354/twitter) that my instructor at Tealeaf Academy is building as a live-coding demonstration. Here are the results:

schemacrawler:




I like the visuals, but the main limitation of this tool is in the name. It only maps the database schema and doesn't know about associations defined at the model layer. In fact, it's pretty smart and can infer associations from table and column names (like the association between mentions and users). But if the foreign key column isn't named after the table it references (like in the relationships-users associations), the association is lost on schemacrawler. In addition, not seeing the model layer, schemacrawler obviously doesn't see indirect associations like leader user -> relationship user -> follower user.

rails-erd:

It appears that this gem is no longer maintained. But it's still up on github. Here is its ERD:


rails-erd does see associations at the model layer, so it shows us that relationships points to the users table and that user has two indirect

Saturday, July 5, 2014

Automatic documentation generation using YARD

I wanted to automatically generate documentation for a blackjack game that I wrote for Tealeaf Academy's Ruby course using Sinatra.

RDoc seems to be the more popular documentation generator for Ruby, but I chose to use another program, called YARD. Here are my reasons:

  • Unlike RDoc, which expects totally free form comments, YARD provides a syntax to specify parameters, return types, and other details and generates consistently formatted output.
  • Using that syntax, it's possible to document a block of code, like a Sinatra route, as a method, even when it's really not.
  • YARD is backwards compatible with RDoc.

Here are the steps I took.

Add the YARD gem to the project

Add to the Gemfile and run

Refactor from classic Sinatra style to modular Sinatra style.

The game was originally written as a classic Sinatra application, meaning that the routes and helpers are defined in the top level namespace (More details), rather than in an application class. YARD documents things in the top level namespace, but doesn't include them in the index, which sort of defeats the purpose of documentation.

To convert a classical application to a modular one, we need to require 'sinatra/base' instead of 'sinatra' and to wrap the application in a class declaration. Then, we change the config.ru file in the root directory. It should now read (assuming the application class is defined in my_app.rb)

Extract helper methods to a module

In a classic Sinatra app, the helper methods are wrapped inside a do-end block. Although YARD can be made to recognize code blocks as methods, it won't recognize a method defined within a code block. To document the helper methods, we need to extract them to their own module.

Document methods and routes

YARD generates hyper-linked html documentation of classes, modules, and methods from Ruby comments. To be processed by YARD, the comments need to follow a specified format.

In general, a line of comments describes some attribute of the code below. Most lines begin with a tag, which starts with an @ sign. The tag specifies the placement and formatting of the text that follows. There are tags for method names and descriptions, parameter and return value names and data types, author names, and many others. Descriptions can be hyperlinked to other descriptions. To document a method, the syntax is This will result in html that renders to something like this.

To document a Sinatra route, we need to use the @overload tag. For example, will document the route as a method named

Generate documentation

Run in the root directory to create the documentation in the /doc folder.

Saturday, June 28, 2014

Sinatra extensions

I have been working on a web-based blackjack game as an assignment for Tealeaf Academy's first course. The program is written in Sinatra, a Ruby based language for web applications.

As the application gets larger, it becomes inconvenient to keep all Sinatra routes and helper methods in the application's main.rb file. The example below shows how to move functionality from main.rb into another file using Sinatra extensions.

One of the first tasks the application performs is to prompt for, read, and save the player's name. The prompt is issued in response to an HTTP GET request, and the input is submitted via a POST. It would be convenient to move the Sinatra routes corresponding to these requests to a file called name_handler.rb.

I create this file in the root directory. In this file, I write a module that contains these routes and register the module with Sinatra. The contents of the file are given below. Note that the routes themselves are defined in lines 10-18.

I then include name_handler.rb in the application by adding at the top of the main.rb file. The routes will now act as though they were defined in main.rb.