Skip to content

LoamStudios/seed_tray

Repository files navigation

SeedTray

SeedTray is a convention-based approach to page specific Javascript.

Installation

Add this line to your application's Gemfile:

gem 'seed_tray'

And then execute:

$ bundle install

Or install it yourself as:

$ gem install seed_tray

In application.js, require seed_tray after the rest of your JS is included.

//= require turbolinks
//= require_tree .
...
//= require seed_tray

Add the data attributes to your <body> element

<body <%= page_data_attr %>>
    <%= yield %>
</body>

Usage

SeedTray makes a couple assumptions about how you will organize your code.

You need to create a object to represent your app with the same name as your Rails app. SeedTray will automatically use this object as the root of your view classes.

You must add an object for each controller#action combination for which you want to provide custom javascript.

For example, let's say your Rails app is called Fruit. You need to have a fruit.js.coffee in assets/javascript.

Let's say you have a controller named BananasController with actions index and show. You will need to add three objects in bananas.js.coffee:

  • Fruit.Bananas

  • Fruit.Bananas.Index

  • Fruit.Bananas.Show

In each of these objects, you need to implement the render method:

Coffeescript:

In app/assets/javascript/bananas.js.coffee

class @Fruit.Bananas
    @render: ->
        # Custom coffeescript to run on every action

class @Fruit.Bananas.Index
    @render: ->
        # Custom coffeescript for bananas#index

class @Fruit.Bananas.Show
    @render: ->
        # Custom coffeescript for bananas#show

If you want some coffeescript to run site wide:

In fruit.js.coffee

class @Fruit
    constructor: ->
        Fruit.delegator.site_wide_render = ->
           # Do something

Javascript ES2015

In app/assets/javascript/bananas.(js, es6)

Fruit.Bananas = class {
  static render() {
    // Custom Javascript to run on every action
  }
};

Fruit.Bananas.Index = class {
  static render() {
    // Custom Javascript for bananas#index
  }
};

Fruit.Bananas.Show = class {
  static render() {
    // Custom Javascript for bananas#show
  }
};

If you want some Javascript to run site wide:

In fruit.(js, es6)

class Fruit {
  constructor(){
    Fruit.delegator.site_wide_render = function (){
      // Site wide JS
    };
  }
}

HEADS UP: Make sure your application object (Fruit from our example) is added before the rest of your code or else, you will get an undefined error.

To finish the install, instantiate the app object in applications.js if you defined any methods or data on it:

new Fruit();

This is particularly important if you intialize the site_wide_render method in the object's constructor. SeedTray must have added the delegator before you attempt to set the value.

Add the data attributes to the

<body <%= page_data_attr %> >
  ...
</body>

page_data_attr puts data attributes with the controller and action on your page. For example, if you were visiting /bananas/1, you'd get:

<body data-controller='Bananas' data-action='Show' >
  ...
</body>

Console Suppression

By default, SeedTray will write to your browser's console when a script is executed or skipped. Depending on your Javascript driver in your test suite, these messages may show in your testing console as well.

To suppress these messages, simply add the following to the appropriate config/environments/ file.

SeedTray.configure { |config| config.suppress_console = true }

Events

Since SeedTray executes after a document's ready event fires, there are several events attached to document provided at various stages of the rendering cycle.

Global:

Upon rendering of any given action within any given controller, the event seedtray:render is fired. Eg:

$(document).on('seedtray:render', function(){ ... });

Controller:

Upon rendering of any action within a given controller, the event seedtray:<controller>:render is fired. Eg:

$(document).on('seedtray:bananas:render', function(){ ... });

Action:

Upon rendering of any given action, the event seedtray:<controller>:<action>:render is fired. Eg:

$(document).on('seedtray:bananas:show:render', function(){ ... });

Please Note:

Since the events are fired in the order sitewide -> controller -> controller#action, each class only has access to it's event and any proceeding events (IE controller can access the controller#action delegation event, but it cannot access the sitewide delegation event)

Namespaced Controllers

A controller named Admin::Dashboard becomes Admin_Dashboard in the convention. More generally, module/word_word_controller becomes Module_WordWord. We replace the scope operator with an underscore and CamelCase the controller name. See the helper definition for the exact details.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/LoamStudios/seed_tray. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

License

The gem is available as open source under the terms of the MITLicense.