validates_acceptance_of howto 1

Posted by ch0wda on November 16 2007 at 09:24 AM

We’re really getting things rolling on Gonowdo and as part of that, we’re starting to accept users on a somewhat limited basis. When signing up, I need to make sure that users accept our terms of service. With Rails, this is extremely simple, but after spending a few minutes on mailing list archives and forums I didn’t find a good resource or howto. Hopefully, this post will serve as that for anyone in the future.

The key to accomplishing this is to use an active record validation called “validates_acceptance_of”. Adding this to the User model with a method will create a virtual attribute for that named method, in my case, I used “terms_of_service”. There is no corresponding column in the database needed. This will not allow a model to be saved without it. By default, this method will allow the record to be saved if it is nil. Setting it to true will mean that you must pass this value to the record everytime you want to save it. One other thing, in order be able to access this method from the view, you need to make it accessible by creating an accessor. Here is the example from our application.

1
2
3
4
5
6
7
8

  class User < ActiveRecord::Base
    # ...
    validates_acceptance_of :terms_of_service
    # ...

    attr_accessible :terms_of_service
  end

In the view, you just need to add a control to the form for selecting this checkbox. Without checking this box, the form will throw a validation error and the model will not be saved.

1
2
3
4
5
6

  <% form_for :user, @user, :url => users_path do |f| %>
    <p>... other controls ...</p>
    <p><%= f.check_box :terms_of_service %> I accept the terms of service.</p>
    <p><%= submit_tag "Save" %></p>
  <% end %>

There are several other configurations that you can pass to validates_acceptance_of, similar to other validations. Check the documentation for this method for more information. If you have more stringent auditing requirements, then you may need to think about just using a boolean field in the database and using a regular validation. Extending this further might even allow you to track acceptance of versions of your terms of service as they get updated. Since we’re allowing nil by default, you will need to make sure that create a test/spec to specifically pass a :terms_of_service method. I would keep this in a special test case and not worry about including it throughout your test suite.

Hopefully, this will get you going, best of luck!

Emacs Autotest Integration

Posted by ch0wda on September 18 2007 at 10:30 AM

I’ve been read in several places about how to get emacs and autotest to play nicely together. This package runs a shell buffer just giving autotest’s output. It’s a nice way to automatically have that visual representation in the same window. It’s actually quite simple to do.

To begin with, you’ll need to download the autotest.el file and also a depencency, toggle.el. From there, I simply added the following to my .emacs file:

  ;; adding autotest integration
  (require 'toggle )
  (require 'autotest)

Restart emacs, and you should be good to go. Note, I also had to add the unit-test.el file, but that wasn’t mentioned anywhere on the wiki.

Navigate in emacs to a the root folder that you want to run autotest in and you can start this mode by typing:

M-x autotest
. Currently, my output is looking a little funny, I think it’s an encoding thing, but I think I can get the kinks worked out pretty soon. Also, make note that this will read the ~/.autotest file to start. A great resource on this nice piece of integration can be found on the emacs wiki.

That’s one less terminal that I’ll have going, meaning that more of my life will be spent in emacs, which is good.

Prototyping with Camping 2

Posted by ch0wda on September 06 2007 at 03:50 PM

As you might know, I’ve been spending a lot of time at work writing some dashboard-type applications using _whytheluckystiff’s Camping Framework. I’ve been experiencing some incredible productivity gains by prototyping with this very small framework, and I think I’m only just beginning to realize exactly how much. I’ve recently undertaken rewriting one of these dashboards in Rails.

The Camping Application

Several months ago, I was tasked with providing some statistics on budget and project management performance for senior management. The maturity of datasources wasn’t very good, many of them were excel spreadsheet laden with macros, access databases, and csv files from 5 or 6 datasources. To further compound the problem, these datasources weren’t always in a consistent data format, so I made the design decision to just create a simple CRUD interface to manually enter the data. All compilation would be handled outside the application for the time being. The benefit of this approach would be that eventually, I could turn the data entry over to someone else.

I developed this solution over the course of about 2 weeks, working on and off until there was a format visually appealing to all parties. I wrote the most basic tests possible using Topfunky’s Mosquito Testing Framework. This solution worked until the application needed to be expanded to the entire organization, not just a subset. It was time to move to Rails.

The Rails Application

In addition to changing the domain to fit the entire organziation, I really wanted to have an extremely clean interface for someone else to enter the data. My goal was to have someone else take over entering the data, and I would just be responsible for the support of the application. Rails also gave me an opportunity to more easily explore automating some of the data entry.

In 2 days, working on it for 8 hours a day, I’m 90% complete, including adding the additional models and unit and functional tests. I realize that it’s a small Rails application, but now if there are enhancement that need to be made I’m on a much better platform.

+----------------------+-------+-------+---------+---------+-----+-------+
| Name                 | Lines |   LOC | Classes | Methods | M/C | LOC/M |
+----------------------+-------+-------+---------+---------+-----+-------+
| Controllers          |   560 |   395 |       8 |      49 |   6 |     6 |
| Helpers              |    20 |    19 |       0 |       1 |   0 |    17 |
| Models               |   152 |   130 |       7 |      18 |   2 |     5 |
| Libraries            |    14 |    11 |       0 |       3 |   0 |     1 |
| Integration tests    |     0 |     0 |       0 |       0 |   0 |     0 |
| Functional tests     |   434 |   342 |      14 |      63 |   4 |     3 |
| Unit tests           |   745 |   565 |       8 |     154 |  19 |     1 |
+----------------------+-------+-------+---------+---------+-----+-------+
| Total                |  1925 |  1462 |      37 |     288 |   7 |     3 |
+----------------------+-------+-------+---------+---------+-----+-------+
  Code LOC: 555     Test LOC: 907     Code to Test Ratio: 1:1.6

So in proper enterprise +3/-3 format, here are some observations…

Eagles

  • My models are almost an exact copy from Camping, with more validations and a couple of additional models that I needed to add for the extra functionality.
  • I already knew the domain of what I needed to create so any reworking could be accomplished on the first pass with Rails.
  • I already had lots of good data to use for Rails development as I just pulled fixtures down from the Camping app.

Turkeys

  • I miss clean view syntax of Markaby in Rails. I realize that I could use Markaby, but if support for this application eventually gets turned over to another group, I thought that the barrier to entry would be lower for the JSP-style syntax of ERB templates.
  • I had to manually copy and paste a lot of code from one Emacs screen to another. There was rumored to be a gem that would transistion a Camping application to Rails, DeCamper, but I couldn’t find any code that had been released. This bears further research.
  • Rails migrations and Camping migrations aren’t very similar, and I wanted to have the cleanest Rails application possible. I reworked the models enough that it just didn’t transfer very well.

Summary

I’ve been in too many situations where I work on things for too long only to have the organziation go in a different direction. Using Camping to prototype before moving on to Rails gets something for my users to react to before I’m too invested in the outcome of my work. When, and if I do need to move to Rails, the transition is seemless and probably cuts down on the total time to get a finished product into production. I’ve been very pleased with this approach, but I think I can reduce the turn around time even further. I think some possible options would be to use ERB with Camping or Markaby with Rails. Also, I think I should have perhaps gone to Rails a few weeks ago, but time was just too hard to come by. The next time you come across a situation that warrants creating something of immediate use that may or may not be thrown away after an initial pass, you should think about this approach.

Emacs Railsy-ness

Posted by ch0wda on April 18 2007 at 12:56 PM

For the most part, I followed the instructions at Dima’s Rails On Emacs page. This worked for the most part, however there were several gotchas that crept up as I was working my way through. Here’s what I did, that might be different than the other tutorials:

  1. I placed the snippets.el and find-recursive.el into the folder that I checked out the Rails on Emacs code. (Perhaps this is what he meant by install, but I originally had them in .emacs.d, and that was wrong.) ruby-inf.el did, however remain in .emacs.d
  2. I reinstalled ruby and installed ruby-elisp from synaptic. I did this because I read that when you install ruby on debian/ubuntu it will automatically install the necessary emacs modes.
  3. Tip After opening emacs, change your buffer to “Messages” it will have all the init information, and I found it very handy for debugging.

I’m also going to install the Emacs Code Browser, which is supposed to provide some parsing of files to show methods, and other view-related functions.

Here’s my .emacs file:
(custom-set-variables
  ;; custom-set-variables was added by Custom -- don't edit or cut/paste it!
  ;; Your init file should contain only one such instance.
 '(standard-indent 2))
(custom-set-faces
  ;; custom-set-faces was added by Custom -- don't edit or cut/paste it!
  ;; Your init file should contain only one such instance.
 '(default ((t (:stipple nil :background "#000000" :foreground "#00ff00" :inverse-video nil :box nil :strike-through nil :overline nil :underline nil :slant normal :weight normal :height 164 :width normal :family "adobe-courier")))))
 ;; this line makes a file executable after saving it
 ;; (add-hook 'after-save-hook 'executable-make-buffer-file-executable-if-script-p)
(setq load-path (cons "~/.emacs.d/emacs-rails" load-path))
(require 'rails)

Resourceful Links

Switching Up My IDE

Posted by ch0wda on April 18 2007 at 10:31 AM

That’s it, I can’t stand the bloat that comes from all things java anymore. I’ve been a pretty religious Radrails user almost since it’s inception. I haven’t been too frustrated with the recent lack of development because it’s done what I need it to do. About 4 months ago, I switched from using Radrails proper to loading it into an existing version of Eclipse as a plugin because I wanted to load some other types of plugins, like one for Erlang support. (Thanks pragprog!) This was serviceable, but since I’m running Ubuntu in a VMWare machine on my laptop I need to conserve all the RAM I can. The JVM for Eclipse currently runs at 86MB when sitting still. Totally unacceptable for my needs.

So, if I’m off the Radrails/Eclipse stack, what should I use? Another popular IDE is JEdit, but since the “J” stands for java, I’m skipping it. I’ve decided to take the time and learn how to use emacs. I love the emphasis on hotkeys and simplicity. Since emacs has been around in some form since 1974, it’s super stable too. It just seems that there is so much more I can do, and quicker too, if I’m just willing to take the time to learn. I am. Plus, there just seems to be some serious street-cred for telling people that you’re an emacs user.

Installation Instructions for Ubuntu Edgy

Since most of the development that I’ll be doing in emacs will be Ruby/Rails related, I’ll want to install Dima’s Rails Emacs minor mode. WARNING: This requires emacs 22, which you’ll either need to compile, or find a package for. There is an Ubuntu package of emacs 22 currently available in the repositories. It’s called emacs-snapshot and the package was built from CVS sources on 20060915, so it’s not the latest sources, but it’s pretty close. Feisty Fawn, which is supposed to release tomorrow (4/19) also has this package, but it’s actually built on 20070407, so very recently. I’ll be upgrading to Feisty soon. Just do the following to install:
sudo apt-get install emacs-snapshot
As a final note, I like to keep all my programming utilities on the Gnome menu together, under the “Programming” heading. The emacs-snapshot package puts menu shortcut in Applications -> Accessories, so it required a little tweaking of the .desktop file. Fire up your favorite editor and edit /usr/share/applications/emacs-snapshot.desktop. Change line that begins with the word Categories to the following to move the shortcut to your Applications -> Programming section:
Categories=Application;Development;

I’ll take you through installing the Rails specific portions next time. Just to give a comparison, Eclipse uses 86MB of RAM just sitting there, while emacs uses only 11MB. I’m looking forward to getting my emacs pinky Why didn’t I switch sooner?

String Includes Enumerable

Posted by ch0wda on February 15 2007 at 07:58 PM

While working on a little side project, I’m using Rails app to do a lot of system calls and grabbing the response of STDOUT or STDERR. One of the things that has made this really easy is that in Ruby, String includes the Enumerable module, which treats the string as an array. This may not be a surprise, except that each item is separated out in the array by a new line character ”\n”. This allows the usage of the “each” method and all 28 other methods that come with Enumerable objects.

Controller:
  def rake
      @rake = `rake -T`
      @tasks = []
      @rake.sort.each { |line|
        @tasks << line.gsub("rake", "")
      }
  end
If you want to iterate over the string character by character then you would have to iterate by byte and show the character value (the each_byte method returns the ASCII character number for the given character. You might do something like this to change all “a” characters to “e” characters:
@rake.each_byte do |b|
  b.chr.gsub(/a/,"e")
end

In Rails, there’s a method called chars” which does some cool things by proxying your string to UTF-8-safe characters.

UPDATED: Dan Manges pointed out that I had a nonsensical example for each_byte.