code.life

Rose Weixel’s technical blog

Integrating Ajax and Rails: A Simple Todo List App

This post is based on a tutorial I created to teach students at The Flatiron School the basics of integrating Ajax with Rails. This guide is appropriate for beginners who have already learned the basics of Rails and jQuery.

It will walk you through the process of adding Ajax to a very simple rails app for creating todo lists. First we’ll go through the basics of setting up the Rails app, then adding jQuery and Ajax to add items without reloading the page. Finally, we’ll refactor with remote: true. Feel free to code along!

The Basic Rails Todo App

Before getting to Ajax, here are the steps to create the basic rails todo app we’ll be building on:

1) rails new todo_app

2) rails g resource todo

3) In the migration file (located in db/migrate):

1
2
3
4
5
6
7
8
9
class CreateTodos < ActiveRecord::Migration
  def change
    create_table :todos do |t|
      t.string :description
      t.string :priority
      t.timestamps null: false
    end
  end
end

4) In app/controllers/todos_controller.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class TodosController < ApplicationController
  def index
    @todos = Todo.all
  end

  def create
    Todo.create(todo_params)
    redirect_to root_path
  end

  def destroy
    todo = Todo.find(params[:id])
    todo.destroy
    redirect_to root_path
  end

  private
    def todo_params
      params.require(:todo).permit(:description, :priority)
    end
end

5) In config/routes.rb:

1
2
3
4
Rails.application.routes.draw do
  root 'todos#index'
  resources :todos
end

6) Create views/todos/index.html.erb with a basic form and list of todos:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<h1>My Todos</h1>

<%= form_for Todo.new do |f| %>
  <div class="form-group">
    <%= f.text_field :description, placeholder:
    "what needs doing?" %>
  </div>

  <div class="form-group">
    <%= f.text_field :priority, placeholder: "priority level" %>
  </div>

  <div class="form-group">
  <%= f.submit %>
  </div>
<% end %>

<ul>
<% @todos.each do |todo| %>
  <li>
    <%= todo.description %><br>
    <strong>priority: </strong><%= todo.priority %><br>
    <%= link_to "done", todo_path(todo), method: 'delete' %>
  </li>
<% end %>
</ul>

7) Before starting up the rails server: rake db:migrate

Now we can create new todos and destroy them. This is as functional as our app needs to be. Except for one thing. Since this is a single page app, it would be really nice if we could add and remove todos without reloading the page. Enter Ajax!

Posting New Todos with Ajax

Now we are going to “ajaxify” the process of creating todos. Since we are entering JavaScript land, we’ll go into app/assets/javascripts. You’ll see a file called todos.coffee or todos.js.coffee. We will not be using CoffeeScript, so rename it to todos.js.

Here’s what we are going to implement:

When the “Create Todo” button is clicked, we will stop the default form submission behavior from happening, and send an Ajax request instead. To break this down further, here are the steps we’ll need to follow:

  1. Create an event listener for the ‘click’ event (or for the submission of the form) that loads when the document is ready and prevents the default behavior from happening (stops the page from reloading).
  2. Grab some information from the form to use in our Ajax request.
  3. Make the Ajax request.
  4. Handle the response and add the new todo to the page.

Create an Event Listener

In app/assets/javascripts/todos.js:

1) Make sure the document is ready before doing anything else.

1
2
3
4
// This is shorthand for $( document ).ready(function() { })
$(function(){

});

2) Listen for the submission of the form.

1
2
3
4
5
6
$(function(){
  $("form").submit(function(){
    // this debugger should be hit when you click the submit button!
    debugger;
  });
});

3) Prevent the default behavior (the form submitting and the page reloading).

1
2
3
4
5
6
7
8
$(function(){
  $("form").submit(function(event){
    event.preventDefault();

    // this debugger should be hit when you click the submit button!
    debugger;
  });
});

Grab Information From the Form

In order to make the Ajax request, we’ll need to give the request the correct action and method to take us to the create action in the todos controller. If we rake routes, we’ll see this:

POST /todos(.:format) todos#create

So we know we will be making a ‘post’ request to ‘/todos’. We could hard code this in our Ajax request, but what if our routes change later on? Our request would no longer work. In order to make our code more robust, we’ll get the correct action and method directly from the form itself. Basicaly, we’ll ask the form where it was going by extracting the information with jQuery.

The debugger we threw into our code above will be really useful in figuring out the jQuery code for pulling out the information we need. With your server running and your JavaScript console open, fill in the form and hit the submit button. When the debugger gets hit, what is this?

`this` in the console

Since our debugger is inside the function that’s attached to the form submission, this is the form itself, and the action and method we need are right there! Let’s use jQuery to grab them, using the handy .attr() method.

`.attr()` in the console

1
2
3
4
5
6
7
8
9
$(function(){
  $("form").submit(function(event){
    event.preventDefault();

    var action = $(this).attr('action');
    var method = $(this).attr('method');

  });
});

Of course, we also need the text we entered into the form for the todo description and priority level. If we open up the form element and all the divs that live inside of it in our console, we see that Rails gave our inputs some nice ids that we can use to select them with. Specifically, there’s an input with an id of “todo_description” and an input with an id of “todo_priority”. Lets grab these using the jQuery .find() method.

.find() in the console

We don’t see the values that we typed into the form yet, but we can pull them out using the jQuery .val() method.

.val() in the console

Great! Let’s store these values as variables so we can pass them in to our Ajax request.

1
2
3
4
5
6
7
8
9
10
11
12
$(function(){
  $("form").submit(function(event){
    event.preventDefault();

    var action = $(this).attr('action');
    var method = $(this).attr('method');

    var description = $(this).find('#todo_description').val();
    var priority = $(this).find('#todo_priority').val();

  });
});

We are ready for the next step!

Make the Ajax Request

We are going to make an Ajax request that will deliver a JavaScript response to the create action in the todos controller.

The jQuery documentation for writing Ajax requests is really nice, so here’s some code I pulled from there:

1
2
3
4
5
$.ajax({
  method: "POST",
  url: "some.php",
  data: { name: "John", location: "Boston" }
});

If we change the method, url, and data to the variables we created, we should be good to go! Our todos.js should now look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$(function(){
  $("form").submit(function(event){
    event.preventDefault();

    var action = $(this).attr('action');
    var method = $(this).attr('method');

    var description = $(this).find('#todo_description').val();
    var priority = $(this).find('#todo_priority').val();

    $.ajax({
      method: method,
      url: action,
      data: { description: description, priority: priority }
    });

  });
});

Since we’re expecting this Ajax request to hit the create action in the todos controller, let’s put a binding.pry in there (make sure you’ve added gem 'pry' to your Gemfile and run bundle install first):

1
2
3
4
5
6
def create
  # if our ajax request works, we'll hit this binding at take a look at params!
  binding.pry
  Todo.create(todo_params)
  redirect_to root_path
end

Here’s what you’ll see when that binding gets hit:

params in pry

Success! The Ajax request went where we wanted it to go and it sent the params through the way we told it to. But params is not quite right. Since we’re using strong params, we need a nested structure where “todo” is a top level key. By changing our Ajax request to include data: { todo: {description: description, priority: priority} } this problem is solved, but there’s actually a jQuery method, .serializeArray(), that will take care of turning all our form data into a nicely structured object (nesting included!) that we can use in our Ajax call. Here’s how it looks in our code:

1
2
3
4
5
6
7
8
// .serializeArray() can be called on any form element (and here, $(this) is our form)
var data = $(this).serializeArray();

$.ajax({
  method: method,
  url: action,
  data: data
});

Now our params will be structured the way Rails expects them to be, and we can move on to the next step!

Handle the Response

We’re still in the todos controller create action, and we’re now able to instantiate new todos using the nicely structured params that we sent via Ajax. Currently, after creating the new Todo, we are just redirecting to the root_path. But the whole point of using Ajax is not to redirect. By default, a rails controller action handles responses that are sent in as html strings. We now want to tell it to respond to JavaScript:

1
2
3
4
5
6
7
8
9
10
11
def create
  Todo.create(todo_params)

  respond_to do |format|
    # if the response fomat is html, redirect as usual
    format.html { redirect_to root_path }

    # if the response format is javascript, do something else...
    format.js { }
  end
end

Before going further into what Rails will do with this JavaScript response, there’s one more problem with our Ajax request. We did not tell it to send back JavaScript! Let’s do that now, and our Ajax call should look like this:

1
2
3
4
5
6
7
8
$.ajax({
  method: method,
  url: action,
  data: data,

  // this line makes the response format JavaScript and not html.
  dataType: 'script'
});

So now that we’re getting the response we want, what is format.js { } actually doing?

When Rails sees that line of code, it will automatically look for a file with the path app/views/<controller name>/<action name>.js.erb. In our example, it’s looking for app/views/todos/create.js.erb.

Make that file and throw a debugger in there to confirm that it’s actually where we land when we get out of the create action.

new create.js.erb file debugger in create.js.erb

That worked! So now that we are in create.js.erb, we have access to any instance variables we created in the controller action that led us there, and we can write JavaScript and ERB (embedded Ruby) code to do whatever we want with our view. We should probably save our newly created todo in an instance variable for just that purpose.

1
2
3
4
5
6
7
8
def create
  @todo = Todo.create(todo_params)

  respond_to do |format|
    format.html { redirect_to root_path }
    format.js { }
  end
end

So what do we want to do next? In create.js.erb, we want to use JavaScript (or jQuery) to append the new todo to the <ul> where the todos live on the page.

We could do something like this:

1
2
3
var html = "<li><%= @todo.description %><br><strong>priority: </strong> <%= @todo.priority %><br><%= escape_javascript link_to 'done', todo_path(@todo), method: 'delete' %></li>";

$('ul').append(html);

Now, when we enter a new todo description and priority and hit the submit button, it appears on the page and no reloading happens! That’s great, but it could use some refactoring.

  1. It’s not DRY: we basically copied and pasted code from our index.html.erb. If the way we want to render todos ever changes, we now have to change it in two places.
  2. It’s ugly. That html string is pretty hard to read, and what’s that escape_javascript doing in there? We need that or the link_to will be evaluated as JavaScript and the whole thing breaks.

The solution to this? A partial. Extract the code for displaying a single todo out of index.html.erb and place it in a new file at app/views/todos/_todo.html.erb:

todo partial

Now you can use Rails magic to render the @todos collection in index.html.erb:

index using todo partial

Finally, replace the html string we had in create.js.erb with code for rendering the partial, passing in @todo as a local variable:

create.js.erb using partial

And we’re done creating todos with Ajax! In the next section, we’ll refactor our code by using remote: true.

Refactoring with remote: true

In Rails, both form_for and link_to helpers can take an argument of remote: true:

Example: link_to with remote: true

1
<%= link_to 'Show Something', something_path(@something), remote: true %>

In the case of our todo list app, we will add remote: true to our form for creating a new todo (the only change here is on the first line of the form):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<%= form_for Todo.new, remote: true do |f| %>
  <div class="form-group">
    <%= f.text_field :description, placeholder: 
    "what needs doing?" %>
  </div>

  <div class="form-group">
    <%= f.text_field :priority, placeholder: "priority level" %>
  </div>

  <div class="form-group">
  <%= f.submit %>
  </div>
<% end %>

So, what does remote: true do for you? In short, it adds a data-remote="true" attribute to the generated html form as seen here, and submits the form via Ajax automagically. As with everything in Rails, there’s metaprogramming going on under the hood. In this case, the JavaScript code that we wrote to hijack the submit event and make the appropriate Ajax request is all generated for you behind the scenes. If you’re feeling extra curious, check out the Rails.js source code.

Here’s a small snippet from the source code linked to above. Not so surprisingly, it looks a lot like the code we wrote (especially lines 2-4!):

1
2
3
4
5
6
7
8
9
10
11
if (element.is('form')) {
  method = element.attr('method');
  url = element.attr('action');
  data = element.serializeArray();
  // memoized value from clicked submit button
  var button = element.data('ujs:submit-button');
  if (button) {
    data.push(button);
    element.data('ujs:submit-button', null);
  }
}

Because Rails is providing all of this JavaScript for us, now that we’ve added remote: true to the form, we can get rid of everything in our todos.js file.

Before adding remote: true:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// app/assets/javascripts/todos.js

$(function(){
  $("form").submit(function(event){
    event.preventDefault();

    var action = $(this).attr('action');
    var method = $(this).attr('method');
    var data = $(this).serializeArray();

    $.ajax({
      method: method,
      url: action,
      data: data,
      dataType: 'script'
    });

  });
});

After adding remote: true:

1
// app/assets/javascripts/todos.js

Just like when we manually wrote out the Ajax call, when the form is submitted the default behavior will be prevented and a JavaScript response will be sent to the create action in the todos controller. The controller will then send us to app/views/todos/create.js.erb, just as it did before. We will leave the rest of our code as is, and we are done with our refactoring!

Deleting todos with remote: true

Now that we’ve seen the beautiful simplicity of remote: true, let’s see how quick and easy it is to remove todos from the database and the DOM with no refreshing needed:

1) In views/todos/index.html.erb, we have a link that hits the destroy action in the TodosController. Simply add remote: true to it.

Note: At this point it’s also important to give each <li> an id that will help us remove the correct item from the DOM after deleting it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<h1>My Todos</h1>

...

<ul>
<% @todos.each do |todo| %>
  <!-- This `id` attribute will help us find the correct element to remove using jQuery -->
  <li id="<%= todo.id %>">
    <%= todo.description %><br>
    <strong>priority: </strong><%= todo.priority %><br>

    <!-- Add `remote: true` to the line below -->
    <%= link_to "done", todo_path(todo), method: 'delete', remote: true %>
  </li>
<% end %>
</ul>

2) Tell the todos#destroy action how to respond_to a JavaScript response:

1
2
3
4
5
6
7
8
9
10
def destroy
  # we need an instance variable `@todo` so we can access it in the next step!
  @todo = Todo.find(params[:id])
  @todo.destroy

  respond_to do |format|
    format.html { redirect_to root_path }
    format.js { }
  end
end

3) Remember that line 7 in the destroy action above will trigger Rails to look for app/views/todos/destroy.js.erb, so create that file and add code to select the todo to remove using jQuery. Let’s make it slideUp():

1
$("li#<%= @todo.id %>").slideUp();

And that’s it. With this simple yet powerful pattern, you can easily ajaxify all the things in all of your Rails apps. If you’re interested in learning more, I’ve listed some handy resources below. Happy coding!

images

Additional Resources

Live Updating DOM Elements With jQuery and Ajax

Based on a talk I gave at the NYCHTML5 Meetup on June 2nd, 2015.

Any web app that involves real-time interactions between users requires some form of live notifications. Implementing this, for a beginner developer such as myself, can be a daunting challenge. This post will walk through how I went about solving this problem when working on Lacquer Love&Lend, a social network for nail polish lovers that allows users to interact via friendships and lacquer loans. As with any social network, I wanted users to see live notifications whenever they received a new friendship or transaction request, or when the state of any of their friendships or transactions changed. The example that follows assumes some basic knowledge of Rails.

Some Basic Ajax

In a basic Ajax request, a user clicks on something, the Ajax request gets sent, and a part of the DOM gets updated without the entire page reloading.

images

The code usually looks something like this:

app/assets/javascripts/something.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 1) Wait for the document to be ready.
$(document).ready(function() {
    // 2) Listen for the submission of the form.
    $("form").submit(function(event) {

        // 3) Prevent an entire page load (or reload).
        event.preventDefault();

        // 4) Grab the information from the form needed for the Ajax request.
        var formAction = $(this).attr('action'); // e.g. '/somethings'
        var formMethod = $(this).attr('method'); // e.g. 'post'
        var formData   = $(this).serializeArray(); // grabs the form data and makes your params nicely structured!

        // 5) Make the Ajax request, which will hit the 'create' action in the 'somethings' controller
        $.ajax({
          url:  formAction,
          type: formMethod,
          data: formData
        });
    });
});

For the basic example, I’m omitting the controller and view as the main focus of this post is how I implemented live notifications. A more detailed explanation of basic Ajax follows in my next post - a prequel to this one, if you will :).

With the code above, a single user’s action of submitting the form sets off the whole chain of events. But for live notifications, more than one user is involved and the action that changes one user’s data is hapenning on another user’s client! Making this happen twisted my brain into a pretzel at first, but after several attempts I got the functionality I wanted. A description of these follows below.

Attempt #1: Refresh a Single Div Every 3 Seconds

In order to get a single part of the page to update without the entire page refreshing, I used a setInterval() function to make an Ajax request every 3 seconds. This would make a GET request to a custom route: users/:id/live_notifications that hit an action named live_notifications in the UsersController.

1) Separate the “live notifications” div into a partial:

images

2) Create a route and a controller action:

config/routes.rb
1
get 'users/:id/live_notifications' => 'users#live_notifications'
app/controllers/users_controller.rb
1
2
3
4
5
6
7
def live_notifications
  @user = User.find(params[:id])

  respond_to do |format|
    format.js
  end
end

3) Make the Ajax request to hit users#live_notifications every 3 seconds:

app/assets/javascripts/live_notifications.js
1
2
3
4
5
6
7
8
9
10
11
12
13
$(document).ready(function() {
    var currentUrl = window.location.href;

    // Given that we're at a url like 'users/:id', this saves the unique id of the user whose show page we are currently looking at
    var userID = currentUrl.substr(currentUrl.lastIndexOf('/') + 1);

    setInterval(function() {
        $.ajax({
            type: "GET",
            url: "/users/" + userID + "/live_notifications"
        });
    }, 3000);
});

4) Once this Ajax request hits the controller (which is set up to handle a JavaScript response in the respond_to block), Rails by default will look for app/views/users/live_notifications.js.erb and execute the following to refresh the partial:

app/views/users/live_notifications.js.erb
1
$("#live-notifications").html('<%= j render "live_notifications", user: @user %>');

This is all it took to refresh that single div every 3 seconds. However, it was far from ideal:

  • Lots of refreshing for no reason (like when you’re looking at another user’s page and no notifications are displayed, or when nothing has changed)

  • Things that never would change are part of the div that is being refreshed (like header text, for example)

  • Last but not least, this kind of indescriminate refreshing breaks the functionality of forms…

images

A Quick Fix for Form Problems

Thanks to jQuery pseudo selectors, we can stop the Ajax call from being made if an input field is currently focused:

app/assets/javascripts/live_notifications.js
1
2
3
4
5
6
7
8
9
10
11
12
$(document).ready(function() {
    ...

    setInterval(function() {
        // prevent the Ajax call from being made if the input field in the live notifications div is focused
        if (!$('#transaction_due_date').is(":focus")){
            $.ajax({
                ...
            });
        }
    }, 3000);
});

Getting More Specific

The next logical step up from the “refresh everything all the time” strategy was to refresh the live notifications div only when looking at one’s own show page (in other words, when the user id in the url matches the id of the current user stored in the session).

In order to make the current_user from the Rails backend available to JavaScript, I put the following in my application layout:

app/views/layouts/application.html.erb
1
2
3
4
5
<script type="text/javascript">
  window.currentUser = {
      id : "<%= current_user.id if current_user %>"
  }
</script>

With current_user.id stored in an object attached to the window, making sure the Ajax call only gets made when a user is looking at his/her own profile page is simple:

app/assets/javascripts/live_notifications.js
1
2
3
4
5
6
7
8
9
10
$(document).ready(function() {
    var currentUrl = window.location.href;
    var userID = currentUrl.substr(currentUrl.lastIndexOf('/') + 1);

    if (currentUrl.endsWith('/users/' + window.currentUser.id)) {
        setInterval(function() {
            ...
        }, 3000);
    }
});

The Final Refactor: Only Refresh When things Have Changed

To change only things that have changed, when they have changed, the ability to compare what’s on the back end with what’s on the front end is needed.

For this part, I needed to capture the state of all of a user’s transactions and friendships (the two things for which there may be a notification), and hide this information on the page. I created a method in the User model that returns all of these states in an array, and put this into a hidden element on the page:

images

Since the transactions could also have due dates, I did something similar for those.

The next step was to change the code in app/views/users/live_notifications.js.erb to check the current state of the user’s transactions and friendships and see if the #all-categories-tracker is up to date:

app/views/users/live_notifications.js.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
var previousInteractionStates = $('#all-categories-tracker').text();
var currentInteractionStates = "<%= @user.transactions_and_friendships_data_array %>";

var countOrStatusChanged = previousInteractionStates !== currentInteractionStates;

var previousDueDates = $.map($(".due-date"), function(val) {
  return $(val).text()
});
var currentDueDates = "<%= @user.due_date_list %>";

var dueDatesChanged = currentDueDates !== previousDueDates.toString();

if (countOrStatusChanged || dueDatesChanged) {
    // UPDATE THE "MASTER TRACKER"
    $('#all-categories-tracker').html(currentInteractionStates);

    // CHECK EACH INDIVIDUAL CATEGORY AND CHANGE ONLY WHAT’S NEEDED
    <% notification_categories.each do |category| %>
        var currentCategory = "<%= category %>";

        // DEAL WITH ANY CHANGES IN COUNT OR STATE
        var currentCategoryStates  = "<%= @user.states(category) %>";
        var previousCategoryStates = $(".category-tracker#" + currentCategory).html();

        // if there's been a change for this category
        if (currentCategoryStates !== previousCategoryStates) {
            // Update the DOM accordingly
             
        }

        // DEAL WITH CHANGED DUE DATES FOR TRANSACTIONS
        if (currentCategory === 'active_requested_transactions' && dueDatesChanged) {
            // Update the DOM accordingly
              
        }
    <% end %>
}

With this final refactoring, checks are in place that stop the unnecessary refreshing that came with the first version:

images

Alternatives

The method I described above for achieving live notifications is very basic Ajax polling. Every serveral seconds, a request/response cycle fires. This inevitably means lots of database querying, even if the amount of refreshing can be reduced to a minimum. In my search for ways to reduce the burden this puts on the database, here are some other techniques I’ve found that may offer some advantages:

1) Long Polling

With this technique, a request fires and waits for a change before sending a response. Then another request can be fired.

2) Web Sockets

Very different than Ajax polling or long polling, web sockets are used for continuous communication between server and client.

3) Server-Sent Events

Unlike web sockets which allows for continuous back and forth from server to client, this technique establishes a persistent connection that allows the server to send data to the client, but not the other way around.

The Fog Creek Fellowship: A Bridge to Life After Flatiron, an Open Door for Women in Tech

After spending three months in a happy Flatiron School chrysalis transforming into a web developer, I graduated a little over two months ago feeling optimistic yet uncertain about the future. I was confident that Flatiron had equipped me to hit the ground ready to build, and had fostered in me a love and excitement for code that would keep me pushing forward no matter where I went next.

Then there was the uncertainty. After spending nine years, more than a quarter of my life, in the education field, I was about to embark on something totally unknown. Coming from a completely non-technical background, as most of my classmates also had, I wondered if I was a “real” developer and how I’d fit in at a tech company.

Aside from the fact that I hadn’t studied computer science and spent most of my life considering nearly every career path except one as a programmer, the knowledge that I’d likely be the only (or one of the only) females in a team of developers at almost any company I ended up at made me wonder how I’d feel at home in this new community.

I had almost forgotten about the startling gender imbalance in tech while I was at The Flatiron School. One thing that sets Flatiron apart from its competitors is that its gender ratio mirrors that of the natural world. In fact, my class was over 50% female, as is the current cohort of students. It’s a place that felt instantly like home, where we all were just a bunch of humans who happened to be on a mission to learn how to code together. People have asked questions like “how does Flatiron get all these women?”. Although it may seem like an obvious thing to ask, maybe the question itself is indicative of part of the problem. Why not ask how the world of tech continues to be so skewed toward men?

These are tough questions to answer, but it’s clear that The Flatiron School is doing a lot of things right. And, I’m happy to say, some forward thinking companies in the world of tech are also stepping up to the challenge of facing and addressing the gender gap. Enter The Fog Creek Fellowship.

Thanks to a partnership with Fog Creek, Trello, and Stack Exchange, nearly every one of my female classmates was able to get a jumpstart on their new coding careers with the mentorship of a senior developer who was willing to devote real time and interest in helping us through the transition. My mentor Max Horstmann exemplified this. When I got that exciting but nerve wracking first technical interview, he was there to do an in-depth whiteboarding session and provide truly constructive feedback. When I had questions about the difference between SQL and NoSQL, he was happy to explain it and discuss the pros and cons. In fact he and all the other mentors in the program were always happy to geek out about pretty much anything with me.

Perhaps most importantly, just like The Flatiron School teaches us to “make no little plans,” my mentor gave me the courage to dream big for my career, not just look for my next job. Should I feel entitled to love what I do for a living? Yes. Could my passion project become a startup one day? Totally possible. This was not just going to be a career change for me – this was a revolutionary mind shift.

Certainly, The Flatiron School and The Fog Creek Fellowship don’t hold any magic answers to the daunting gender gap in tech. But the fact is, when we’re faced with challenges that seem almost impossible to overcome, often the best thing to do is just to throw your hat over the wall and do something. At the end of one journey and the beginning of a much longer one, I’m filled with gratitude and hope.

Reading and Writing to Instance Variables in Ruby: Self., @, or Nothing?

Today marked the end of my second week as an instructor at The Flatiron School, where I graduated just about two months ago. While working with a student this morning, I realized I had been taking for granted a piece of knowledge that I learned in week two of my own semester.

When I first was learning about object orientation, one of the most confounding things for me was when to use @, self., or no prefix at all when dealing with instance variables in class definitions.

After several conversations with classmates and instructors, I thought I had it all straightened out. My table mates and I even wrote an ‘Instance Variable Manifesto’ to make sure we’d retain this enlightenment for all time. Today, I was grappling with the issue once again. It’s funny how learning to program doesn’t always happen in a straight line. The experience reminded me not to take for granted things I “know”, and to savor the moments of re-learning.

Here’s the issue that led to my temporary existential crisis today (had I totally lost my grasp of object oriented programming, all knowledge of Ruby, and/or my mind entirely?):

  • We have a class, Shoe.
  • It has an attribute, condition, with an attr_accessor.
  • It has a method, cobble, that sets a Shoe’s condition to "new".
  • The Rspec test first made a new instance of Shoe and then set its condition to "old". Then, it had the expectation that the condition of the shoe will be equal to "new" after calling the cobble method.

This is the code my student had:

1
2
3
4
5
6
7
class Shoe
  attr_accessor :condition

  def cobble
    condition = "new"
  end
end

At first glance, the reason this code was not making the test pass eluded me. We put a binding.pry in the cobble method, and found that while condition was indeed set to 'new', the test was still failing. Wasn’t condition = "new" just making a call to the condition= method provided by the attr_accessor? Apparently not.

In fact, as I later re-realized, condition = "new" was creating a local variable, condition with the value "new", which has nothing to do with the value of @condition. I was able to come back to understanding this concept when I recalled that I had grappled with this very same thing almost exactly four months ago, when I was working on the exact same lab. I searched through the notes I had taken during those early Flatiron days and found the “manifesto.”

Four months later, here’s my distilled version of it.

  • Use @ only in the initialize method or within a custom reader/writer method (this accesses the instance variable directly)

  • If you intend to ever read or write to an instance variable, build the appropriate reader/writer methods or use attr_accessor, attr_writer, or attr_reader as you deem appropriate. This allows you to delegate getting and setting your instance variables to methods rather than having to manipulate the variable directly.

  • When altering the value of an instance variable, use the writer method prefixed with self. Without giving the writer method an explicit receiver (self), the Ruby interpreter will assume you are setting a local variable rather than calling the writer method (this is what led to the bug in the code snippet above).

  • When simply reading the value of an instance variable, the reader method may be called with no prefix. The receiver of the reader method is implicitly self.

Here’s a code example to demonstrate usage of the previous guidelines:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Shoe
  attr_accessor :condition

  # we're initializing the attribute @condition, so we need to call the instance variable directly
  def initialize(condition="new")
    @condition = condition
  end

  # we're changing the value of @condition, so we call the writer method, which needs to be called on self or else Ruby thinks we're just setting a local variable
  def wear
    self.condition = "worn"
  end

  def cobble
    self.condition = "new"
  end

  # we're just reading the value of @condition, so we can call the reader method (whose implicit receiver is self)
  def report_condition
    if condition == "new"
      "This shoe is in perfect condition!"
    elsif condition == "worn"
      "This shoe needs to be cobbled!"
    else
      "The condition of this shoe is #{condition}."
    end
  end

end

Note that you can also use self. when calling reader methods, and it sometimes feels semantically more natural to do so. Unlike using @, this still delegates responsibility to the reader method, exactly the same as calling the reader method with no self. prefix.

TL;DR

  • Use @ in the initialize or reader/writer methods.

  • It’s better to delegate to reader and writer methods rather than accessing instance variables directly.

  • You cannot call a writer method without the explicit receiver, self. When Ruby sees the = (or -=, or +=), it assumes you are setting a local variable if no receiver is specified.

Making Friends (With Code)

This post will not be about how I’ve spent the last ten weeks at The Flatiron School making awesome friends while coding together, or about my process of becoming friends with code. Those are posts for another time. This one is about the kinds of friendships that are actually built with code, the kind you can persist in a database.

Over the course of working on my two most recent projects, I’ve discovered that there is more than one way to make a friendship happen on the backend of a Rails app (or most likely any app). My first crack at making friendships was for a nail polish sharing app where friends can view each other’s collections and ask to borrow from each other. I watched Treehouse’s tutorial on building social features in Ruby on Rails, which is a good place to start if you’ve never done something like this before. Although it helped me understand it somewhat, the way it was done in the tutorial still seemed pretty complicated to me. I decided to try to figure it out on my own so that I could break it down and understand it better.

Here are the basic back-end requirements for creating a friendship (clearly some buttons and forms on the front-end are needed, but those are implementation details, so I’ll leave them out of this post):

  • You have to teach your models that some Users have relationships with other Users (a self-referential association).

  • You have to store that relationship in the database so that both sides of the relationship have knowledge of it and access to it.

  • You have to have a way of representing and keeping track of the state of the relationship at any given time (requested, accepted, etc.)

Here’s how I did it in my first go-around:

1) I created a join table, friendships:

1
2
3
4
5
6
7
8
9
10
11
class CreateFriendships < ActiveRecord::Migration
  def change
    create_table :friendships do |t|
      t.integer :user_id
      t.integer :friend_id
      t.timestamps
    end
    # it's a good idea to add an index for faster look-ups in the database
    add_index :friendships, [:user_id, :friend_id]
  end
end

2) In the model for Friendship, I taught it that Friends are really just other Users:

1
2
3
4
5
6
7
8
9
10
11
12
class Friendship < ActiveRecord::Base
  belongs_to :user
  belongs_to :friend, class_name: 'User', foreign_key: 'friend_id'

  validate :is_not_duplicate, :on => :create

  def is_not_duplicate
    if !(Friendship.where(:friend_id => friend_id, :user_id => user_id).empty? && Friendship.where(:user_id => friend_id, :friend_id => user_id).empty?)
      errors.add(:friendship, "This friendship already exists!")
    end
  end
end

As you can see from the above, I decided I didn’t want to allow “duplicates” of friendships in the database, but as it turns out there are reasons why you might not want to do it this way. I’ll go into that later.

3) I made the User model aware of the Friendship model:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class User < ActiveRecord::Base
  has_many :friendships
  has_many :friends, through: :friendships

  validates :name, presence: true, uniqueness: true

  def accepted_friends
    accepted_friends = []
    Friendship.where(user_id: self.id, state: 'accepted').each do |friendship|
      accepted_friends << User.find(friendship.friend_id)
    end
    Friendship.where(friend_id: self.id, state: 'accepted').each do |friendship|
      accepted_friends << User.find(friendship.user_id)
    end
    accepted_friends
  end

  def requested_friends_awaiting_approval
    pending_friends = []
    Friendship.where(user_id: self.id, state: 'pending').each do |friendship|
      pending_friends << User.find(friendship.friend_id)
    end
    pending_friends
  end

  def friendships_for_your_approval
    pending_friendships = []
    Friendship.where(friend_id: self.id, state: 'pending').each do |friendship|
      pending_friendships << friendship
    end
    pending_friendships
  end

  def friends_for_your_approval
    pending_friends = []
    Friendship.where(friend_id: self.id, state: 'pending').each do |friendship|
      friend = User.find(friendship.user_id)
      pending_friends << friend
    end
    pending_friends
  end

  def all_friends
    accepted_friends + requested_friends_awaiting_approval + friends_for_your_approval
  end

end

You’ll notice that I wrote a whole bunch of methods to tell Users how to find their friends on both sides of the relationship. I wanted to give users custom notifications in the views depending on whether they had a pending request or a request awaiting their approval, which was part of the reason for this. But even if I hadn’t wanted to do that, I would have at least needed some kind of setup like this that makes multiple hits to the database every time someone wants to see all of their friends.

4) Finally, state is a big part of this model. I set it up so a friendship could have a state of pending or accepted (similar methods would create other states, like rejected). This is where the friendships controller comes in. For the sake of brevity, I’ll just describe the create and update methods:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class FriendshipsController < ApplicationController

  def create
    @user = current_user
    if params[:friendship] && params[:friendship].has_key?(:friend_id)
      @friend = User.find(params[:friendship][:friend_id])
      @friendship = Friendship.new(friend: @friend, user: @user, state: 'pending')
      @friendship.save
      flash[:notice] = "Your friendship with #{@friend.name} is pending."
      redirect_to(:back)
    else
      flash[:notice] = "Friend required"
      redirect_to root_path
    end
  end

  def update
    @friendship = Friendship.find(params[:id])
    @friendship.update(state: params[:state])
    redirect_to(:back)
  end

end

Since I’ve made a column in the friendships table for state, I can set and update the value of that attribute so a Friendship can introspect on the state it is currently in (what if we could write a method for doing this in real life?).

I set the state of the friendship to 'pending' whenever it first gets created. Then, when the User who was “friended” decides to hit the ‘Accept’ button (or the ‘Reject’ button as the case may be), the friendship can get updated accordingly.

So, although the implementation of friendships I ended up with in my first attempt has the functionality I wanted, but as I mentioned before, it’s not the most efficient. While my reasoning was that it is not desirable to have two rows in the friendships join table for every relationship that gets created, this reasoning did not take into account the way databases work. Because I have to query twice (Who are the people I’ve friended? Who are the people who have friended me?) every single time I want to access my friends, this is actually unneccesarily expensive. Since rows in a database are cheap, why worry about adding an extra row if it reduces the number of times you need to hit the database?

I got a second crack at this problem during my current project, an app for teachers that includes functionality for generating seating charts according to who works well together and who doesn’t. Along with my teammates, we built Buddyships (and Enemyships, too!) in a more reciprocal way:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Enemyship < ActiveRecord::Base
  belongs_to :student
  belongs_to :enemy, class_name: 'Student', foreign_key: 'enemy_id'
  belongs_to :course_section

  after_create :inversify
  after_destroy :destroy_inverse

  validates_uniqueness_of :student, :scope => [:enemy, :course_section_id]
  validates_uniqueness_of :enemy, :scope => [:student, :course_section_id]

  validate :cant_be_own_enemy, :cant_be_buddies_and_enemies

  def inversify
    self.enemy.enemyships.create(:course_section_id => self.course_section_id, :enemy_id => self.student.id)
  end

  def destroy_inverse
    if inverse = self.enemy.enemyships.where(:enemy_id => self.student.id, :course_section_id => self.course_section_id).first
      inverse.destroy
    end
  end

  private
  def cant_be_own_enemy
    if student_id == enemy_id
      errors.add(:enemy_id, "you can't be your own enemy! :(")
    end
  end

  def cant_be_buddies_and_enemies
    if Buddyship.find_by(student_id: student_id, buddy_id: enemy_id, course_section_id: course_section_id)
      errors.add(:enemy_id, "you can't be both buddies and enemies for the same class! :(")
    end
  end

end

In this implementation, two rows in the join table are created for each relationship, using a method aptly called inversify.

Because of the reciprocal nature of the relationship created in this model, one database query (student.enemyships) is all it takes to find all potential Enemies. If you were only creating relationships, you’d care about not writing to the database more than you needed to. But since, in general, we query for friendships way more frequently than we create them, we want to make sure the querying is as efficient as possible.

So, while one-way relationships are fine for a follower-followee type of relationship, if you want to create a reciprocal relationship in your next app, don’t shy away from those extra rows in the database.

Awesome Programmer == Awesome Person

We’re nearing the end of the amazing whirlwind that is week eight at The Flatiron School. We’ve bid farewell (at least for now) to lectures and labs, and have blasted off into project mode. No predetermined specs, no Ironboard green lights, just forty eager, fledgeling developers putting all of their ambition, grit, and new skills into building things.

In the midst of the whirlwind, Obie Fernandez, author of the “bible” for Rails development, dropped by to chat with us today. It was inspiring to hear him talk about one of his latest endeavors, the Andela Fellowship, which is a program whose mission is to train some of the brightest young people in Africa to be awesome developers and connect them with employers. Echoing the words of The Flatiron School’s own Avi Flombaum, Obie told us that learning to be an awesome developer is not just about learning “hard skills”. It’s about learning to be an awesome person. Furthermore, he said,

“Programming is a career that encourages awesomeness.”

Though it wasn’t the first time I heard that message, it meant something more to me today than it did in week one, and the words sat quietly brewing in the back of my brain as I spent the evening coding with my teammates.

Does the act of learning to program make you a better person? I’m not so sure of that, but I’m sure that learning to be an awesome person makes you a better programmer. And while learning about nested hashes doesn’t somehow magically make you an awesome person, I do believe that people who are continually striving and struggling to be great programmers will be nudged in the direction of awesomeness by the nature of the endeavor itself.

So, what is it about programming that encourages awesomeness?

  1. Communication and Empathy:

    • No successful programmer works in isolation. I’ve learned at The Flatiron School that while you might go faster alone you definitely go farther if you work together. Failure to listen and communicate effectively negatively affects the team, the workflow, and the product.

    • Code is for communication. It’s not just a set of instructions for a computer. When it’s done right, code tells a story that other developers can understand and build upon.

  2. Caring About The Small Things:

    • In order for your code to work, you have to get the details right. Getting the details right requires patience, mindfulness, and taking pride in one’s work.

  3. Going With The Flow:

    • A program is never done. A good programmer is willing to let go and accept changes, be willing to start from scratch, and be open to going in new directions and taking new approaches.

  4. Grit:

    • Starting to learn to program is hard. Keeping on learning to program while it’s hard takes grit.

  5. Being a Lifelong Learner:

    • Technology never stops evolving, and neither do awesome programmers. If you want to love your career in programming, you’ve got to love learning first.

Before I end this post, let me be clear that by no means do I believe any of the above qualities are unique to the set of people known as “programmers”. In fact, anyone can learn to program. More importantly though, anyone can learn the skills it takes to be an awesome person. I’m just really happy to find that learning both of these in parellel go so nicely hand in hand.

JavaScript: The Honey Badger of Programming Languages

After spending six weeks in Ruby land, last week was all JavaScript all the time at The Flatiron School. I feel like I’ve just added a hammer with superpowers to my programming tool box. You might bend a few nails along the way, but you can build almost anything with it.

Also, JavaScript is weird. Although it cares a lot about semi-colons, there are some important ways in which, just like the honey badger, it just doesn’t seem to care at all. Here I will attempt to get comfortable with this strange new animal by diving deep into some of its more surprising aspects. To provide some contrast and context, especially for those who (like myself) are more at home with Ruby, I’ll make some comparisons as I go along.

Scope

Let’s dive right in. For comparison, here is some Ruby:

javascript-ruby-comparison/ruby.rb
1
2
3
4
5
6
7
dog = 'Fido'

def bark
  puts "#{dog} says woof"
end

bark

In Ruby, a method is a scope gate, so dog is not defined in the bark method. Ruby will tell you this in no uncertain terms:

1
2
3
4
[18:12:24] javascript-ruby-comparison
♥ ruby ruby.rb
ruby.rb:4:in `bark': undefined local variable or method `dog' for main:Object (NameError)
 from ruby.rb:7:in `<main>'

On line 4, Ruby has no idea about what dog is, because the universe in line 4 is the local scope of the method bark. This scope gate can be very nice, since it means we cannot accidentally overwrite a variable we defined in the global scope from within a method. In order to make dog into a global variable that we can access inside the method, Ruby requires us to be very explicit about it, putting a $ in front of that variable both where it is defined and wherever it is referenced:

javascript-ruby-comparison/ruby.rb
1
2
3
4
5
6
7
$dog = 'Fido'

def bark
  puts "#{$dog} says woof"
end

bark

Now we clearly see that we are playing with a global variable, and Ruby plays along:

1
2
3
[18:32:01] javascript-ruby-comparison
♥ ruby ruby.rb
Fido says woof

While JavaScript does have a concept of functions creating a new scope, variables assigned outside of those functions can easily be accessed from within:

javascript-ruby-comparison/javascript.js
1
2
3
4
5
6
7
var dog = 'Fido'

function bark(){
  console.log(dog + ' says woof');
}

bark();

JavaScript doesn’t care if you want to reach outside the function’s scope to grab a variable. JavaScript functions have knowledge of the universe around them:

1
2
3
[18:38:34] javascript-ruby-comparison
♥ jsc javascript.js 
--> Fido says woof

So what else can you do with a variable defined outside a function from within a function? As it turns out, JavaScript will let you do whatever you want:

javascript-ruby-comparison/javascript.js
1
2
3
4
5
6
7
8
9
10
var dog = 'Fido'

function bark(){
  dog = 'Spot'
  debug(dog + ' says woof from within the function');
}

debug(dog + ' says woof outside of the function');
bark();
debug(dog + ' says woof after the function is called');

What happened to Fido?

1
2
3
4
5
[20:47:14] javascript-ruby-comparison
♥ jsc javascript.js 
--> Fido says woof outside of the function
--> Spot says woof from within the function
--> Spot says woof after the function is called

Looks like the name change was permanent. And by the way, by always using var, we can prevent such dangers:

javascript-ruby-comparison/javascript.js
1
2
3
4
5
6
7
8
9
10
var dog = 'Fido'

function bark(){
  var dog = 'Spot'
  debug(dog + ' says woof from within the function');
}

debug(dog + ' says woof outside of the function');
bark();
debug(dog + ' says woof after the function is called');
1
2
3
4
♥ jsc javascript.js 
--> Fido says woof outside of the function
--> Spot says woof from within the function
--> Fido says woof after the function is called

By using var within the function, we created an entirely different dog and did not alter the original.

Arity Schmarity

Before we go any further, I must admit that hadn’t heard the word arity until I crossed paths with JavaScript. I reckon I’m not alone in this, so here’s a definition courtesy of Wikipedia:

In logic, mathematics, and computer science, the arity of a function or operation is the number of arguments or operands the function or operation accepts.

OK. This sounds like something I know from Ruby land. Here’s a familiar example:

javascript-ruby-comparison/ruby.rb
1
2
3
4
5
6
class Dog
  def initialize(name)
    @name = name
  end

end

According to the above definition, the initialize method of the Dog class takes exactly one argument. You could say its arity is one (more commonly, this is known as a unary function).

Ruby cares about arity, and will give you very nice error messages to make you aware of this:

1
2
3
4
5
6
7
8
2.1.2 :002 > require 'ruby.rb'
 => true 
2.1.2 :003 > fido = Dog.new
ArgumentError: wrong number of arguments (0 for 1)
 from /Users/rose/Development/code/javascript-ruby-comparison/ruby.rb:3:in `initialize'
 from (irb):3:in `new'
 from (irb):3
 from /Users/rose/.rvm/rubies/ruby-2.1.2/bin/irb:11:in `<main>'

I tried to make a new Dog with 0 arguments, and Ruby was expecting 1. So Ruby blew up. This is arity checking at work.

JavaScript does not care about arity! Here’s photographic proof (this is a lot easier to see in the browser’s JavaScript console):

images

To review what just happened:

  • I made a constructor function for Dog (yeah, functions are really all-purpose in JavaScript, so that right there was a class definition of sorts).
  • In this constructor function, I said that Dog takes a name.
  • I made a new Dog, fido, and did not pass in any arguments.
  • JavaScript did not blow up.
  • Just to be sure, I asked JavaScript to show me fido.
  • JavaScript returned a Dog object with a name of undefined.

Whenever it can, JavaScript will try to help you out, whether you want it to or not. If you say a Dog has a name and then forget to give it one, JavaScript will trust that this was your intent and will throw in an undefined rather than yelling at you.

Teaching Old Dogs New Tricks

Ruby cares about defining an object’s attributes and behaviors up front. Objects in Ruby behave in consistent and predicatable ways.

Using our prior definition of the Dog class, Ruby will let us know that we haven’t taught Dogs to bark yet:

1
2
3
4
5
6
7
8
2.1.2 :001 > require 'ruby.rb'
 => true 
2.1.2 :002 > fido = Dog.new('Fido')
 => #<Dog:0x007f9fd5757c78 @name="Fido"> 
2.1.2 :003 > fido.bark
NoMethodError: undefined method `bark' for #<Dog:0x007f9fd5757c78 @name="Fido">
 from (irb):3
 from /Users/rose/.rvm/rubies/ruby-2.1.2/bin/irb:11:in `<main>'

Of course! We did not define a bark method, so we get a predictable NoMethodError.

JavaScript doesn’t care about defining all of an object’s attributes and behaviors up front, and pretty much lets you do whatever you want, whenever you want. Here’s a continuation of the console session above:

images

  • I asked fido to bark, having never defined a bark function or attribute. JavaScript quietly returned undefined.
  • I told JavaScript to give fido.bark the value of 'woof', and JavaScript happily obliged.
  • Now not only can fido bark, but the Dog object that is fido has been fundamentally altered, now containing a new bark attribute!

So, can all Dogs bark now?

images

No, they cannot. Now the definition of Dog is a bit of a mess - fido is a Dog that can bark, while spot can’t. The very nature of Dog-ness has been brought into question, and JavaScript is fine with all of this. No errors, no complaining. For better or for worse.

Playing with Global Scope

This one is extra weird, so get ready.

In the hierarchy of Ruby objects, main is the top level:

1
2
3
4
5
6
♥ irb
2.1.2 :001 > self
 => main 
2.1.2 :002 > self.class
 => Object 
2.1.2 :003 > 

I don’t know why you’d want to mess with main, and Ruby makes certain it’s not easy to do so (in fact, it’s impossible to do so by accident):

1
2
3
4
5
6
7
8
9
2.1.2 :003 > self.name
NoMethodError: undefined method `name' for main:Object
 from (irb):3
 from /Users/rose/.rvm/rubies/ruby-2.1.2/bin/irb:11:in `<main>'
2.1.2 :004 > self.name = "Rose"
NoMethodError: undefined method `name=' for main:Object
 from (irb):4
 from /Users/rose/.rvm/rubies/ruby-2.1.2/bin/irb:11:in `<main>'
2.1.2 :005 > 

Want to mess with the top-level object in JavaScript? Go right ahead, JavaScript doesn’t care!

1
2
3
4
5
6
7
8
9
>>> this.name
undefined
>>> this.name = "Rose"
Rose
>>> this
[object global]
>>> this.name
Rose
>>>

I just named the global object after myself, and JavaScript did not care one bit. This example is a bit contrived, but believe me that some undesireable things can happen if you don’t watch out for global assignment. Here’s a (slightly) less contrived example:

javascript-ruby-comparison/javascript.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function Dog(name){
    this.name = name;
    this.hunger = true;
    this.bowl = 'full';
}

Dog.prototype.checkNeeds = function() {
    if(this.hunger === true){
        (function feed(){
            this.hunger = false;
            this.bowl = 'empty';
        })();
    } else {
        (function play(){
            this.hunger = true;
        })();
    }
};

var fido = new Dog('Fido');

debug(fido.hunger);

fido.checkNeeds();

debug(fido.hunger);
debug(this.hunger);
debug(this);

If I run this code, here’s what my debug statements reveal:

1
2
3
4
5
♥ jsc javascript.js 
--> true          // fido was born hungry
--> true          // after calling checkNeeds(), he's still hungry...
--> false         // ...but this isn't hungry...
--> [object global]   // because we fed the global object instead of fido!

As you can see, Bad Things can happen when the global object is always available. Fortunately, there is a way for you to make JavaScript care about this! You just have to tell JavaScript to use strict.

javascript-ruby-comparison/javascript.js
1
2
3
4
'use strict';

function Dog(name){
  // the rest of my code...

Now, when we run the code, JavaScript will blow up just the way we want it to!

1
2
3
4
5
6
♥ jsc javascript.js 
--> true
Exception: TypeError: Attempted to assign to readonly property.
feed@javascript.js:12:17
checkNeeds@javascript.js:14:11
global code@javascript.js:24:16

The Moral of the Story

This was a long post, and it probably could get longer. But I think this is enough to chew on for now. The bottom line is that JavaScript has some crazy ways, but these ways are not unlearnable, and the reward for learning them is a much saner coding experience. If you understand the quirks, remember your vars, and always use strict, you and JavaScript can be unstoppable, just like the honey badger.

images

Flash Messages With Sessions in Sinatra

Sinatra is a DSL (domain specific language) for building small dynamic web apps with all the beauty of Ruby and without the bulk of Rails. Recently, my Flatiron School classmates and I built a simple playlist app that allows users to perform all the basic CRUD operations on songs - you can create, retrieve, update, and destroy them. Emulating RESTful routes for these actions (à la Rails), I created something like the following:

app/controllers/songs_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class SongsController < ApplicationController

  get '/songs' do
    @songs = Song.all
    erb :"songs/index"
  end

  get '/songs/new' do
    erb :"songs/new"
  end

  post '/songs' do
    @song = Song.create(params[:song])
    redirect :"/songs/#{@song.id}"
  end

  get '/songs/:id' do
    @song = Song.find(params[:id])
    erb :"songs/show"
  end

  get '/songs/:id/edit' do
    @song = Song.find(params[:id])
    erb :"songs/edit"
  end

  post '/songs/:id' do
    @song = Song.find(params[:id])
    @song.update(params[:song])
    redirect :"/songs/#{@song.id}"
  end

end

With the corresponding models and views that make these routes real, a working web app was born. Pretty darn cool. But there was a feature in the spec that was still left to add, and it became a bit of a challenge:

Whenever a song is created or updated, the user should see a message like this:

images

Here’s what I wanted to achieve:

  • The user fills out the form at songs/new and clicks ‘Submit’.
  • The newly created song’s show page at songs/:id is rendered with a success message.
  • The user reloads the page (or navagates away and back), and *poof* the success message is gone.

In order to get this to work, I would have to somehow pass a message from one action in the controller to another. The create (or update) action would have to pass a message along to the show action which would pass this message along to the view. It would be nice to have something like an envelope called success_message that could hold one of three values at any given time:

  • "Successfully created song." (right after the song is created)
  • "Successfully updated song." (right after the song is updated)
  • nil (immediately after the success message is rendered in the view)

According to this vision, I was able to put some yet-to-be-functional code in songs/show.erb:

1
2
3
4
5
6
<!-- this bit of code at the bottom of the page would reveal the contents of the success message if it isn't nil -->
<% if @success_message %>
  <div id="success" style="border: 2px solid green;">
  <%= @success_message %>
  </div>
<% end %>

But how would @success_message, which would have to be definied in the show action in order for the show page to know about it, be able to hold a message the was created in another controller action (create or update)?

I knew that params is one such data object that holds values that can be passed from one action to another, but as it is already the envelope for carrying and delivering form data entered by the user, it didn’t seem like the right place for a success message to live. If only there was some other vessel, like params, but not…

There is. It’s a session! It becomes available to you as soon as you put this in your application controller:

1
2
3
4
5
class ApplicationController < Sinatra::Base
  ...
  # add this line to enable the magic
  enable :sessions
end

Once you’ve added that, you get this handy little object called session that you can access in any of your controllers, which can in turn pass along any value it contains to a view. Just to see what it looked like before doing anything with it, I put a binding.pry inside my index action in songs_controller.rb, fired off shotgun, and loaded the index page on my local server. Here’s what pry spat out when I asked it what session was:

1
2
[1] pry(#<SongsController>)> session
=> {"session_id"=>"857d0d856ee646d76204c1138cf57fc497f80ffd85fef19befdbb26f60f8e022", "csrf"=>"598119612cef0d88134413ddd54bad52", "tracking"=>{"HTTP_USER_AGENT"=>"7be1a42d74a413474898ddb9adfef9a5a84719e3", "HTTP_ACCEPT_LANGUAGE"=>"66eae971492938c2dcc2fb1ddc8d7ec3196037da"}}

Here it is again, split up onto several lines for readability:

1
2
3
4
5
6
7
8
{
  "session_id"=>"857d0d856ee646d76204c1138cf57fc497f80ffd85fef19befdbb26f60f8e022",
  "csrf"=>"598119612cef0d88134413ddd54bad52",
  "tracking"=>{
      "HTTP_USER_AGENT"=>"7be1a42d74a413474898ddb9adfef9a5a84719e3",
      "HTTP_ACCEPT_LANGUAGE"=>"66eae971492938c2dcc2fb1ddc8d7ec3196037da"
  }
}

So that’s our session object, before we’ve done anything with it. Inside it there’s "session_id", a unique key that lives inside your cookie for the life of your session. What else is in there? Having just learned about preventing cross-site request forgery, I presumed "csrf"=>"598119612cef0d88134413ddd54bad52" to be the CSRF token. If you want to learn more about this (and you should!), read about it here. Finally there’s "tracking", which I believe holds information about the user’s browser. For our current purposes (creating a flash message), we don’t need to care about these values, but it helps to see how session is structured and what kinds of things it can contain.

Let’s move on and see how we can use this session object to help us with our success message.

Before doing anything to it, it would help to understand what kind of object session is. It looks like an ordinary Ruby hash, but in fact it is a special kind of Rack object. Why guess when you can pry it?

1
2
[2] pry(#<SongsController>)> session.class
=> Rack::Session::Abstract::SessionHash

As it turns out, the SessionHash object has a lot in common with a Hash object. 103 methods in common (out of 177 total), to be exact:

1
2
[3] pry(#<SongsController>)> session.methods.select{ |method| Hash.methods.include?(method) }.count
=> 103

One hash-like thing you can do with session is put new keys into it, with values that you can assign and change at your whim. And since the session persists from one HTTP request to another, it can pass values around from one action in the controller to another. This sounded like just the right object to hold the success message!

Here’s what I did (after enabling sessions, as shown above):

1) At the bottom of my create action (immediately before redirecting to the show page), I added a :success_message key to session, setting its value to the one-time message I want my users to see:

songs_controller.rb
1
2
3
4
5
6
7
  post '/songs' do
    @song = Song.create(params[:song])

    session[:success_message] = "Successfully created song."

    redirect :"/songs/#{@song.id}"
  end

2) I did the same thing for my update action:

1
2
3
4
5
6
7
8
  post '/songs/:id' do
    @song = Song.find(params[:id])
    @song.update(params[:song])

    session[:success_message] = "Song successfully updated."

    redirect :"/songs/#{@song.id}"
  end

3) Then, I added some code at the top of the show action to pass this message along so it could be rendered by the erb template in the view, and to ensure that the message is immediately set to nil so it will only render once:

1
2
3
4
5
6
7
8
  get '/songs/:id' do
    @song = Song.find(params[:id])

    @success_message = session[:success_message]
    session[:success_message] = nil

    erb :'songs/show'
  end

Now my success message behaves exactly as I imaged it should, appearing and disappearing at the appropriate times.

Due to the stateless nature of HTTP requests, had I simply used an instance variable @success_message inside these get and post actions, any value assigned to it would have been instantly forgotten the moment another request was made. The @success_message inside the two actions would have in fact been completely out of each other’s scope. The session, however, is available across all actions.

This ability to fake statefulness in your controllers opens up a world of functionality other than flash messages, not the least of which is maintaining a user’s “logged in” state as they browse from one page to another. Without sessions, almost all of the interactions and transactions that occur over the Internet as we know it could not even happen.

So if you haven’t yet, sit down and get to know the powerful little session. It’s definitely worth prying into.

Join Tables in ActiveRecord: Complex Associations, Simple Code

Up until a few weeks ago, my entire coding toolbox consisted of a small sample of some built in Ruby methods. Two of these became blog post topics (#find and #slice), and one—the << method—became the central character of my first coding dream/nightmare, with reserved words while and true playing key supporting roles. I used these methods to write other pretty simple methods.

After just a few weeks at The Flatiron School, I’m quickly learning that building up complex programs, like web apps, can’t (or maybe really just shouldn’t) be accomplished by writing out method after method in one big file. You need the right structures and tools to create complex objects, persist them in a database, and express relationships between these objects. Using ActiveRecord, you get some really simple and powerful tools for all this that hide a huge amount of complexity away, allowing you focus on designing your app to do what you want it to do.

While ActiveRecord makes it easy to create models and associations, some of the concepts involved were hard for me to get my head around at first. One such concept was the join table. I ran up against a problem in need of a join table while working with my classmates on a lab involving modeling characters and actors.

In ActiveRecord speak, actors have many characters and a character belongs to an actor. Here, in all of its elegant simplicity, is how you’d create the models that express this relationship:

app/models/actor.rb
1
2
3
class Actor < ActiveRecord::Base
  has_many :characters
end
app/models/character.rb
1
2
3
class Character < ActiveRecord::Base
  belongs_to :actor
end

Now all we need are two tables (actors and characters) to make this association work. The characters table, being on the belongs_to side of the relationship, must have a column for the foreign key, actor_id. In ActiveRecord, this can be accomplished in remarkably few lines of code:

db/migrations/001_create_actors.rb
1
2
3
4
5
6
7
8
class CreateActors < ActiveRecord::Migration
  def change
    create_table :actors do |t|
      # ActiveRecord provides an id (primary key) column by default, for free!
      t.string :name
    end
  end
end
db/migrations/002_create_characters.rb
1
2
3
4
5
6
7
8
9
class CreateCharacters < ActiveRecord::Migration
  def change
    create_table :characters do |t|
      t.string :name
      # Here is where the magic happens. ActiveRecord knows that this references the actors table.
      t.integer :actor_id
    end
  end
end

This is the basic pattern you’d follow to model any has_many belongs_to relationship in ActiveRecord. What seems like “magic” here is made possible by ActiveRecord Ruby methods that either give our associated classes more methods that let them interact with each other, or wrap SQL statements and hide them away (in the case of migrations). But that is a topic for another post.

Back to actors and characters. As my classmates and I were creating these models, two big things came to the surface:

1) We could not recall any of Tom Cruise’s many characters’ names.

2) What happens when a character has more than one actor? One of my favorite characters would most certainly break our has many/belongs to association—The Doctor.

images

How can we fit The Doctor into our current schema??? The more I thought about it, the more impossible it seemed. Here is an illustration:

images

The above is our simple model, before The Doctor comes along and breaks everything. Just to be sure I was grasping how NOT to try to include The Doctor and his many actors, here is how it might look:

images

Our actors table seems fine, but our characters table is definitely not okay, and we haven’t even included the eight doctors from the first twenty-six seasons yet.

With our current setup, we have to change the entire schema every time we add another Doctor. This is very, very bad. A database was designed for adding lots of rows. Not so for columns.

In order to make things right, we need a different association: many-to-many. Actors have many characters, and a character has many actors. In order to set our database up for this association, we need a join table. First the visual:

images

Now for the migration (assuming your actors table is still intact and you’ve already removed all but the name column from characters):

004_create_actors_characters_join_table.rb
1
2
3
4
5
6
7
8
class CreateCharacterActorRelationships < ActiveRecord::Migration
  def change
    create_table :character_actor_relationships do |t|
      t.integer :character_id
      t.integer :actor_id
    end
  end
end

We also need to change our actor and character models. In order for the association to work, we need to somehow connect our actors and characters table through the character_actor_relationships table. The association we need in our actor and character models is has_many :through:

app/models/actor.rb
1
2
3
4
class Actor < ActiveRecord::Base
  has_many :character_actor_relationships
  has_many :characters, through: :character_actor_relationships
end
app/models/character.rb
1
2
3
4
class Character < ActiveRecord::Base
  has_many :character_actor_relationships
  has_many :actors, through: :character_actor_relationships
end

Finally, we need a model for CharacterActorRelationship:

app/models/character_actor_relationship.rb
1
2
3
4
class CharacterActorRelationship < ActiveRecord::Base
  belongs_to :character
  belongs_to :actor
end

Now we have the right associations and the right database schema to add all of the Doctors that ever were and ever will be throughout all time.

images