Sudojs::Rails

More than just making the currently released versions of sudo.js and sudo-x.js available to your application, sudojs-rails is about a development pattern. A pattern that is enforced, and made covenient, through the use of generators.

This highly opinionated workflow creates a global-level namespace for your code, a convenient namespace-level observable model, and expects that you want new javascript class objects placed into either the app/assets/javascripts/application/ directory or, preferably, into an app/assets/javascripts/views/<controller_name>/ directory (more below).

Along with this, it is expected you will want a 'manifest' file created (or appended to if existing) for the newly created Class Object. Manifests will named for controller actions (or the global application) and should be loaded either globally (in the application case) or per controller (more on this below). This allows for a degree of freedom when differentiating assets.

New Class Objects that you create can inherit from sudo.js defined types, or your own custom classes, and be written in .js or .coffee

Installation

Add this line to your application's Gemfile:

gem 'sudojs-rails'

And then execute:

$ bundle

Or install it yourself as:

$ gem install sudojs-rails

Usage

Prepare Your Project

Before use, a few steps need to be followed to prepare your project for our preferred workflow.

  • We place manifest files into an app/assets/javascripts/manifests directory. This means that your app/views/layouts/application.html.* file needs to be adjusted to account for this:

    <%= javascript_include_tag 'manifests/application.js' %>
    

Preferably, you will not place this in your head tag

  • We assume that any Class Object not used more than once (i.e. is unique to a particular controller#action) will not go into application.js but be placed into its own manifest for that controller. For this to function, a helper method can be constructed in app/helpers/application_helper.rb

    def controller_javascript
      controller_manifest = File.join('manifests', "#{self.controller_name}.js")
      return '' if Rails.application.assets.find_asset(controller_manifest).nil?
      return javascript_include_tag(controller_manifest)
    end
    

This allows the following, combined with the previous include tag:

    <%= javascript_include_tag 'manifests/application.js' %>
    <%= controller_javascript %>
  • When concatonating for staging and production environments the following code needs to have been inserted into your config/environments/staging and config/environments/production .rb files:

    config.assets.precompile += %w( manifests/* )
    

In Practice

running the command rails g would reveal that a single sudojs:install command can be made. Execute the command rails g sudojs:install -h (or see below) to see the USAGE directives. Running rails g sudojs:install Spam will install the correct files and directories (with your shiny new Spam namespace).

sudojs:install USAGE

Description: Install sudo.js along with it's particular directory hierarchy.

Example: rails g sudojs:install [html_extension] [js_extension] [css_extension] [--skip-css=true/false]

Two namespaces, 'page' and 'lib', will be automagically created. The 'models' and 'templates'
Containers will be appended to the page namespace, and 'lib' is used to house Class definitions 
by convention.

The install generator uses these options to expand the values in the sudo_js.yml file:
  1. `--html_extension` => Use the full extension, i.e. `.haml`. defaults to `.erb`.
  2. `--js_extension` => defaults to `.js` pass `.coffee` if you are of the coffee persuasion.
  3. `--css_extension` => defaults to `.css`. Sass for example would need `.scss`

NOTE: to skip any and all generating of css files pass the option `--skip-css=true` when invoking the install generator.
Obviously, you could then leave the `css_extension` argument out. The option defaults to false.

This will create:
app/
  assets/
    stylesheets/
      manifests/
        application.*
    javascripts/
      manifests/
        application.*
      models/
        base.*
      views/
        application/
          page.*
config/
  sudo_js.yml

sudojs:class USAGE

After installing a second generator becomes available, run rails g again and sudojs:class should now be an option. The reason for this is that :class depends on a yaml file to be placed in config/ to function. Executing the command rails g sudojs:class -h would reveal this:

Description: Create a skeletal sudo.js Class and place the files correctly for a given controller#name.

Example: rails g sudojs:class View foo#baz

Where `View` is a Class Object that this new Object will inherit from. Sudo.js itself
will recognize 6 types:

  1. 'Base'
  2. 'Model'
  3. 'Container'
  4. 'View'
  5. 'ViewController'
  6. 'Dataview'

The inheritance for any of these will be set as `_.<Name>` as we assume sudo has taken the 
global `_` char as an alias. If the argument is any other string we assume you are inheriting
from a custom class and pass it through as is.

Where `foo#baz` *can* match a controller#action (like `home#show`) it does not
have to. The controller argument (`foo`) allows the generator to place the file correctly and 
create/modify the correct manifest file. The name argument will be the proper name of the 
Class Object itself.

If a corresponding views/controller/name.html* is found, a skeletal instantiation of the newly 
created View will be placed there.

This will create (or modify):
  app/
    assests/
      stylesheets/
        manifests/
          foo.css
        views/
          foo/
            baz.css(*)
      javascripts/
        manifests/
          foo.js
        views/
          foo/
            baz.js(*)

And modify (if found):
  app/
    views/
      foo/
        baz.html(*)

Note: If the route is application level (application#baz) the file will be placed in the application level directory and the manifests/application file will be modified

Note:
  If the `route` is application level (application#baz) the file will be placed
  in the application level directory and the manifests/application file will be modified

Contributing

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