RailsConf: Bill Katz - Metaprogramming Writertopia

Posted by Nick Sieger Sat, 24 Jun 2006 17:27:00 GMT

Bill Katz took a code-focused approach to explaining metaprogramming and DSLs.

Resources

Bill applies Paul Graham’s quote on bottom-up design and lisp as justification for using Ruby to program DSLs.

Authorization plugin

In search of a better authorization scheme, Bill wanted an elegant syntax using blocks to delineate sections of code that require specific permissions, and a more intuitive way of managing the data surrounding access controls.

current_user.has_role? "moderator"
current_user.has_role? "member", workshop
workshop.accepts_role? "member", user

current_user.is_moderator_of workshop
user.is_eligible_for? campbell_award

Implementing permit

class MeetingController < ApplicationController
  permit "rubyists and wanna_be_rubyists", :except => :public_text

We need a class method. Where to put it? How does this work? (Insert pretty diagram of instance, singleton class and superclass here.) Metaclassees are “anonymous”, you don’t see them by looking at class ancestors.

ActionController::Base.send(:include, Authorization::Base)
ActionView::Base.send(:include, Authorization::Base::ControllerInstanceMethods)

Singleton methods from the point of view of the object are the same as instance methods in the metaclass. See slides on “How do we permit?” for details. Bill chose to tuck the DSL-related methods into modules and used self.included, class_eval and other goodies to set up the methods in the correct places. There is more than way to do this but I suspect Bill chose to do it for purposes of cleanly separating concerns along the lines of where in the class hierarchy the methods live.

ActiveRecord::Base.send(:include,
  Authorization::ObjectRolesTable::UserExtensions,
  Authorization::ObjectRolesTable::ModelExtensions)

This loads an acts_as_authorizable plugin which, when used in a model, inserts an accepts_role family of methods for querying and setting user roles.

Bill blazed through a whole lot of pretty-looking code here for how to set up the DSL infrastructure. You’ll have to go over to the writertopia developer link to see it. Bill has said he’ll post his slides online as well.

Questions

  • Use of method_missing -- does that clash with ActiveRecord::Base usage of method_missing? No, as long as you use super to invoke the next method in the chain, you’re ok. Ruby module inclusion semantics handle this for you.
  • How to insert the class methods? A discussion started around ActionController::Base.send(:include, ...) and There is More Than One Way to Do It.
ActionController::Base.send(:include, Authorization::Base)

class ActionController::Base; include Authorization::Base; end

ActionController::Base.class_eval { include Authorization::Base }
  • Question about the class inheritance chain. There are actually two inheritance chains, one for the classes and one for the metaclasses. Resolution at method invocation time travels first to the object’s metaclass, then to the object’s class, then to the superclass of the singleton class, then the class’s superclass, etc. Blech, that makes no sense. Instead, go read Seeing Metaclasses Early.

Posted in ,  | Tags  | no comments | no trackbacks

Comments

Trackbacks

Use the following link to trackback from your own site:
http://blog.nicksieger.com/articles/trackback/28