Ruby 1.8.6 Considered Harmful

April 20th 2011

At $WORK today, we discovered the following anomalie in Ruby 1.8.6:

  {:a => 1}.hash != {:a => 1}.hash
  >> true

wat.

This basically means that hashes are not reliable hash keys. It also means that arrays of hashes cannot be modified through set operations, such as #–.

Please, upgrade your rubies.

You can argue that you should never be in a position to find this out. You would be right.

Still upgrade your rubies.

Init Scripts with Thin, Bundler and Monit

October 15th 2010
#!/bin/bash
LANG=en_US.UTF-8 \
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
BUNDLE_GEMFILE=/u/apps/my_app/current/Gemfile \
/usr/local/bin/bundle exec thin ${1:-start} -C /u/apps/my_app/shared/thin_conf.yml -O

You will thank me later, for sparing you much pain.

Some discussion:

LANG is used to set the language in the shell. This is necessary because Ruby looks at this variable to decide which language it should normally use. This is important because the Locale code for ActiveRecord has a bunch of UTF-8 Characters in it.

PATH is important because when monit starts up a shell, it’s basically like doing

env -i

BUNDLE_GEMFILE points to our gemfile.

Then we start our process with thin.

Rails Security Made Easy

April 25th 2010

I’ve just released an early-alpha version of secure_rails (http://github.com/alexbartlow/secure_rails), a way of collecting the cross-cutting concern of security into a single cohesive set of policy files.

It looks a lot like this:


#rails g security:model User
# lib/security/models/user.rb
 Secure(User) do |u|
   u.policy(:default) do
     attr_accessible # complete lockdown
   end
   
   u.policy(:self) do
     attr_accessible :name, :email # The user himself can edit name and email
   end
   
   u.policy(:admin, :include => :self) do
     attr_accessible :status # moderators can edit status
   
     validates_exclusion_of :status, :in => [:banned_forever], 
       :unless => :skip_status_validation
       
     def skip_status_validation ; false ; end
     # but the moderator cannot set the status to banned forever
   end
   
   u.policy(:manager) do
    # this doesn't do anything, but is here to show that you can use include to
    # pull in multiple roles
   end
   
   u.policy(:super_admin, :include => [:admin, :manager]) do
     def skip_status_validation ; true ; end 
       # superadmins skip the status validation check
   end
   
   # policies always take precidence over the policies they include.
   # That's why the super-admin policy works.
 end

That’s for models. It also lets you specify controller-grained access control:

# lib/security/controllers/users_controller.rb
SecureController(UsersController) do |u|
  u.policy(:default) do
    # Don't allow unprivileged users to change anything
    if [:create, :update].include?(params[:action])
      raise SecurityTransgression.new
    end
  end
end

Pretty awesome, dry, an unlikely to have you forget a before_filter :require_admin in an internal page. Default everything to closed, and you can open up all of your controllers and models in one place.

Check it out over on github (http://github.com/alexbartlow/secure_rails) – play around with it in your rails 3 apps, and let me know if you have any problems!