Skip to content

Diving into Compass and SASS

Thanks for everyone who came out to my talk at Barcamp Tampa Bay today, and many thanks to all the organizers, volunteers, and sponsors.

Here are the slides to my talk – Diving into Compass and SASS.

 

Pow! Dead-easy rails development servers

The Problem: you’ve got multiple rails projects in development; possibly one or more use subdomains, and you can’t be bothered messing with vhosts and /etc/hosts and <insert extra hassle steps here> just to look at your app in the browser.

The Solution: Pow, a zero-configuration Rack server for OSX, by Sam Stephenson over at 37 Signals.  (Oh, yeah, this is an OSX solution, so other platforms go pout.)

I’ve been working with it for a few days now, and quite like it so far.

It runs on node.js, so if you don’t have that installed, go get a nice tall bottle of whiskey and commence to installin’. I’ll wait.

Back? Ok. Let’s get Pow installed and running in 90 secs or so:

Oh, wait. Back up. Installing and using Pow involves unix commands and symbolic links and sure there’s only a couple of things to type but that’s soooo hard….luckily, there’s a gem for that. sudo gem install powder

And then, to install Pow: powder install

No sudo, but it’ll ask you for your password.

Then, go to the root of your rails (or any rack) app:

powder up

That’ll start the pow server. You only have to do that once, no matter how many apps you’re serving.

powder link

to link up your app to a pow server. By default, it takes the name of the dir you’re in, so if your app is in ~/code/myapp, it’ll use myapp.dev. If you’d like to use a different url, just do:

powder link myfancyappname

Now, you can go to myapp.dev in your browser (or myfancyappname.dev), and you’re all set.

Here’s the extra handy bit: if you use subdomains in your app, just do:

powder link subdomain.myapp

Now subdomain.myapp.dev is available.

That’s it.

powder down will turn off the server should you want to,

powder restart

will restart your app, and

powder remove

will remove the pow server link.

Oh, to get the app’s logs, just run powder applog from the app root; it’s like tail -f development.log

Enjoy

Filtering spam with akismet and rails

I’ve got a rails site with an active comments section. For a couple of years I’ve been using the recaptcha gem by fellow tampa.rb member Jason Perry, and that’s mostly worked well.

Recently we’ve been getting hit by spam from Russia which has been getting past the recaptcha filters. The spammer in question may or may not be Leo Tolstoy (pictured).

Has recaptcha been cracked? You can read

Image via Wikipedia

opinions about that elsewhere.

In the meantime, I needed to add more protection to keep the discussions hammy. So, I turned to the akismet service from the WordPress folk, and the rakismet gem.

To get it set up was fairly simple, with one gotcha.

First, install the rakismet gem. In your Gemfile:

gem 'rakismet', '0.4.2'

Note that I’m specifying the 0.4.2 version – this app is on rails 2.3.x, and the 1.0.x version of rakismet is rails 3 only.

Next, sign up for an akismet api key over at akismet.com/. This service will run you $5/mo.

Then add your key and site url to config/initializers/rakismet.rb: Rakismet::KEY = '8167608161e2' Rakismet::URL = 'http://www.wmnf.org'

Now the gotcha: the docs for rakismet hint that a third setting, Rakismet::HOST, is optional, and only useful if you’re using typepad or another akismet endpoint. It fails if that’s not configured, though, and there’s no default in the gem. So, add a third line:

Rakismet::HOST = 'rest.akismet.com'

In your comment model, add:

include Rakismet::Model

You may have to map some fields from your model to the ones rakismet expects; details are in the readme.

Now, before you save a comment, just check

comment.spam?

and you’re all set.

You may want to save the comments anyway and set a state flag to ‘spam’ or the like, so you can make sure valid comments aren’t getting unfairly flagged.

Hope that helps.

Enhanced by Zemanta

Running migrations in Sinatra

Using Active Record in Sinatra and miss your rails db migration tasks?

Create a /lib/tasks directory from your project root, and copy this file into it: https://github.com/rails/rails/blob/2-3-stable/railties/lib/tasks/databases.rake

In your Rakefile, add this line (thanks to this post):

Dir.glob('lib/tasks/*.rake').each { |r| import r }

And, to let the migrations dump your schema.rb file:

RAILS_ROOT = File.dirname(FILE)

And you’re all set.

Textmate trick for failing cucumber stories

Quick tip: if you’re trying to clean up some failing cucumber features, and you get output like so: cucumber features/my_feature.feature:24 # Scenario: My user does stuff cucumber features/my_feature.feature:38 # Scenario: My user does more stuff

And you’d rather it look like this:

bundle exec cucumber features/my_feature.feature:24 -f pretty bundle exec cucumber features/my_feature.feature:38 -f pretty

So you can copy/paste back into terminal to run the features under bundler with pleasant output, here’s how:

  • Copy paste the failing scenario lines to a new textmate window;
  • Do cmd-f for find/replace – put cucumber (.) #. in the ‘find’ and bundle exec cucumber $1 -f pretty in the ‘replace’, and check ‘regular expression’, then ‘replace all’.

Post-deploy notifications on EngineYard Cloud

Post-deploy notifications on Engine Yard cloud

I’ve got a project hosted on EngineYard‘s cloud servers, with geographically-dispersed team. The developers are often working on separate feature sets, often deployed independently. As a quality-control and awareness measure we wanted to be notified when a deploy was done.

This was pretty easy to set up, and would work with capistrano deployments also.

First we set up a mailer action; I used an existing mailer class for this but you might want to create a separate class just for process-type notifications:

  def deploy_notification(attribs)
    subject       "A build of my_project was deployed to #{attribs[:env_name]}"
    from          "MyProject CodeMonkey HQ"
    @from =       "notify@example.com"
    recipients    "bullwinkle@example.com"
    sent_on       Time.now
    body          :revision => attribs[:revision], :env_name => attribs[:env_name]
  end

and the corresponding deploy_notification.text.plain.erb:

  Heads up code monkeys! New code has been deployed to <%= @env_name %>

  Details:

  Environment: <%= @env_name %>
  Revision: <%= @revision %>

I’ll probably make that a little fancier with a direct link to the commit on the githubs, and possibly pull in the commit message etc.

Next, we add a rake task to call the mailer; I put this in /lib/tasks/deploy.rake:

  namespace :deploy do
    desc "notify developers of deployment"
    task :notify => :environment do
      attribs = {}
      ARGV.each do |arg|
        if arg.match(/TO=(.*)/)
          attribs[:env_name] = $1
        elsif arg.match(/REVISION=(.*)/)
          attribs[:revision] = $1
        end
      end
      SupportMailer.deliver_deploy_notification(attribs)
    end
  end

Finally, for engineyard integration, in deploy/after_restart.rb:

  # notify dev team of deploy
  run "cd #{release_path} && rake deploy:notify TO=#{@configuration[:environment]} REVISION=#{@configuration[:revision]}"

That gets called by the engineyard chef scripts after the deploy finishes. For capistrano deployments, you could do the same in an “after deploy:restart” call.

That’s it. Hope it’s helpful.

Why use automated deployment?

I was talking with a developer about their first rails project, the deadline of which was looming. After a quick walk-through of the code I started asking about process stuff — what are you using for tests? Are you using capistrano for deployment?

The answers were “I’d like to use tests at some point in the future” — danger! — and that no, he was deploying things manually up to a vps instance.

I said that whatever server admin task like deployment that I can automate and do from my own machine, I will. He asked, “why, are you not a server guy?”

So, I thought I’d jot down a snapshot of why I use capistrano (or chef recipes, with engine yard-ish clouds) for deployment, in case someone else is wondering.

Three main reasons: flow, safety, and process.

Flow

This one’s pretty simple. During the course of a development day, my screen-estate is taken up by an editor window, a browser, and the console. My console (iTerm) usually has several tabs open, typically three per project: a server, a prompt at the app’s root for doing git operations and kicking off tests, and one tab that’s tailing the cucumber or rspec logs.

If I want to deploy, I just drop into the console that’s already open, and run a simple command (“cap deploy”) and I’m done. It’s just part of the flow, and flow is everything.

If I have to deploy something manually, that involves: * opening a new tab * logging into the server * moving to to the app root * running commands like git pull, etc * possibly restarting mongrels * logging out and closing the tab

None of which is in the flow of developing. In other words, I have to switch modes from developer to sysadmin, and switching modes kills the flow.

Safety

This one’s simple also. Capistrano has a lovely command: “cap deploy:rollback”. If I deploy something that’s not ready for primetime, and satellites begin falling from their orbits or nuclear attack turtles start becoming sentient before they’re meant to, I can just kick off a rollback and I’m back to safety and fluffy bunnies. That’s because capistrano keeps several releases stored on the server, and switching to a previous codebase is as easy (mostly) as switching some symlinks.

In the manual world, it’s messier. I don’t like messy. Not with prematurely-sentient nuclear turtles out there.

Process

Anything I have to do manually is something I’m likely to either screw up or forget. That’s because I’m a forgetful screw-up, but it’s important to build self-protection into your process flow.

Aside from updating the codebase, deployments can typically involve migrating the db, updating symlinks, restarting search servers, notifying services such as hoptoad and newrelic, etc. Anything that has to be done each time you deploy can be built into a capistrano script, so you don’t have to think about it. What you don’t have to think about, you won’t forget to think about, and you won’t screw-up.

If the updated codebase depends on a migrated db, and you forget to run the migrations after deploying manually, well here come the sentient nuclear turtles. And they’re mad.

So, keep the world safe: automate your deployment.

quick tip: bunder, rails 2.3.8, and rspec

I set up an app on 2.3.8 with bundler, and when trying to run the rspec tests got .../config/Gemfile not found (Bundler::GemfileNotFound)

which is odd.

I’d grabbed the code for config/intializers/preinitializer.rb from gembundler.com; to solve the issue I changed line 15 from

ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", _ FILE _)

to

ENV["BUNDLE_GEMFILE"] = File.expand_path(File.join(Rails.root,"Gemfile"), _ FILE _)

Hope that helps…

quick tip: zsh and bundler

I’m just starting to look at bundler — way ahead of the curve as usual.

I’m using zsh, and every time I ran a bundle command I’d get:

correct 'bundle' to .. [nyae]?

To turn off the autocorrect message, just add this to your .zshrc:

alias bundle='nocorrect bundle'

upgrading hoptoad: uninitialized constant HoptoadNotifier::Catcher

Dept. of Quick Tips Dept.: If you’re upgrading from an older plugin version of the hoptoad notifier to the 2.2 gem, and you see uninitialized constant HoptoadNotifier::Catcher when you try to script/generate hoptoad, go to application_controller and remove the line:

include HoptoadNotifier::Catcher

Then run script/generate hoptoad again and all should be well.

Oh, and if you can’t unpack the gem, try removing lib/tasks/hoptoad_notifier_tasks.rake (via here).