I’ve recently been working on a couple Rails 4 applications. I tend to be a hands-on learner, while I have been reading Andy Lindeman’s book Upgrading to Rails 4, most of my learning has come from working on applications (and begging Andy for help when I get stuck). Deprecation warnings help greatly in figuring out changes to Rail’s API, but new features such as Turbolinks can prove to be a little trickier to understand, especially when they just seem silently work.
As the README states:
My first run-in with Turbolinks was when I was trying to add click events to elements on the page for a rating feature. I was using jQuery so my CoffeeScript was similar to this:
jQuery -> $("span.star").on "click", -> ... code dealing with ratings ...
This code worked perfectly while I was developing this rating feature because I was directly loading the page. However, my rating feature was not working when I navigated to this feature from another page. This is because when I clicked on the link to thepage with the feature Turbolinks loaded the page. There was no document ready event fired, so the above code wasn’t executed; therefore my rating feature wasn’t working.
In reading about Turbolinks, the first solution to catch my eye was to simply disable Turbolinks on the link to the page with my rating feature. At this point I had already spent a fair amount of time on my rating feature. I was ready to move on to something else so I chose the following method to get my feature working:
= link_to "My rating feature", rating_feature_path, "data-no-turbolink" => true
While this worked, I was kind of bummed about having to disable Tubrolinks. I took a look at Andy’s book to see if he had a better solution; and he did! I removed the data attribute on the link disabling Turbolinks. Then I refactored my CoffeeScript to to use the pattern Andy recommend in his book. Now my code looks something like this:
attachRatingHandler = -> $("span.star").on "click", -> ... code dealing with ratings ... $(document).ready attachRatingHandler $(document).on "page:load", attachRatingHandler
Now the code works with Turbolinks. The “page:load” event will be triggered with Turbolinks loads a page. The “ready” is still needed for when the full page is loaded.
UPDATE: A Better Solution
After I published this article Simon Courtois pointed out that we could simplify the code above using JQuery’s
on method. Using this method to simplify our code we end up with something like:
attachRatingHandler = -> ... code dealing with ratings ... $ -> $(document).on 'click', 'span.star', attachRatingHandler
Aside from learning about how Turbolinks works, I also learned that I should probably spend a little more time reading about the changes to Rails in Rails 4. I could have probably saved a fair amount of time if I had understood how Turbolinks worked up front.