Why do this?
As usual, we'll start with why. Why do this to our existing Ruby on Rails application? There are several reasons:
- We always keep our Ruby on Rails application up to date. Starting from Rails 5.1.0, rails-ujs is a part of the Rails itself.
- We hate duplication. Why should we keep using jquery-rails (the gem for jquery-ujs) if Rails itself already has the rails-ujs with similar functionality?
- We love to keep our Gemfile clean. We drop any gem that we don't use anymore. Jquery-rails is one of them.
- Last but not least, we love to keep everything simple
Recommended requirement
Before migrating from jquery-ujs to rails-ujs, we recommend the Ruby on Rails application has the following:
- Integration tests. In our project, we use capybara and selenium, with some headless browsers.
- Unit tests. We use RSpec for this.
- Supported Rails version. At the time we did this, we've upgraded our Rails version to 6.0.2.1
- Latest ruby version. We used 2.6.5 when we migrated long ago.
- Make sure all the gems in Gemfile are up to date.
So, let's get into the steps on how to migrate from jquery-ujs to rails-ujs.
1. Clean up all unofficial calls to jquery and jquery-ujs
Then, move it to application.js
//= jquery
//= jquery_ujs
2. Replace jquery-ujs with rails-ujs
3. Decide keep or remove jQuery itself
In our project, we decide to keep it and upgrade it to jquery3. The rails-js itself doesn't use jQuery as a dependency. So, it's possible to get rid of jQuery from your Rails project.
4. Fix any error shown on the failed integration tests
It is the most interesting but also the trickiest part. It will vary from project to project. Based on our experience, here are what we do:
- Replace the trigger() with the native Javascript click()
- Put the require("@rails/ujs").start() at the top of app/javascript/packs/application.js once we migrate from Sprocket to Webpacker
- Since we decide to use jQuery3, there is no more adjustment needed on the AJAX call. But if you decide to drop jQuery too, you'll need to look into Rails UJS event handler here.
- We have problems with Bootstrap modal not showing on the integration tests, but it's showing on manual test. Our deep investigation shows us we need to do step 1 above.
- Besides that, for unknown reasons, the click_link function of Capybara doesn't work to trigger the Bootstrap modal. For such cases, we have no choice but to stick with execute_script function.
- We also add id attribute for every link or button we use to trigger the Bootstrap modal. This simplifies the codes in our integration tests to target the element easily. This way we can use such neat codes: click_link("element-id")
Final Notes
- Migrating from jquery-ujs to rails-ujs isn't a difficult task. Though we can't consider it's easy either.
- If you have so many jQuery dependencies, it's better to use both jQuery and rails-ujs as we do.
- If your existing application doesn't have any integration test, we'll recommend you to prioritize building one first. Otherwise, you'll mess up many things without anyone in your team realize it.