Provides the Modularity CoffeeScript library in a convenient way for Rails applications.
CoffeeScript Ruby
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


Makes the modularity.js library available to Rails 3.1 applications.

Modularity is a framework for lightweight component-oriented CoffeeScript. It allows to compose functionally rich web pages in a clean, intuitive, and testable way out of well structured and reusable components. It scales very well with complexity.



Load modularity in your application's Gemfile:

gem 'modularity-rails'

And then execute:

$ bundle

Finally, you have to load the modularity file into your application's javascript. The easiest way is to add it to

 # require jquery
 # require modularity


Modularity is a lightweight framework for building powerful AJAX applications. Modularity avoids magic and heavyness. It focusses on providing a pragmatic and interoperable foundation for clean hand-written code bases. Modularity provides practices to create code bases of incredible complexity that are still nicely manageable and perform very well.


Modules are native CoffeeScript classes that are specialized for doing what most JavaScript running in browsers does: managing a UI consisting of DOM elements, reacting to events that happen within that section, representing application logic specific to that section, and providing high-level APIs for others to interact with the section.

Each module has a container. The container is the outermost DOM element of a section. Everything the module does must happen inside this container. The module is responsible for managing the inner DOM-structure of the container.


Modules are supposed to form a loosely coupled architecture, in which they communicate with each other through events. Similar to jQuery events, a module can trigger an event using its trigger method, like so:

@trigger 'user_selected', user

The first argument is the event name, the second one an optional data payload. The event is a normal jQuery event, triggered from the container of the module.

Other modules can subscribe to events from particular modules using a similar mechanism:

@user_list.on 'user_selected', (e, user) -> ...

The first argument is the jQuery event object, the second one the data payload.

Event Autobinding

If you want to avoid writing lots of boilerplate code to wire up events, use Modularities autobind method together with the convention to name your event handler methods "on_#{module_name}_#{event_name}". For example, to listen to the "entry_created" event of a module called "userlist", name your method "on_userlist_entry_created". To illustrate this more, the following two pieces of code are equivalent:

Manual event listener setup:

@userlist = new UserList()
@userlist.on 'entry_selected', @user_selected
@userlist.on 'entry_created', @user_created
@userlist.on 'entry_deleted', @user_deleted

user_selected: (e, user) -> ...
user_created: (e, user) -> ...
user_deleted: (e, user) -> ...

Automatic event listener setup:

@userlist = new UserList()

on_userlist_entry_selected: (e, user) -> ...
on_userlist_entry_created: (e, user) -> ...
on_userlist_entry_deleted: (e, user) -> ...


Similar to Ruby mixins, mixins in Modularity allow to include orthogonal functional aspects defined in separate objects into a class.

myMixin =

  # This will be called when an instance of a class that includes this mixin is created.
  constructor: ->

  # This method will be available in every class that includes
  myMethod: ->

class MyModule extends Module

  @mixin myMixin

  constructor: (container) ->

    # The super constructor will call the mixin constructors here.

    # ...


Hooks are a more direct and easier way to interact with mixins. They are methods with predefined names that mixing modules can implement to hook into events of their mixins without the need to wire up event handlers, and with the ability to interact with the workflow of the mixins.

Reusable example modules and mixins.

Modularity comes bundled with a bunch of example modules and mixins that can be used in production code. The example modules are located in vendor/assets/javascripts/modules/ and vendor/assets/javascripts/mixins and must be explicitly required in your Rails files using the require commands of the asset pipeline.


  • A simple button. Fires the clicked event when anything inside the container is clicked. Uses the clickable mixin.
  • Similar to button, but includes the click count as data payload in the fired event.



Including this mixins adds a 'clickable' aspect to your module, i.e. turns it into a button. Clicking anywhere inside the container makes it fire the 'clicked' event.


Including this mixin makes a module closable. The mixin searches for an embedded DOM element with the class 'CloseButton'. When it is clicked, the following things happen:

  • The closable_closing hook of the closable class is called. This hook could be used to display confirmation dialogs (and abort the close process) or to fire custom events that depend on the DOM still being present. If this method returns a falsy value, the closing process is aborted.
  • The closable module fires a local 'closing' event (with the DOM still present).
  • The whole module including its container is removed from the DOM.
  • The closable_closed hook of the closable class is called.



  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Added some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

Running the unit tests

$ evergreen run

Automatically refreshing the browser during development.

Modularity-Rails comes with support for LifeReload via Guard.

  • Install the LiveReload browser extension: Chrome
  • Run the evergreen server: $ evergreen run
  • Run the guard server: $ bundle exec guard
  • Start the LiveReload plugin in Chrome (button in address bar).
  • Navigate to the test page that you want to observe.
  • Change and save code and see the browser reload.