MVCoffee
Model, View….. Coffee!
MVCoffee is a suite of software tools written in CoffeeScript and Ruby that provides a client-side Model View Controller (MVC) framework and cache. It’s designed from the ground up to work closely with (and take advantage of the coolest features of) Ruby on Rails.
Version 1.1.0 is now released!
Source on github:
mvcoffee.js
CoffeeScript library
js-rails-routes
command line utility
Code Demos
To get a feel for how MVCoffee does some of the things it does, check out these demos:
The Philosophy and Benefits
Yes, there are a lot of other client-side MVC frameworks out there. Most of them are somewhat one-size-fits-all, in that they don’t have an opinion about the server-side technology used. MVCoffee could potentially be used with any server-side solution, but it is specifically designed to work closely with Ruby on Rails. Its approach is inspired by the Rails way of doing things, and it takes advantage of and enhances many of Rails’ features, like routes, model associations and validations, metaprogramming techniques and Turbolinks.
The guiding philosophy is this. Caching has both benefits and pitfalls. Rails can make server-side caching easier, but ultimately it’s optional. If you can get by without the benefits, you don’t have to worry about it.
The same is not true on the client.
If you think about it, a web page is a cache. It’s a snapshot of some of your data, frozen in time and held onto indefinitely. Unless the user navigates to another page, or unless you do something explicitly to refresh the data should it become stale, you may be displaying out-of-date data to the user. Or worse, you could be allowing the user to interact with out-of-date data!
Like it or not, you face the pitfalls of cached data on the web, so you might as well enjoy the benefits. If you’re dealing with invalidating stale data (and it behooves you to!), you might as well not be reloading data that isn’t stale. Know whether it’s stale or not, and do the right thing accordingly.
Here are some of the things MVCoffee does to help you keep the data on the client fresh while gaining improved performance:
- Makes it easy to move rendering of dynamic data to the client with embedded JavaScript (
ejs
) templates that look almost identical to the familiar Rails embedded Ruby (erb
). It does this by providing a model layer that mirrors Rails’ ActiveRecord and JavaScript versions of the<route>_path
functions for generating URL’s within the app. This client side rendering can be completely agnostic as to the source of the data, whether it’s from a first time page load overhtml
, a refresh via Ajaxjson
, or an inexpensive rerender of cached data already on the client. - Automates refreshing potentially stale data. Users frequently will be visiting your
app in multiple tabs, browsers or even devices at the same time. MVCoffee detects
when a page could be potentially out of date and fires the
refresh
method on all running controllers. All you have to do is specify what should be refetched and recached on a refresh. - Facilitates client-side caching while still allowing URL-based navigation of your application. In other words, you don’t need to resort to a Single Page Application (SPA) on your client in order to keep the JavaScript state live. You get the convenience of bookmarkable pages in your application and the performance benefits of cached data on the client.
- Fills in some holes in Turbolinks with a process called “clientizing”. Turbolinks unobtrusively follows GET anchor
links via Ajax, keeping the javascript session live and providing faster performance.
It does NOT, however, provide this same convenience for any kind of
form
on the page out of the box. This means normallybutton_to
andform_for
elements, when clicked, cause a full page load and restart of the JavaScript session (wiping out any cached data). MVCoffee extends the unobtrusive JS to handle forms, buttons, and delete and post anchor links for you. -
Provides Rails-style validations and associations on client-side models, with a familiar Class Macro-like syntax for defining model attributes. Although you have to Repeat Yourself to define the client models, this pain is eased by the similar syntax, and could conceivably be automated in the future.
it = class MyNamespace.User extends MVCoffee.Model it.has_many 'item' it.validates 'name' test: 'presence' it = class MyNamespace.Item extends MVCoffee.Model it.belongs_to 'user' it.validates 'sku' test: 'numericality' only_integer: true
-
Requires only a few lines of client code to make an input form automatically validate against the associated model and submit to the server over Ajax only if valid. This saves you having to repeatedly make the same jQuery
.submit
intercepts and Ajax calls.@item = new MyNamespace.Item @addClientizeCustomization selector: "#item_form" model: @item
- Provides familiar Rails server-side functionality on the client, such as the flash, session and errors array.
- Handles redirects on the client. This ensures that the JavaScript session will
remain live (preserving the cache), and even allows redirecting after a
json
request over Ajax. - Normalizes browser behavior concerning pausing and resuming your application.
Desktop browsers fire
onblur
andonfocus
for the window and do not stop timers when your window receives anonblur
. Safari on iOS, on the other hand, does stop timers but does not fireonblur
andonfocus
. MVCoffee normalizes this and provides apause
andresume
life cycle for client-side controllers. (Note: Android and Windows browers have not been tested at this time!) - Saves you typing with the usual “convention over configuration” way, alleviating the need for the whole
respond_to do |format|
business by normalizinghtml
andjson
responses.
Reference Guides
To learn more, check out the guides: