Tag Archives: rails

MySQL, Snow Leopard and ruby

I got a shiny new MacBook Pro on the weekend, yay! After months of complaining about the slowness and the heat evaporating from my old Macbook, I’m finally off to better grounds.

But then there was the annoying task of setting up the machine with all the software that I’m using. MySQL and ruby turned out to be particular problems. I installed MySQL for 10.5, since MySQL haven’t published one for OS 10.6 yet. I ran “gem install mysql”. And then the pain started.

I got all the errors that were reported elsewhere:
uninitialized constant MysqlCompat::MysqlRes” and “undefined method `real_connect’ for Mysql:Class (NoMethodError)“. I tried all the suggestions – including:
"sudo env ARCHFLAGS="-arch x86" gem install mysql -- --with-mysql-config=/usr/local/mysql-5.1.39-osx10.5-x86/bin/mysql_config -V --debug, but just couldn’t get there.

My laptop reports in the System Software Overview: “64-bit Kernel and Extensions: No”, so I assumed I had to use the 32 bit versions. However, that was a wrong assumption. Even though my kernel seems to be 32 bit, applications seem to be 64 bit.

So, eventually I re-installed MySQL for Mac OS X 10.5 (x86_64) and ran the correct gem install command:
sudo env ARCHFLAGS="-arch x86_64" gem install mysql -- --with-mysql-config=/usr/local/mysql-5.1.39-osx10.5-x86 and things were fine.

Additionally, there was some fighting with the PrefPane and re-starting mysql. I had to kill it manually and I had to install the updated PrefPane of Swoon dot net to make it work.

Hope this helps somebody avoid the same pain!

Date & Time selection plugins for Rails

I just tried comparing the different date & time selection plugins that are available for Rails and because the wiki page at rubyonrails.org is dated and I cannot edit it, I decided to write this brief blog post to save you the 20 min it took me to locate the currently available plugins and their demos:

So now you can compare and pick the one that suits you best. Enjoy! 🙂

UPDATE: John just told me that there is a list of other plugins at the bottom of the CalendarDateSelect plugin page – doh!

Rails Authorization Plugin

The Rails authorization plugin is a really nice way of providing role management and restrict access to specific features. It also works nicely with the RESTful authentication plugin which manages user login and authentication.

However, there is a serious lack of documentation of how to use this plugin – the README.txt inside the plugin and the source code is the best I have found. I also learnt some from the slides for the Railsconf 2006 on “Metaprogramming Writertopia”. This blog entry is collecting what I have learnt and also freely copies some text from the different sources.

Assuming you have installed the authorization plugin, you need to extend your models with the plugin. In particular the User model and the model(s) that you would like to use multiple user roles for.


class User < ActiveRecord::Base
# Authorization plugin
acts_as_authorized_user
...
end


class Account < ActiveRecord::Base
# Authorization plugin
acts_as_authorizable
...
end

The acts_as_authorized_user part of the plugin creates the following methods for the User model:

  • has_role? role_name [, authorizable_obj]: finds out if a user has a certain role (for a certain object)
  • has_role role_name [, authorizable_obj]: creates the role if non-existant, and assigns the role to the user (for a certain object)
  • has_no_role role_name [, authorizable_obj]: remove role from user (for a certain object), and the role if not in use any longer

As some background information, the plugin creates 2 tables – one for the roles (name, authorizable_type, authorizable_id, timestamps), and one that maps roles to users roles_users (user_id, role_id, timestamps). The authorizable_type and authorizable_id map the role to the authorizable_obj.

The acts_as_authorizable part of the plugin creates the following methods for the Account model:

  • accepts_role? role_name, user: finds out if the user has the role on the model
  • accepts_role role_name, user: sets the user to have the role on the model
  • accepts_no_role role_name, user: removes the user from having the role on the model

In the code, you can now use the following methods to create roles for users and accounts. Assuming we have a user ‘u’ and an account ‘a’, we can do one of the following to create the role ‘admin’:

  • u.has_role ‘admin’, a
  • a.accepts_role ‘admin’, u
  • u.is_admin_for a
  • u.is_admin (gives user the role ‘admin’, not tied to a class or object)

To check on roles, you can use the following:

  • u.has_role ‘admin’, a: return true/false if the user has the role ‘admin’ on the account
  • u.is_admin? a: return true/false if the user has the role ‘admin’ on the account
  • u.is_admin_of? a: return true/false if the user has the role ‘admin’ on the account
  • u.has_role ‘admin’: return true/false if the user has the role ‘admin’ on anything
  • u.is_admin?: return true/false if the user has the role ‘admin’ on anything
  • u.is_admin_of_what Account: returns array of objects for which this user is a ‘admin’ (only ‘Account’ type)
  • u.is_admin_of_what: returns array of objects for which this user is a ‘admin’ (any type)
  • a.accepts_role? ‘admin’, u: return true/false if the account has the user with the role ‘admin’
  • a.has_admin(s)?: return true/false if the account has users with the role ‘admin’
  • a.has_admin(s): returns array of users which have role ‘admin’ on the account

There are more dynamically generated methods and they are created through the method_missing hook. There is a whole domain-specific language behind this creation of methods. Just about everything that sounds like proper English will work.

An interesting twist is that roles can also be set on model classes: u.has_role 'admin', Account. So, roles can be set on one of the following three scopes:

  • entire application (no class or object specified)
  • model class
  • an instance of a model (i.e., a model object)

In your controller, you can now use two methods to check authorization at the class, instance, or instance method level: permit and permit?. permit and permit? take an authorization expression and a hash of options that typically includes any objects that need to be queried:


def index
if current_user.permit? 'site_admin'
# show all accounts
@account = Account.find(:all)
else
@account = current_user.is_admin_for_what(Account)
end
end


class AccountController public_page
...
def secret_info
permit "site_admin" do
render :text => "The Answer = 42"
end
end
end

The difference between permit and permit? is redirection.

permit is a declarative statement and redirects by default. It can also be used as a class or an instance method, gating the access to an entire controller in a before_filter fashion. permit? is only an instance method, that can be used within expressions. It does not redirect by default. You will find more information on the boolean expression of the permit or permit? methods here.