Thursday, March 27, 2014

Ruby SuperModule Comes To The Rescue!!

Tired of ActiveSupport::Concern and Ruby's modules not allowing you to mix in class methods easily? Well, worry no more! SuperModule comes to the rescue!

SuperModule allows defining class methods and method invocations the same way a super class does without using def included(base).

This succeeds ActiveSupport::Concern by offering lighter purely idiomatic Ruby syntax and simpler module dependency support.

1. Just include SuperModule at the top of a module definition:
module UserIdentifiable
  include SuperModule

  belongs_to :user
  validates :user_id, presence: true

  def self.most_active_user
    User.find_by_id(select('count(id) as head_count, user_id').group('user_id').order('count(id) desc').first.user_id)

  def slug

2. Mix newly defined module into a class or another super module
class ClubParticipation < ActiveRecord::Base
  include UserIdentifiable
class CourseEnrollment < ActiveRecord::Base
  include UserIdentifiable
module Accountable
  include SuperModule
  include UserIdentifiable
class Activity < ActiveRecord::Base
  include Accountable

3. And start using by invoking class methods or instance methods
ClubParticipation.create(club_id:, user_id:

More details and examples are available over here:

And the SuperModule RubyGem lives over here:



Henrik N said...

Cool idea and clever implementation.

I wrote something with a similar "just write it as you would inline" API a few years back. Slightly more boilerplate; simpler implementation:

Andy Maleh said...

Thanks for sharing. Interesting indeed. Reminds me a bit of JavaScript's Stampit library though applied in Ruby. Thought I'd mention in case you'd like inspiration for newer features.

By the way, I just released an improved SuperModule v1.1.0 yesterday. Check it out:

SuperModule's goal is just focused on making modules simply includable without any boilerplate ritual, a smaller scope than Stampit's grand ideas, but a good step forward nonetheless that is a lot easier to digest by developers.

Banister's include_complete came really close to addressing my concern, but not quite all the way as mentioned in the gotchas I talk about in this Reddit post:

In any case, I'd like to hear back if you end up using SuperModule on projects.