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.