This week I checked out Sublime Text 3 and it’s definitely a lot snappier to start up and do global searches than ST2. There’s also a branch of Package Control in alpha that mostly works with ST3. I found that a lot of the syntax bundles and tm-bundle ports worked out of the box, but some packages still require developers to port their code to Python 3.
So, when I was porting my settings over, I noticed a useful keybinding that I had forgotten wasn’t built into Sublime. TextMate had this feature where you can Command + Control + R and it’d locate the file you’re working on in the sidebar. I use this so often I thought I’d share this. Here’s how you do it. Open Menu > Sublime Text > Preferences > Key Bindings - User and paste the following snippet:
Recently, I’ve needed to add some state machine functionality in some of my models. So, the first thing I did was check out various ruby state machine gems on the Ruby Toolbox. I prefer Sequel over ActiveRecord, but almost all of the gems listed only provide adapters for ActiveRecord or Mongoid. The amount of effort to write a Sequel adapter is definitely something to consider for me.
state_machine is the gorilla of state machine gems. It has tons of features, adapters for ActiveRecord, DataMapper, Mongoid, MongoMapper, and Sequel, but can be overkill for simple uses cases. I don’t need multiple state machines per class, event parallelization, namespacing, etc. However, having generated Graphiz visualizations can be invaluable when you have complicated state transitions. I’ve actually used state_machine before, but I do feel it’s too heavy for my needs.
AASM has been around for years and has adapters for ActiveRecord and Mongoid. It’s relatively light, but it doesn’t have a Sequel adapter and from looking at the ActiveRecord adapter, it seems like it’d be a little work to write one.
Transitions is the state machine extracted from ActiveModel. It’s super simple, but requires ActiveModel compliance. For Sequel support, there is a a ActiveModel plugin that provides this. I attempted this solution first, but ran into an after_initialize exception, which I believe is an ActiveRecord specific hook.
“Workflow is a finite-state-machine-inspired API for modeling and interacting with what we tend to refer to as ‘workflow’.” The API is similar to the other 3, but the immediate difference is that you define events and transitions in the context of the state. When I used state_machine, events were defined separately from states and therefore you could reuse the same event definitions. Workflow is pretty lightweight at about 500 loc and as a bonus, also supports generating Graphviz visualizations. Workflow doesn’t have a Sequel adapter, but it looks like adding support only requires defining 2 methods.
All these gems provide, states, transitions, events, generated predicates and hooks, but I decided to go with Workflow because it was lightweight and it seemed like the easiest to write a Sequel adapter for. I also have some complicated flows, and the Graphviz diagrams can help a lot in visualizaing transitions.
To write a persistence adapter for Workflow is fairly straightforward. Override load_workflow_state and persist_workflow_state(new_value) methods in the class. I packaged it into a gem, workflow_sequel_adapter. To use it, just add this to your Gemfile:
and then in your class, include WorkflowSequelAdapter:
So, how do you use Workflow? Well, here’s one simple use case. A User model starts in an unconfirmed state. When the user signs up, they get a confirmation email with a link to confirm their account. When they click on that link, the confirm event is triggered, and the state transitions to active. While active, the event deactivated can be triggered, which will transition the state to inactive.
require'bcrpyt'require'secure_token'classUser<Sequel::ModelincludeBCrypt# for password encryptionincludeWorkflow# for workflow blockincludeWorkflowSequelAdapter# for workflow sequel persistenceset_allowed_columns:email,:password# allow email and password to be set via mass assignmentworkflow_column:state# use 'state' as the workflow column instead of 'workflow_state'workflowdostate:unconfirmeddoevent:confirm,transition_to::activeendstate:activedoevent:deactivate,transition_to::inactiveendstate:inactivedoevent:activate,transition_to::activeendend# if you define a method with the same name as the event name, it'll be invoked after the transition# this will clear the confirmation_token after a user is confirmeddefconfirmself.confirmation_token=nilself.save_changesend# equivalent of ActiveRecord scopes for each statesubset:unconfirmed,state:'unconfirmed'subset:active,state:'active'subset:inactive,state:'inactive'# singleton method to authenticate based on email, passworddefself.authenticate(email,unencrypted_password)user=self[email:email,state:'active']userifuser&&user.password==unencrypted_passwordenddefpassword@password||=Password.new(encrypted_password)enddefpassword=(new_password)@password=Password.create(new_password)self.encrypted_password=@passwordend# generate unique confirmation token after createdefafter_createsuperself.confirmation_token=generate_confirmation_tokenself.save_changesenddefvalidatesupervalidates_presence[:email,:encrypted_password]validates_unique:email,:confirmation_tokenendprivatedefgenerate_confirmation_tokenrecord=truewhilerecordtoken=SecureToken.generaterecord=self.class[confirmation_token:token]endtokenendend
State predicates are also generated so you can tell which events can be triggered:
I have a piece of code that needs to remove (rm -rf) a directory, but sometimes FileUtils#rm_rf will fail and return an Errno::ENOENT with the message “Directory not empty.” Maybe a file in that directory is locked by the OS, but for whatever reason, it can fail. So in such a case, I retry it a few times and exit if it fails to remove that directory after those attempts.
The retry counting and incrementing bit can be verbose and if you need similar functionality elsewhere in your code, it can get kind of messy. I have another piece of code that uses Grit to clone a git repo and that can time out so I retry that code a few times too. This type of retry code can be useful when accessing external apis or anything that can possibly time out that you might want to retry.
I have a Rails application with an initializer that accesses my Mongoid models. This works fine locally when I run rails s, but when I deploy to Heroku, the deployment will eventually timeout as Heroku tries to run:
It’s not just Heroku though. If I run that rake task locally, it will also just seem to freeze or lock up when it tries to access any Mongoid model. I’ve verified this with the ruby debugger.
It turns out that Mongoid only preloads your models when $rails_rake_task is false (ie. not a rake task). Here’s the Github issue where this change was made. I’m not sure why this was changed. I guess most rake tasks don’t need to eager load the models since they don’t need to access them. To work around this, I’ve just put a condition also checking for $rails_rake_task. In my case, the initializers need to access the models when the app starts up, not when rake tasks are run.
Update 10/12/2011 - Looks like I posted this too soon. This is coming back.
Rails 3.1 comes with a live compilation mode for serving static assets, but in order to describe what it does we’ll need to go over the recommended method of serving up static assets in Rails.
Normally, after a deploy, it’s recommended you run:
This will run in the production environment even without specifying a RAILS_ENV. This rake task compiles all your static assets to:
Usually, you’ll do this via a post deploy hook. Then your Rails app will serve the files via the ActionDispatch::Static rack middleware.
Let’s say you decide to not precompile your assets. Any requests to a static asset will return a 404 because it can’t find the asset. However, if you turn on live compilation, Rails will compile static assets on the fly. To turn it on:
By default, around line 12, you’ll see that this is set to false. This isn’t recommended, since there’s more processing involved than the precompile route.
So you have a brand new Rails 3.1 app and you’re using the new asset pipeline feature. You’re also using a content delivery network (CDN) like Amazon CloudFront or Cloudflare to serve up static assets. Everything’s working great, but little do you know, Rails is polluting your cache storage with static assets!
When you use a CDN, a request for a static asset will hit the CDN first. If the CDN doesn’t have that asset on its servers, it will request the asset from your Rails app and then store it across it’s global distribution network. The next time the asset is requested, it will be served up from the closest geographical data center to the user. This hopefully gives the effect that your website is loading faster.
I’ve been migrating a project from Postgres to MongoDB, where dynamic fields would help tremendously. We went with Mongoid for our ORM since it seems to have the most support and activity on Github. However, one thing I’ve noticed after migrating all my models is that the app was instantly slower. Everything felt sluggish, but when I deployed to a staging box, everything was fast and snappy. One of the first things I started to do was to switch on some production environment settings to see if some of these flags could give me a hint as to what the issue was.
Updated July 14, 2011: As of Nanoc 3.3, nanoc-deploy will be integrated into nanoc core.
Recently at work, we’ve needed to deploy some static websites. The designers had been hand coding these in raw html for months, but I thought it’d be great if we could bring in some HAML and SASS goodness since they’ve been using it extensively on our Rails apps. I’ve been dabbling with static website generators months ago for my parent’s restaurant website. I looked at Jekyll, Toto, and StaticMatic, Webby, but ultimately I found the best for me was nanoc. This was in part due to @h3rald blogging about it.
Jekyll is great, but it’s mainly aimed at blogging. Toto was too simple. StaticMatic and Webby aren’t actively maintained. Nanoc is pretty actively maintained and it’s great for building any kind of static site, not just blogs.
At work, we’ve recently switched from Engine Yard AppCloud to Heroku. One of the things we’ve been missing is daily database dumps. Heroku does provide you with an addon called PG Backups. The basic free version will retain 2 postgres backups, which you have to kick off manually.
There’s a gem created by @ddollar (now maintained by joemsak) called heroku_backup_task. This gem adds a rake task that captures a new database backup in the PG Backup addon and expires the oldest one.
I’m working on a Rails 3 app that hosts many projects and every resource within the app is scoped by a project. So wallpapers, videos, polls, etc. belong to a project. Ideally, I want my routes also scoped by a project. It’s easy to configure nested resources that give you routes that look like:
But since everything is scoped by the project name, why don’t I just drop the /projects prefix?
So this gives us params[‘project_name’] in each video action. Now our routes can look like this: