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.
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.
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
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
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.
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.
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:
cucumber (.) #.
in the ‘find’ and
bundle exec cucumber $1 -f pretty
in the ‘replace’, and check ‘regular expression’, then ‘replace all’. 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.
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.
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
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.
This one’s simple also. Capistrano has a lovely command: “cap
In the manual world, it’s messier. I don’t like messy. Not with prematurely-sentient nuclear turtles out there.
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.
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…
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'
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).