Investigating RSpactor
RSpactor is a command line tool for OSX Leopard that does basically the same thing as autotest, which is to re-run your specs any time one of your application files changes.
The reason that it only works on Leopard is the same thing that makes it better than autotest at this point. It uses the filesystem events (FSEvent on Leopard) exposed by RubyCocoa. This makes it much, much faster than using the file notification system used by autotest. It’s saved my MBP fan from spinning up when I go through a development session. Additionally, Growl support is built in so you have very nice notifications available for when your tests pass or fail.
Since I rebuilt the version of Ruby that was included with Leopard, I ended up having to manually install the RubyCocoa libraries. Thankfully though, this was relatively straightforward as well. If you’re running a stock Leopard install, you wont need to do anything other than:
superbia:~ matt$ sudo gem install rspactor superbia:~ matt$ cd /path/to/your/app && rspactor
If you’re using autotest currently and are on OSX Leopard, do yourself a favor and check this tool out.
Has it really been five years?
Five years ago today, I launched this blog as a way to work on my writing skills as well as give back a little to the community that I’ve learned so much from. It’s been a very fun and interesting ride. I’ve much enjoyed being able to provide technical information to my audience.
A recent review of my Google Analytics account showed the following posts as the most popular on this site. Interestingly enough, the single most popular post on this site has no technical nature whatsoever. The rest I’ve noticed are very tactical in nature and are probably a result of having almost 75% of my traffic driven by search engines.
- Escape from the Crimson Room
- Submitting ASP.NET form with the ENTER key
- Date validation in ASP.NET
- Replacing notepad in Windows Vista
- Serializing an IDictionary object
- Windows Vista and the screen saver
- Executing a SQL script using ADO.NET
Over the past five years, I’ve created 757 posts that have generated 1378 comments. I’ve had visits from 183 countries/territories across the globe. This has far surpassed anything that I originally thought would happen with this site. After all, who would want to listen to a geek from Boise, Idaho? My goal for this site for the next five years is to continue to provide technical, how-to information. I’d also like to increase the social aspects of the site and look forward to posting things that cause conversations to occur on this site as well as others.
Here’s to five more years. Thank you to all of my readers. You mean more to me than I can ever express. Keep reading and I will keep writing.
A while back I posted that I didn’t really get Twitter. However, recently, my synapses started firing around this concept. I’m just starting to look at it as a very intriguing public form of instant messaging.
Im mattberther on twitter.com. Drop by and say hello.
Is there anything you need help with?
A daily scrum meeting involves asking each participant of the scrum team three questions:
- What did you do yesterday?
- What will you do today?
- Is there anything in your way?
I’ve found that very rarely do people offer anything to the “is there anything in your way” question. After all, we are all engineers and there should be nothing in our way that we can not solve.
I’ve started asking this question slightly differently. The question I ask now is: “Is there anything you need help with?” I’ve noticed that this question tends to spawn a discussion among the team members much more than the previous question. I am not quite sure why this is, but so far it seems to be working.
How I use Leopard Spaces
OSX 10.5 (Leopard) introduced one feature that has fundamentally enhanced my productivity more than any other tool or feature before. Spaces, for those unfamiliar, are virtual desktops for your computer. The key problem with the initial implementation of Spaces was that the desktops were designed to be centered on the application, rather than on tasks, which is my preference.
With the application-centric focus, I am only able to have one instance of the application open and when I click on the icon in the dock, I’m instantly transported to the space containing that application. However, the way I’ve decided to utilize Spaces (with a task-centric focus), I have a need to have Safari or TextMate open on many different windows.
In Leopard 10.5.2, the doc has some preferences that you can set on the commandline that will not switch spaces when you hit CMD-TAB. Thanks to Mac OSX Hints for the tip.
superbia:~ mattb$ defaults write com.apple.dock workspaces-auto-swoosh -bool NO superbia:~ mattb$ killall Dock
So, my space layout? I have 2 rows of 3 spaces. Email occupies space 1. Feed reading is occupied by space 2. IM and Twitter activity goes on in space 3. Space 4 is my Parallels VM (with 4gb of RAM on my MBP, I can afford to run a Windows VM all the time). Space 5 is occupied with my development tools. Space 6 is open for other things.
I’ve mapped my hot corners with Expose as well. Top right shows my spaces, top left shows windows on the space. Bottom left shows my desktop and bottom right shows the screen saver (or locks the computer).
I really enjoy the Spaces feature and highly recommend some variation of this for people to become increasingly productive with OSX.
Rails applications and 500 errors
The default scaffolding generated for a model has the capability of throwing a number of exceptions, resulting in a 500 level response status being sent to the client. The largest cause of these exceptions is the default behavior of ActiveRecord::Base.find. If find can’t locate a record that matches the user-supplied identified, then the method throws an ActiveRecord::RecordException. Take a look at the default code generated for a controller utilizing a User model.
def show @user = User.find(params[:id]) end
Fairly straightforward, and without looking at any edge cases, it’s very clear, clean and concise code. As you probably expected, Rails created something that lets you easily work around this. The dynamic finder methods do not throw exceptions, rather they return nil if a record is not found. If you haven’t learned about the dynamic finder methods, you should really learn more about them. By rewriting the generated scaffold code slightly, we are able to present a friendly message to the end user letting them know that a record was not found.
def show @user = User.find_by_id(params[:id]) render(:file => ‘public/404.html’, :layout => true, :status => 404) and return unless @user end
As you can see, the render method has the capability of setting the layout, so you can have a nice consistent look and feel across your 404 page, as well as the status code which signifies to the browser that the resource was not found.
This new code is validated by these rspec tests:
describe "Given a request to show an invalid user id" do setup do User.stub!(:find_by_id) get :show, :id => "invalid" end it "should not assign a user" assigns[:user].should == nil end it "should return a status of 404" do response.headers["Status"].should == "404 Not Found" end it "should render a 404 file" do response.should render_template("public/404.html") end end
This little technique will certainly help keep the size of the production log file down as well as present a nice interface to your users should a request for an invalid record id come in.
Capistrano Deploy Error
I was running a deployment using Capistrano earlier and came across a strange error. The error said:
Errno::ENOENT: No such file or directory - /tmp/501/SSHKeychain.socket
This was a puzzling error, but I think I finally traced it back to an installation of SSHKeyChain (which I ended up uninstalling). To fix the error, I ran the following command, after which Capistrano started to work again.
superbia:~ mattb$ unset SSH_AUTH_SOCK
This resolved the problem on my MacBook Pro, running Leopard and Capistrano 2.2.
Providing ActiveRecord validations for non-database models
The validations provided by the Rails framework are very powerful and provide a very easy, no cost way of validating forms prior to submitting them to the database. You might see the validations in a class this way:
class User < ActiveRecord::Base validate_presence_of :name end
If there is not a name entered on the form when creating/updating the user, the save will fail with an error that can be displayed to the user.
I was hoping to leverage this same technique for some other forms that I had in my Rails application. These forms did not have a corresponding model in the database, as they were models that described sending an email. The goal was to provide for some required fields and then check whether or not the form was valid prior to sending the email.
My first pass at this looked like this:
class ContactInformation < ActiveRecord::Base attr_accessor :name attr_accessor :email_address attr_accessor :body validates_presence_of :name validates_presence_of :email_address validates_presence_of :body end
and in the controller:
def send_mail @contact_info = ContactInformation.new(params[:email]) Notification::deliver_contact_form(@contact_info) if @contact_info.valid? # error checking omitted for brevity end
This technique did not work, since ActiveRecord makes a database call to define the accessors when valid? is called. I needed something a little different, so I looked to Google. I found a solution here that almost worked for me. What didnt work for me was that in the first piece of code, the behavior was overwritten for *all* ActiveRecord::Base, meaning that the rest of my application would not have database access with ActiveRecord. The second solution on the page seemed way more complicated than I felt that it needed to be. After all, the first solution worked. Using the first technique, I just needed to find a way to limit scope.
A little Ruby metaprogramming led me to this, which I think is an excellent solution to this problem (which I put in $RAILS_APP/lib/active_form.rb).
module ActiveForm def self.included(base) base.class_eval do alias_method :save, :valid? def self.columns() @columns ||= []; end def self.column(name, sql_type = nil, defaults = nil, null = true) columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type, null) end end end end
Essentially, what we’re doing is using Module.included and Module.class_eval methods to execute code whenever the ActiveForm module is included in another class or model. When the class is evaluated, we alias the save method to the valid method and add a method that allows are model to register columns. This method simply mocks out an ActiveRecord column (without connecting to the database), which basically fools ActiveRecord into thinking there actually is a database table.
The model class is modified slightly from the example above. In addition to including the ActiveForm module, which provides us this functionality, the attr_accessor methods are changed to the column method described above. The model now looks like this:
class ContactInformation < ActiveRecord::Base include ActiveForm column :name column :email_address column :body validates_presence_of :name validates_presence_of :email_address validates_presence_of :body end
The controller code works as I initially had written it. And, I get all the joys of the ActiveRecord validations without having a database table for information I dont want to save in the database.
Site update
As part of the development of a strategy to consolidate a number of online accounts as well a series of planned enhancements, I have recently migrated this site to a dedicated server, provided as a Joyent Accelerator. The shared hosting provided by Joyent has been great. However, the time has come to upgrade. I think that I have everything working now, but if you come across something that looks funky, please drop me a note.
What does this mean to you? For now, nothing really, except page loads should be a hell of a lot faster. :)
Slow .rxml processing
There has been a performance issue that has been well documented when using Builder::XMLMarkup. Over the course of time, I’d noticed that my rails app has gotten slower and slower building XML as more data ended up in the database. On my development environment, it would take approximately 15 seconds to render the xml generated by this controller.
As it turns out, the pure ruby implementation of String#to_xs is pretty slow. Thankfully, there is a C extension which you can install to alleviate this. Installing fast_xs is as easy as:
superbia:~ matt$: sudo gem install fast_xs
If you’re using Rails 2.0, you’re done. If you’re using Rails 1.2.x, we’ll do some monkey patching to make this essentially a drop-in fix. We’ll utilize the same techniques that are used to address the issue in Rails 2.0. Essentially, we want to extend String to take advantage of the fast_xs method if it is available. To do this, open $(RAILS)/config/environment.rb and add the following lines to the bottom.
begin require ‘fast_xs’ class String alias_method :original_xs, :to_xs if method_defined?(:to_xs) alias_method :to_xs, :fast_xs end rescue LoadError #fast_xs extension unavailable end
Again, this is exactly how Rails 2.0 takes care of it for you. By the way, this one single change dropped my render time from roughly 15 seconds to just under 3 seconds. If you’re building a lot of XML with Builder::XMLMarkup, you need to take a look at this.
