Rails JavaScript Workflow (Rendering JavaScript partials)

This post summarizes how to pass data from a Rails application to the client and how to execute JavaScript code in Rails views. Let’s start by creating a new Rails application called BaseballApp and then generate a Player resource with name and batting average attributes.

$ rails new BaseballApp
$ rails generate resource Player name batting_average:integer

Make 100 players with a batting average that is a random number between 1 and 1000.

# db/seeds.rb
def batting_average
  rand(1..1000)
end

100.times do |count|
  Player.create(name: "Bob#{count + 1}", batting_average: batting_average)
end

Populate the database by running $ rake db:seed.

Create an index view that displays all the players and their batting averages in a table.

# controllers/players_controller.rb
class PlayersController < ApplicationController
  def index
    @players = Player.all
  end
end

# views/players/index.html.erb
<code>
<% @players.each do |player| %>
<table>
  <tbody>
  <tr>
    <td>Name</td>
    <td>Batting Average</td>
  </tr>
  <tr>
    <td><%= player.name %></td>
    <td><%= player.batting_average %></td>
  </tr>
  </tbody>
</table>
<% end %>

We will write some JavaScript and want to access the BaseballPlayer objects in the browser (aka, the “client”). Let’s add some code to pass the Ruby player objects to the client as JavaScript objects.

# views/players/index.html.erb
<%= content_tag :div, class: "players_class", data: {players: @players} do %>
<% end %>

Navigate to http://localhost:3000/players and open the JavaScript console. We will use some JQuery to demonstrate that the Ruby player objects are now available in the client as JavaScript objects.

Screen Shot 2013-06-05 at 7.46.39 PM

We have made the Ruby objects accessible to the client as JavaScript objects by adding them to an empty div with a data-players attribute.

Use Object oriented JavaScript to add a function that accepts a collection of JavaScript objects as an argument, randomly selects an object, and alerts the user the name and batting average for the object.

# assets/javascripts/players.js
var Players = {
  randomPlayer : function(players) {
    var min = 0;
    var max = players.length - 1;
    var random_index = Math.floor(Math.random() * (max - min + 1)) + min;
    return players[random_index];
  },
  alertRandomPlayer : function(players) {
    var random_player = this.randomPlayer(players);
    alert("Name: " + random_player.name + " :: Batting average: " + random_player.batting_average);
  }
}

Now we can add a JavaScript partial to run the alertRandomPlayer method after the Player#index page is loaded.

# views/layouts/application.html.erb
# Add this line to the head tag:
<%= yield :head %>

# views/players/index.html.erb
<% content_for :head do %>
  <script type="text/javascript">
    <%= render 'players/alert_random_player.js' %>
  </script>
<% end %>

# views/players/_alert_random_player.js.erb
$(function() {
  players = $('.players_class').data('players');
  Players.alertRandomPlayer(players);
});

I get confused when I try and execute JavaScript code in the assets/javascripts folder. It is easier to keep track of things by rendering partials and executing the JavaScript when you expect it.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s