Securing a Rails app on Passenger with SSL

Posted by Brian in Howto, Rails, tips, web (July 24th, 2012)

Configuring a site for SSL is simple once you understand the process. Unfortunately I don’t set these up all that often so I forget. In my book Web Development Recipes I cover how to set up the certificates on the Apache server, but I don’t explicitly show how to make it work with a Rails application. So here’s how I usually set things up.

Assume we have a Linux-based server running Ubuntu (either 10.04 or 12.04), we keep our sites in /var/www and we will define our virtual host in the file /etc/apache2/sites-available/mysite

We want to make sure all HTTP requests go to HTTPS. To do that, we need to set up security for the site *and* add a redirect, either at the application level or at the server level. Many folks will recommend using Rack:SSL, but I’m just going to let Apache take care of it for me.

To make all this work we’ll need to enable two Apache modules; ssl and rewrite. The rewrite mod may already be enabled so you should scan your /etc/apache2.conf or your other configs for it.

To enable the mods, we use the a2enmod command:

$ sudo a2enmod ssl
$ sudo a2enmod rewrite

Next we need to modify the site definition in /etc/apache2/sites-available/mysite so it uses SSL and our certificates. First we’ll change the host for HTTP on port 80 so it redirects traffic to the secure site, like this:


  ServerName myapp.example.com
  RewriteEngine On
  RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=permanent]

I’m using named virtual hosts here, so this rewrite only applies to myapp.example.com and none of the other sites I may have set up.

In the same file, we add the definition for the secure site on port 443, the default SSH port. This contains all the info that Passgener needs to spawn the site.


  ServerName myapp.example.com
  DocumentRoot /var/www/myapp/current/public
  
    AllowOverride all
    Options -MultiViews
  

  SSLEngine on 
  SSLOptions +StrictRequire 
  SSLCertificateFile /etc/apache2/certs/myapp.example.com.crt 
  SSLCertificateKeyFile /etc/apache2/certs/myapp.example.com.key 

To make this work, we have to generate the certificate and the key.

We do that by creating the /etc/apache2/certs folder and changing into it:

$ sudo mkdir /etc/apache2/certs
$ cd /etc/apache2/certs

Then we generate our Certificate request which also generates a key.

$ sudo openssl req -new -newkey rsa:2048 -nodes -keyout myapp.example.com.key -out myapp.example.com.csr 

Then we take the csr file and get it signed by the cert admin. Or if we need things secured temporarily, we could
sign it ourselves, knowing that our users will get a nasty warning about unknown certs.

$ openssl x509 -req  -in myapp.example.com.csr \
 -signkey myapp.example.com.key -out myapp.example.com.crt

You really don’t want to go to production with a self-signed certificate though.

Once these files are in the certs directory, we can restart the web server and everything should work as expected.

Sharing Vim configs with Mac and Windows using Dropbox

Posted by Brian in Howto, Programming, Rails (January 27th, 2011)

I’m back to using VIm again, after a few years of working with TextMate on the Mac. VIm is great because it works the same on many different platforms, and I jump from Mac to Windows a lot these days.

I’ve devised a setup that lets me keep almost all of my configuration for VIm on my Dropbox account so I can have the same configuration synchronized on all of the computers I use. Here’s how you do it:

Inital Setup

Of course, I assume you have Dropbox and VIm installed on your Mac and Windows machines. I’m not covering any of that setup in this article.

You need a few folders in your Dropbox to make this work. I find doing this on my Mac the easiest:

mkdir -p ~/Dropbox/dotfiles/.vim/autoload
mkdir -p ~/Dropbox/dotfiles/.vim/backup
mkdir -p ~/Dropbox/dotfiles/.vim/bundles

Next, we’ll create a master .vimrc file in our Dropbox. If you already have one, move it there.

mv ~/.vimrc  ~/Dropbox/dotfiles/.vimrc_main

If you don’t have a good config file, there’s one at the end of this article you can look at. For now, just create a blank file there:

touch ~/Dropbox/dotfiles/.vimrc_main

Next, let’s set up a way to manage plugins, or extensions to VIm.

Pathogen

We’ll use Pathogen.vim to manage our plugins. Pathogen modifies VIm’s load paths and lets us keep our plugins in folders we can easily update.

Download Pathogen.vim from the official site and place it in your Autoload folder.

mv pathogen.vim ~/Dropbox/dotfiles/.vim/autoload/pathogen.vim

vimrc

Now, create a new .vimrc in your Dropbox folder. This will be our normal .vimrc for our macs.

  vim ~/Dropbox/dotfiles/.vimrc_mac

And put this in the file:

call pathogen#helptags()
call pathogen#runtime_prepend_subdirectories(expand('~/Dropbox/dotfiles/.vim/bundles'))
source ~/Dropbox/dotfiles/.vimrc_main

We’re telling Pathogen to load any installed plugins from our Dropbox, and then we’re loading in our vimrc_main file which will contain all of our platform independent configuration.

Now, symlink that to your home directory so VIm will find it.

ln -s ~/Dropbox/dotfiles/.vimrc_mac ~/.vimrc

And symlink your .vim folder so everything else you put there gets loaded as well:

ln -s ~/Dropbox/dotfiles/.vim ~/.vim

Now we’re ready to set up the Windows side of things.

Windows setup

Since Windows has no symlink support, you’ll need to create a couple of empty stubs. You’ll need a _vimrc file and a _vimfiles folder in your Home directory.

First, from a command prompt, create a _vimfiles folder

   mkdir %HOMEDRIVE%%HOMEPATH%\vimfiles

And an autoload folder

   mkdir %HOMEDRIVE%%HOMEPATH%\vimfiles\autoload

Then copy pathogen.vim into that folder from your dropbox

   cp "%HOMEDRIVE%%HOMEPATH%\My Dropbox\dotfiles\.vim\autoload\pathogen.vim" %HOMEDRIVE%%HOMEPATH%\vimfiles\autoload\pathogen.vim

Create the file %HOMEDRIVE%%HOMEPATH%_vimrc

  vim %HOMEDRIVE%%HOMEPATH%\_vimrc

Add this to the file:

call pathogen#helptags()
call pathogen#runtime_prepend_subdirectories(expand('c:\My Dropbox\dotfiles\.vim\bundles'))
source c:\My Dropbox\dotfiles\.vimrc_main

This is nearly identical to the file on our Mac, but it instead specifies the paths to the vim bundles folder and vimrc_main files in our Dropbox. Change those paths to the ones for your Dropbox installation!

Environment Variables and Path

At this point, you should set a HOME environment variable, as Windows doesn’t yet ship with that variable set by default (although it does have HOMEDRIVE and HOMEPATH variables.) Many VIm plugins use the HOME environment variable, and things might break down if you don’t have one set. You can set the HOME environment variable to %HOMEDRIVE%%HOMEPATH%.

Next, you should ensure that VIm is on your system PATH so you can access it from the commandline.

You typically set both of these environment variables through the Control Panel.

  1. From the desktop, right-click My Computer and click Properties.
  2. In the System Properties window, click on the Advanced tab.
  3. In the Advanced section, click the Environment Variables button.
  4. Finally, in the Environment Variables window, highlight the Path variable in the Systems Variable section and click the Edit button. Add the path to gvim.exe to this list, keeping in mind that each different directory is separated with a semicolon.
  5. Next, create a new environment variable called HOME, and give it the value %HOMEDRIVE%%HOMEPATH%

Plugins

Many of the most awesome plugins for VIm are now maintained in Git repositories stored on Github. If you have Git installed on your Mac, which you can do quickly with the Mac OSX installer, you can clone each plugin’s repository right into your vim/bundles folder and Pathogen will load them right up.

Here’s what I use:

  • Rails.vim gives me support for Rails development
  • The Cucumber and HAML bunldes provide syntax support for their respective languages.
  • The NERDTreee plugin gives me a project tree which is absolutely necessary when working on anything substantial.
  • The closetag plugin lets me close any open HTML tags by pressing CTRL+_, and since I work in HTML and XML a lot, it’s a lifesaver when you’re several levels deep in a hierarchy.
  • I’m using the VividChalk color scheme, which I love.


cd ~/Dropbox/dotfiles/.vim/bundle
git clone git://github.com/tpope/vim-rails.git
git clone git://github.com/tpope/vim-cucumber.git
git clone git://github.com/tpope/vim-haml.git
git clone git://github.com/tpope/vim-endwise.git
git clone git://github.com/scrooloose/nerdtree.git
git clone git://github.com/scrooloose/nerdcommenter.git
git clone git://github.com/tpope/vim-surround.git
git clone git://github.com/vim-scripts/closetag.vim.git

For suggestions on other plugins, see Tammer Saleh’s blog post on the topic, which is very helpful.

A .vimrc_main config file

Remember the .vimrc_main file we created in the Dropbox? You’ll put all of your common configuration in that file. Here’s what’s in mine, if you’d like a starting point. I’ve pulled this from so many sources I can’t even remember where everything came from, but I have found that peeking at other people’s VIm files is really helpful.

A couple of important points about this configuration:

  1. The mapleader key is set to the comma, and I’ve set it so that the NERDtree plugin can then be toggled with ,d when you’re in normal mode.
  2. I’ve set soft tabs to two spaces.

It’s not an amazing configuration by any means, but it does the job for me.

Wrapping Up

There are a ton of steps to this process, but once you’ve gone through it, you can easily work on code on any configuration. And you can install Dropbox on Linux, too, so you could expand this over to that platform as well.

Share your comments and suggestions. I’m always looking for new VIm tips.

Learning Clojure – Baby Steps Towards Readable Code

Posted by Brian in Clojure, Howto, Languages (October 29th, 2010)

One thing that keeps me coming back to trying to learn Clojure is the way the language forces me to think about problems in a different way. To illustrate that, I thought I’d share a simple problem and solution with you.

The sales tax on items where I live is 5.5%. 5% goes to the state of Wisconsin, and the other .5% goes to Eau Claire county. So, given a price, let’s compute the total amount owed by the customer. Most programmers have done this simple problem enough. We know that the math is basically this:

price + (price * 0.055)

Let’s break down what we know about Clojure and write this expression.

First, we know we can add two numbers together like this:

(+ 4 4)

And we know we can multiply things like this:

(* 4 4)

So by combining those concepts together, we could define our function like this:

(defn total [price] (+ price (* price 0.055)))

That works, but let’s make it more expressive.

In Clojure, things like + and * aren’t just traditional operators. They’re functions, and the parameters we pass in can also be functions.

So if we made a function that computed just the sales tax for Wisconsin at 5%:

(defn wi_tax [price] (* 0.05 price))

and another function that computed the tax for Eau Claire county at 0.5%

(defn ec_county_tax [price] (* 0.005 price))

then we can simply add the results of those two functions together with the price to get our result.

(defn total [price] (+ price (wi_tax price) (ec_county_tax price)))

When we call

(total 5)

we see that we end up with a total of 5.275 for our total price. More importantly, we’ve written readable code.

Looking into the problem more, we see we’ll need to round the number up to the nearest hundredth. Also, this illustrates how we can make better use of functions, but this code doesn’t seem to be very maintainable in its current form. There are 72 counties in Wisconsin, each with their own value for taxes. But I’m sure Clojure has a nice way of handling things like that.

Baby steps, for now.

How to Survive a Live Coding Demo Without a Projector

Posted by Brian in Accessibility, Howto, Public Speaking, tips (October 10th, 2010)

I love to turn bad situations into opportunities to help others learn. This morning I gave a talk at Twin Cities Code Camp on “Building Mobile Apps with HTML5 and Web Standards”. The talk had a slide deck, but was mostly designed to be a follow-along live demo. When I went in to give the talk, the projector system was locked down. According to my feedback, the talk still worked very well, thanks to the preparation I did beforehand to accommodate for things like this. Hopefully this advice will help you if you’re preparing for a talk in the future.

My slides for the talk are online here. The code is on Github.

Practice Writing and Drawing

I have horrible handwriting when I write fast, and when I’m nervous. I teach a lot though and have learned to slow down and think carefully as I write. Having clear handwriting on a whiteboard is really important because you’re going to have to give people URLs to your content. They need to be able to read it at the back of the room, too, so be sure to write big.

Learn to carefully draw simple shapes that resemble things you’d show on-screen. In my talk, I drew the interface elements we’d be creating and was able to show how they’d look.

Have a live copy people can see

Make the finished product available on your website so people can play with it. If you’re building a web site, provide the URL to the demo version. If you’re demoing an iPhone or Android app, have a link to a video that people can watch that shows the app in action if you can’t get access to put the app on the App store. This helps people see what’s in your head (and on your screen.)

Make a PDF of your slide deck!

If you use Keynote or PowerPoint, or even SlideDown, convert your slides to PDFs. Include presenter notes in your export so that people will have more context as they’re reading along. If you don’t make use of presenter notes, you should start. They can help you when you present, but they can also help jog memories later when people look at your slides at work.

Protip: Presentation Remote for iPhone will let you see the presentation notes in your hand. You can control the slideshow with it as well.

Use Git and Github for your examples

Lately I’ve been using Git branches to stage my code examples. For my talk on HTML5 mobile apps, I started out with a new branch like this:

git init
git checkout -b 01_simple_form

Then I’ll do all the work for the first stage, commit it, and make a new branch for the second stage. In this talk, the first branch was just the HTML for the user interface. The second branch then covered the JavaScript we used to create the database on the client machine.

git add .  
git commit -m "Web form"
git checkout -b 02_create_database

By the time I’m done, I have several branches in the repository that I can use to track the stages of my live demo. At the end, I merge my last branch into the Master branch.

git checkout master
git merge 09_offline

Protip: If I realize that I made a mistake, I can check out the earlier branch, fix the code, commit the code, and merge that fixed branch forward into the branches that followed.

git stash      # puts your in-progress work aside
git checkout 01_simple_form
# fix changes
git commit -am "fixed the form"
git checkout 02_create_database
git merge 01_simple_form
git checkout 03_add_note
git merge 01_simple_form 
git stash apply # put your stuff back

Once I’m ready, I create the new Git repository and push my code. I have to push the master branch and the other branches too.

git remote add origin git@github.com:napcs/html5_offline_notes.git
git push origin master
git push origin 01_simple_form
git push origin 02_create_database
git push origin 03_add_note
..

So how does this help me during a talk? I can direct people to the Github page and they can use the Select branch section to see each branch. The Github web interface lets them follow along as I talk about the code. That’s what I did here.

Git advantages
Uploaded with Skitch!

Be ready offline

As a last resort, take this git repository and your PDF presentation and make it available on a thumb drive, or fire up a local wifi hotspot and run a server. An iPad, iPhone, or iPod Touch with Air Sharing can help with this.

Wrapping Up

So, that’s how I’ve done preparation for my talks and managed to make it through a code-centric talk with just a whiteboard. Do you have any suggestions on what you would do?

Reordering Records with acts_as_list and Metaprogramming

Posted by Brian in Howto, Metaprogramming, Rails (May 28th, 2010)

Using acts_as_list, you can reorder items by adding a “position” column to your database and then easily sort records.

  class Project < ActiveRecord::Base
     acts_as_list
  end
  
  class Task < ActiveRecord::Base
     acts_as_list
  end
  

The acts_as_list plugin also provides you methods to manipulate the position.

  • @project.move_to_top
  • @project.move_to_bottom
  • @project.move_higher
  • @project.move_lower

In a current project, I have multiple items that need reordering, which means I'd be duplicating a lot of controller actions and other code across my controllers and views. I'll show you how I used metaprogramming to significantly reduce that duplication.

The Route To Reordering

First, we need some routes. Add this to your routes.rb file:

  %w{projects tasks}.each do |controller|
    %w{move_higher move_lower move_to_top move_to_bottom}.each do |action|
      instance_eval <<-EOF
        map.#{action}_#{controller.singularize} "#{controller}/:id/#{action}", {:controller => "#{controller}", :action => "#{action}"}
      EOF
    end
  end

We use an array of controllers, then we have another array of the four actions, and we just make the named routes. This generates

    move_higher_project        /projects/:id/move_higher                            {:action=>"move_higher", :controller=>"projects"}
      move_lower_project       /projects/:id/move_lower                             {:action=>"move_lower", :controller=>"projects"}
     move_to_top_project       /projects/:id/move_to_top                            {:action=>"move_to_top", :controller=>"projects"}
  move_to_bottom_project       /projects/:id/move_to_bottom                         {:action=>"move_to_bottom", :controller=>"projects"}

        move_higher_task       /tasks/:id/move_higher                            {:action=>"move_higher", :controller=>"tasks"}
         move_lower_task       /tasks/:id/move_lower                             {:action=>"move_lower", :controller=>"tasks"}
        move_to_top_task       /tasks/:id/move_to_top                            {:action=>"move_to_top", :controller=>"tasks"}
     move_to_bottom_task       /tasks/:id/move_to_bottom                         {:action=>"move_to_bottom", :controller=>"tasks"}

Metaprogramming really cuts down on work when you use it correctly. This turns out to be a pretty nice way of generating route patterns that share common attributes.

Keep The Control Centralized

Now let's step it up a notch. Each controller is going to need the four reordering methods. The logic will be identical except for the object they work on and the URL they redirect to when they're finished.

Let's create a module that adds controller methods to match these routes. We'll add it into our controllers where we need it.

Create the file lib/reorder_controller_actions.rb:

  module ReorderControllerMethods

      %w{move_higher move_lower move_to_top move_to_bottom}.each do |action|
        define_method action do
          klass = self.class.name.split("::").last.gsub("Controller", "").downcase.singularize.camelize.constantize
          item = klass.find(params[:id])
          item.send(action)
          flash[:notice] = "The #{klass.to_s} was reordered."
          redirect_to :action => "index"
        end
      end
  end

That module defines four controller actions and calls the corresponding method on the model, then does a redirect back to the index action. It'll be the same everywhere I use it, so I also gain consistency with metaprogramming.

We need to add this to the bottom of config/environment.rb so that our controllers can make use of it.

  require 'reorder_controller_methods'

Then, in each controller where we need this module, we mix it in with include

class ProjectsController < ApplicationController
  include ReorderControllerMethods
end

class TasksController < ApplicationController
  include ReorderControllerMethods
end

Stop and REST for a second

Is it appropriate for me to do it this way? I'm going to argue that while technically the position of something could be sent to the update action, I want specific redirection and notification to occur when I change the order of elements. The logic was getting too nasty in the update action, so I split each thing apart, so I went with this approach instead.

An Improved View

Next, we need some buttons for our index pages with arrows on them so the user can trigger the ordering. How about a simple helper that can generate all four buttons for us?

  def reorder_buttons(object)
    thing = object.class.name.camelize.downcase
    result = ""
    [
      {:action => "move_higher", :label => "↑"},
      {:action => "move_lower", :label => "↓"},
      {:action => "move_to_top", :label => "↑↑"},
      {:action => "move_to_bottom", :label => "↓↓"}
    ].each do |item|    
      result << button_to("#{item[:label]}", send("#{item[:action]}_#{thing}_path", object) )
    end
    result
  end

We use an array hold the buttons. We use hashes within the array to map the action to the label of the button. We then iterate and generate buttons for each one, concatenating to a string that we then return.

Then in our index views, we just need to call this:

  <%=reorder_buttons @project %>

That generates exactly what I need - four buttons, one for each reordering action.

Wrapping Up

This solution easily allowed me to add reordering to a lot of controllers in only a few minutes. Hopefully it will help you do the same. You could improve this by storing the methods in a constant so that you didn't have to duplicate the array all the time, and I'm sure there are other improvements that I could make as well. I'd love to hear from you.

Making “as_string” Attribute Readers for ActiveRecord

Posted by Brian in Howto, Metaprogramming, Rails, tips (March 15th, 2010)

Occasionally, I need to transform boolean model attributes like “active” to display “active” or “inactive” instead of “true” or “false” when making reports or views. A lot of times this means writing some kind of helper method like this:

def active_or_inactive(object, true_message, false_message)
  object.active ? true_message : false_message
end

and calling it like this:

  <%= active_or_inactive(@project, "Active", "Inactive" %>

That’s not a bad approach, and it helps keep the views slightly cleaner by keeping the logic out, but it ends up being more characters than simply using a ternary operator in the view. I’ve used a slightly different approach in some of my more recent projects and I thought I should share it with you.

Move It To The Model

That’s right, I’m advocating pushing that helper into the model itself. I can hear you now, yelling something about “this guy doesn’t know what he’s talking about! How dare he put display logic in his models!” But before you close your browser, allow me to explain.

It just so happens that I need this logic not only in my views, but in my text-based reports that I run outside of the web server. I could mix the module with the helpers in when I needed it, but there’s also something un-object-oriented that bugs me about helpers. They remind me of PHP a bit. I feel like I should be calling object.active_as_string("Active", "Inactive") instead. So that’s what I’m going to do.

First, a unit test, because we’re all good professionals that write tests first. I want to call a method called active_as_string which takes two parameters – the string to print when it’s true and the string to print when it’s
false. Here are my tests:

require 'test_helper'

class ProjectTest < ActiveSupport::TestCase

  test "should display 'Active' if active" do
    p = Project.new(:active => true)
    assert_equal p.active_as_string("Active", "Inactive"), "Active"
  end

  test "should display 'Inactive' if not active" do
    p = Project.new(:active => false)
    assert_equal p.active_as_string("Active", "Inactive"), "Inactive"
  end
end

Tests help me design the method’s use up front. With two failing tests as my guide, I can now take my first stab at making the method work:

class Project < ActiveRecord::Base
   def active_as_string(true_message, false_message)
      self.active ? true_message : false_message
   end
end

With that implemented, my tests pass. However, I also have a "closed" boolean I need to handle, and it would also be nice if I could display "No description" if a project's description was blank. I could write my own _as_string methods like I've done already, but instead, I'll do a little metaprogramming to generate what I need.

Let's add four more test cases - to test the "closed" and the "description" fields.

  test "should display 'Closed' if closed" do
    p = Project.new(:closed => true)
    assert_equal p.closed_as_string("Closed", "Open"), "Closed"
  end

  test "should display 'Open ' if not closed" do
    p = Project.new(:active => false)
    assert_equal p.closed_as_string("Closed", "Open"), "Open"
  end
  
  test "should display 'No Description' if description is nil" do
    p = Project.new(:description => nil)
    assert_equal p.description_as_string("No Description"), "No Description"
  end

  test "should display the description if it exists" do
    p = Project.new(:description => "Hi there!")
    assert_equal p.description_as_string("No Description"), "Hi there!"
  end

Now, let's build some methods!

ActiveRecord::Base.columns

Every ActiveRecord class has a class method called columns that returns a collection of column objects. The Column object describes each database column and lets you determine its type and its name. We can use that and class_eval to generate a whole bunch of methods at runtime.


class Project < ActiveRecord::Base
  self.columns.each do |column|

    if column.type == :boolean

      class_eval <<-EOF

        def #{column.name}_as_string(t,f)
          value = self.#{column.name}
          value ? t : f
        end

      EOF

    end
  end
end

In this example, we're creating the _as_string method for each boolean column. It takes two parameters and is basically the same code we already used in our original method earlier. Notice how class_eval can do string interpolation using Ruby's #{} syntax. That makes it easy to build up the method names.

We can use that same concept to do the same for any other methods - we'll just cast them to strings and check to see if they are blank.

  class_eval <<-EOF

    def #{column.name}_as_string(default_value)
     value = self.#{column.name}.to_s
     value.blank? ? default_value : value
    end

  EOF

We throw that into the else block and our whole example looks like this:

  class Project < ActiveRecord::Base
  
    self.columns.each do |column|
    
      if column.type == :boolean
      
        class_eval <<-EOF
        
          def #{column.name}_as_string(t,f)
            value = self.#{column.name}
            value ? t : f
          end
          
        EOF
        
      else
      
      class_eval <<-EOF
      
          def #{column.name}_as_string(default_value)
           value = self.#{column.name}.to_s
           value.blank? ? default_value : value
          end
          
        EOF
        
      end
      
    end
  end

If you run your tests now, they all pass. But our work isn't done - this isn't very DRY. We may want to use this in another class too.

Modules!

Create a new module and mix the behavior into your models. Create the file lib/active_record/as_string_reader_methods.rb (create the active_recordfolder if it doesn't exist already) and put this code in the file:

  module ActiveRecord
    module AsStringReaderMethods
     def self.included(base)
       create_string_readers(base)
     end

     def self.create_string_readers(base)
      base.columns.each do |column|

         if column.type == :boolean

           class_eval <<-EOF

             def #{column.name}_as_string(t,f)
               value = self.#{column.name}
               value ? t : f
             end

           EOF
         else

           class_eval <<-EOF

             def #{column.name}_as_string(default_value)
               value = self.#{column.name}.to_s
               value.blank? ? default_value : value
             end

           EOF
         end
       end
     end
    end
  end

It's mostly the same code we had before, but in this case we're using the self.included method to trigger the method creation on the model that includes the module.

Now, remove the code from your Project mode and replace it with

include AsStringReaderMethods

Run your tests, and everything should pass. You now have a module you can drop into your projects and you'll have this functionality yourself. Now it's up to you to expand upon this, and use this pattern in your own work if you find it useful.

Good luck!

Rails and SQL Server – “There is no text for object”

Posted by Brian in Howto, Rails, tips (February 23rd, 2010)

I recently moved a Rails application to a new SQL Server 2005 server on a recent project and everything seemed to go smoothly, but when I tried to fire up a connection to the database from my Rails application, I was greeted with

ActiveRecord::StatementInvalid: DBI::DatabaseError: 42000 (15197) [FreeTDS][SQL Server]There is no text for object 'people'.: EXEC sp_helptext people

The “people” table here is actually a view that gets used all over the place in multiple applications. The DBA had moved the databases from an older SQL Server 2000 database previously.

The solution was to ensure that the application’s user account had the “view definition” permission on the view in question as well as the “select” permission. On the view, in the SQL Server Management Studio, right click and choose “Properties”. Then choose Permissions select your user account, and then select the “View definition” permission. Checking the box under the “Grant” column was enough for me to make it work.

Interestingly enough, the production server (which was upgraded months ago from SQL Server 2000 to 2005), does not have the permission set, but still works fine.

Hopefully someone else finds this useful.

Autocomplete forms in Rails 2.3.3

Posted by Brian in Howto, Rails (August 28th, 2009)

When Rails 2 was released, the core team dropped some of the Javascript Ajax helpers like in-place editing and autocompleting, and released them as plugins. However, if you’ve ever tried to use them with a modern Rails application, you may have encountered problems with routing and authenticity tokens. In this brief post, I’ll walk you through a trivial example that shows how to make Autocomplete work, using the advantages that Rails 2.3 has, including format responses.

First, let’s get a basic Rails app running with a Projects table with a single field, the project’s name :

 rails autocomplete
 cd autocomplete
 ruby script/generate model project name:string
 ruby script/generate resource projects
 rake db:migrate

Next, let’s load some test data.

 ruby script/runner "
 ['The Ninja project', 'The Top Secret project', 'World Domination'].each do |p|
    Project.create(:name => p)
 end
 "

Grab the autocomplete plugin from Rails’ Github repository and install it as a plugin:

 ruby script/plugin install git://github.com/rails/auto_complete.git

Our basic app is installed, but we need to implement a controller action to display projects.

Open app/controllers/projects_controller.rb and add this method:

  def index
    @projects = Project.all :limit => 10
    respond_to do |format|
      format.html
    end
  end

When the user requests HTML, we’ll show the last 10 projects created. Good enough for now. Let’s implement the layout and the view.

Open app/views/layouts/application.html.erb and build a very simple layout:


  
    Autocomplete
    <% =javascript_include_tag :defaults %>
  
  
  
    <%= yield %>
  


This very basic layout loads the default Javascript fiels for Rails and yields the template.

Now open app/views/projects/index.html and add this code:


<% if @projects.any? %>
    <%=render @projects %>
<% else %>

There are no projects to show.

<% end %>

Here we have a list of projects, and when we click the submit button, we’ll filter the results. We’re using render here, and when you pass the render helper a collection, it looks for a partial that it can use render each of the elements in the collection.

Create app/views/projects/_project.erb and add this line:

  • <%=h(project.name)%>
  • Now we have to do the filtering in the controller. Since the search box is simply applying a filter to the list of projects, it makes sense for us to use the index action for the request. This means changing the controller’s index action slightly.

    def index
      keyword = params[:query]
      if keyword.present?
        keyword = "%#{keyword}%"
        @projects = Project.all :conditions => ["name like ?", keyword], :order => "name asc", :limit => 10
      else
        @projects = Project.all :limit => 10, :order => "created_at desc"
      end
      
      respond_to do |format|
        format.html
        format.js do
          render :inline => "<%= auto_complete_result(@projects, 'name') %>"
        end
      end
    end
    

    If the query parameter comes in, then we want to filter. We build up a LIKE query and get the results. If no query parameter is present, we just get the top ten recent projects.

    However, this is really messy. Let’s get that search logic out of the controller.

    Open app/models/project.rb. Move the search logic into a new method:

    def self.find_all_by_keyword(keyword)
      if keyword.present?
        keyword = "%#{keyword}%"
        @projects = Project.all :conditions => ["name like ?", keyword], :order => "name asc", :limit => 10
      else
        @projects = Project.all :limit => 10, :order => "created_at desc"
      end
    end
    

    Now change app/controllers/projects_controller.rb to call the method instead of doing the search:

    def index
      @projects = Project.find_by_keyword(params[:query])
      respond_to do |format|
        format.html
        format.js do
          render :inline => "<%= auto_complete_result(@projects, 'name') %>"
        end
      end
    end
    

    Much better. At this point you have a non-Javascript search for your projects in a very short time.

    Let’s add the autocomplete functionality. First, in the view, change the text field to this:

    <%= text_field_with_auto_complete :project, :name, 
        { :name => "query" },
        {:method => :get, :url => projects_path(:format => :js) } %>
    

    This sets up the autocomplete field to send its queries to our index action, but specifies that we should use the “js” format, perfectly appropriate for this, as it’s a Javascript-only request, so we should provide our response with Javascript.

    Open the controller and modify the controller’s code so it looks like this:

    def index
      @projects = Project.find_all_by_keyword(params[:query])
      respond_to do |format|
        format.html
        format.js do
          render :inline => "<%= auto_complete_result(@projects, 'name') %>"
        end
      end
    end
    

    The only real change is adding the format.js block of code. Here, we’re using Rails’ inline renderer which renders ERb code. Within that ERB, we’re calling the auto_complete_response helper provided by the autocomplete plugin to render the specially formatted list that the auto compelte text field expects. We’re using inline rendering here, but you could use a view with the .js extension. Since it’s one line, I’ll save the file I/O.

    With the responder in place, the autocomplete should start working. This is a pretty simple example, but it does illustrate how to make the autocomplete plugin work in a current Rails application, without working about

    Saving without callbacks

    Posted by Brian in Howto, Rails, tips (August 19th, 2009)

    Occasionally, you need to do something to a model without invoking callbacks. This is especially necessary for instances where you need to modify the record you just saved in an after_save callback. For example, say you want to create a hash based on the record’s ID. You won’t have the ID until after it’s been saved, and if you call self.save in an after_save callback, you’re going to end up in an endless loop.

    It turns out that ActiveRecord has two private methods.

    create_without_callbacks

    and

    update_without_callbacks

    Remember that private in Ruby is less about keeping you from calling the methods and more about letting you know that you shouldn’t depend on them. With Ruby’s send method, using either of these in your application is easy.

    Note that in Ruby 1.9, send doesn’t allow calling private methods, but send! does.

      class Project < ActiveRecord::Base
        after_save :create_hash_from_name_and_id
    
        private
          def create_hash_from_name_and_id
            self.hash = Digest::SHA1.hexdigest("#{self.id}#{Time.now.to_s}#{self.name}")
            self.send :update_without_callbacks
          end
      end
    

    It's my opinion that these methods should not be private. If I can skip validations with save(false), then I should be able to skip callbacks as well.

    There are other patterns you can use to skip callbacks.

      class Project < ActiveRecord::Base
        attr_accessor :skip_callbacks
    
        with_options :unless => :skip_callbacks do |project|
          project.after_save :create_hash_from_name_and_id
          project.after_save :do_more_stuff
        end
    
        private
          def create_hash_from_name_and_id
            self.skip_callbacks = true
            self.hash = Digest::SHA1.hexdigest("#{self.id}#{Time.now.to_s}#{self.name}")
            self.save
          end
      end
    

    So there you go. Go forth and skip callbacks at will.

    Using a class method with or without named scopes

    Posted by Brian in Howto, Rails (August 17th, 2009)

    Here’s a quick one, building off of the previous post on Geokit and Named Scopes.

    If you have defined a class method you want to run which operates on a collection of records, you can share it with named scopes.

    class Project < ActiveRecord::Base
      validates_presence_of :name
      named_scope :completed, :conditions => {:completed => true}
    
      # returns array of names for projects
      def self.names
        scope = self.scoped({})
        scope.all.collect{|record| record.name}
      end
    end
    

    This allows you to do

    @project_names = Project.names
    

    Or

    @project_names = Project.completed.names
    

    If you return the scope, you can continue chaining. If you don’t return the scope, then you can’t. This comes in handy though for creating a method that returns other objects than the object you’re working with. Here’s a completely contrived example:

    Say you want to find the actual hours you’ve spent on all your completed projects:

    class Project < ActiveRecord::Base
      named_scope :completed, :conditions => {:completed => true}
      
      def self.tasks
        tasks = []
        self.scoped({}).all.each do |project|
          tasks += (project.tasks)
        end
        tasks
      end
      
      def self.actual_hours
        hours = 0
        tasks.each do |task|
          hours += task.hours
        end
        hours
      end
    

    Grab the value like this:

    actual_hours = Project.completed.actual_hours
    

    Now, of course there are other ways to do this, and this particular method will result in a lot of queries. If you were doing this hours counting in a real app, you’d be better off using SQL. This example illustrates the point though. Now go build something more awesome.

    Next Page »