Sneaky Abstractions

Subscribe to my Feed, follow me on , recommend me on Working With Rails or see my code on GitHub

Prototype-based inheritance in Ruby

Posted on June 06, 2007 16:59 Tagged with ruby.

This was originally posted as a response to a “challenge” on irb.no, and I thought it was kind of clever, so I’ll post it here as well ;) The challenge was to write something object-oriented in Ruby without using classes. So, inspired by my recent crush on ECMAScript, I thought, why not try to implement prototype-based inheritance in Ruby?

Object.class_eval{ attr_accessor :prototype }
Object.class_eval do
  def method_missing(s, *a)
    if self.prototype.nil?
      raise NoMethodError, "LOL U MISSING #{s}!!"
    else
      self.prototype.send(s, *a)
    end
  end
end

cat = Object.new
def cat.meow; 'IM IN UR OBJECTZ'; end
cat.meow # => "IM IN UR OBJECTZ"
kitten = Object.new
kitten.prototype = cat
kitten.meow # => "IM IN UR OBJECTZ"

(Yes, a bit of LOLCODE inspiration there too)

I’m sure this has been done by many before me, because it’s so simple. And that’s what I like about it. The implementation is simple beause the concept is simple. Simplicity beats complexity any day.

Meet Sanskrit, the Rich Textile Editor

Posted on June 03, 2007 22:25 Tagged with sanskrit, javascript, textile.

Sanskrit is a simple “rich-text editor” with no bells or whistles, and it outputs Textile instead of XHTML. It’s meant to be safe (with regards to XSS, hence Textile) and simple. It only works with the most basic (inline) text styles.

This is my very first time writing something that resembles a library in JavaScript, so it’s probably full of bad practises, errors and generally smelly code. If you have tips for improvement, please let me know. I’ve tested this in Gecko, IE6, IE7, Opera 9 and Konqueror (which doesn’t support this kind of stuff, but the fallback to a normal textarea works), but if you find that it doesn’t work in a browser (and preferrably how to fix it :), please let me know about that too.

Internet Explorer 7, I accept your presence

Posted on May 09, 2007 13:15 Tagged with internet explorer.

If you’re into self-afflicted pain and use Internet Explorer 7 you should now get this page as HTML instead of X(HT)ML. I recently found out that IE7’s Accept header consists of nothing but */*, which means it supports every type of document there is. Then I found out that’s not actually true, so HTML is now the default unless your browser asks for something else, like XHTML.

The CSS probably doesn’t work in IE, so everything is probably out of place. I couldn’t care less.

IRB for JavaScript

Posted on May 09, 2007 10:47 Tagged with irb, javascript, spidermonkey.

Have you ever wished there was a console application for JavaScript, like IRB for Ruby, where you can try things out? Well, there is one and it is part of Mozilla’s SpiderMonkey JavaScript implementation (in C). If you’re on Ubuntu (and maybe Debian too?), installing it is as easy as

apt-get install spidermonkey-bin

Then, run js:

js> Foo = function(){}
function () {
}
js> Foo.prototype.bar = function(){ print('BAR!') }
function () {
    print("BAR!");
}
js> foo = new Foo()
[object Object]
js> foo.bar()
BAR!

This may be something that everyone else but me knew about, but I’m pretty excited to have somewhere other than a browser to try out things as I start learning JavaScript properly.

New SVN address/domain troubles

Posted on May 09, 2007 09:28 Tagged with subversion.

I’ve been having some domain troubles lately, so if you’ve been using one of my plug-ins with svn:external or trying to install one in a new project Subversion probably complained about not being able to look up the domain svn.2750flesk.com. I’ve moved the plug-ins to

http://nimrod.interinter.net/plugins/

Sorry for any inconvenience this might have caused, such as messing up a streamlined Capistrano deployment process :)

Cleaning up your nest: How to nest resources with multiple access points

Posted on April 29, 2007 18:50 Tagged with rails, resources, controllers.

With Rails’ new routes nesting resources is easy. Now, whether you should nest or not depends on a lot of things, and others have written smart things about that. Sometimes though, nesting makes sense, and sometimes resources can have multiple access points. In REST terminology, they’re actually different resources, even though in Rails they use the same model. A classic example is this:

class User < ActiveRecord::Base
  has_many :posts
end

class Category < ActiveRecord::Base
  has_many :posts
end

class Post < ActiveRecord::Base
  belongs_to :user
  belongs_to :category
end

Here, it makes sense to list posts in a certain category and posts that are written by a certain user in addition to just listing all posts. But how do you represent this in a RESTful manner in Rails? The basic assumption seems to be that a controller maps to a model, but I don’t think that’s the best way to do it. If you have multiple resources that use the same model, how would you know in which context the controller is used? For

PostsController
in this example, how would you limit the posts listed based on a user or a category? Sure, it’s doable, but it can get pretty messy. Instead, I suggest thinking of a controller as a resource access point. That is, controllers map to resources. So, in this example, we would have a separate controller for each of these resources:

#/posts
class PostsController < ApplicationController

  def index
    @posts = Post.find(:all)
  end

end

#/category/:category_id/posts
class CategoryPostsController < ApplicationController
  before_filter :find_category

  def index
    @posts = @category.posts
  end

  private
    def find_category
      @category = Category.find(params[:category_id])
    end
end

#/users/:user_id/posts
class UserPostsController < ApplicationController
  before_filter :find_user

  def index
    @posts = @user.posts
  end

  private
    def find_user
      @user = User.find(params[:user_id])
    end
end

Then we map all the resources in routes.rb, specifying which controller to use for the nested resources. We also add a

:name_prefix
to the nested resources so the names don’t clash with the other resources with the same name.

ActionController::Routing::Routes.draw do |map|
  map.resources :posts
  map.resources :users do |user|
    user.resources :posts, :controller => 'user_posts', :name_prefix => 'user_'
  end
  map.resources :categories do |category|
    category.resources :posts, :controller => 'category_posts', :name_prefix => 'category_'
  end
end

But that’s not DRY

There’s a lot of repetition here, but who cares? The controllers have clearly separated concerns because they represent different resources. For

UserPostsController
you may not want to show a single post for example, but instead, in /user/:user_id/posts, point to /posts/:id. Repeating yourself is much better than getting tangled up in increasingly complex abstractions.

1 2 3 4 5

✪✻✫✿✬✼✭❀✮✾✯❁✰❃