Now with 100% more AJAX
In this post I’ll do a deep dive into how and why I refactored each feature.
This was the first feature I tackled. Originally, when a user created a comment, the page would refresh and Rails would render the new comment to the comment feed on the task page. To edit a comment, a user would have to click on the edit button, which would take them to the comment edit page. The user could then edit the comment text on this page. On submission they would be redirected to the task page. This step is unnecessary and doesn’t make for a good user experience.
The refactored Comment CRU process users AJAX for a more dynamic and seamless user experience. When a user creates a comment, a few things happen:
– The form’s default behavior is prevented
– Form values are serialized and (along with the URL) are passed to another function
– The next function executes an AJAX POST request to the appropriate controller action with the arguments
– Rails creates a new Comment in the database, and renders a JSON response
– On success, a new Comment object is created with the response
– The Handlebars template is rendered with the Comment attributes and injected into the page via JQuery.
Note: the Handlebars templates are compiled on page load, so they are ready for use when the AJAX requests are submitted.
Submitting the newly rendered form sends an AJAX POST request to the application. Much like when we created the first comment, another Comment object is created with the response. The first Handlebars template is rendered with the Comment attributes and then injected back into the page.
Notes function similarly to Comments, however there are a few differences. On the Notes index page, only Note titles are rendered by Rails. When a user clicks “View”, the Note content is loaded to the page via an AJAX GET request. Once loaded, the user can edit the Note content and title in place (similar to Comments). Form information is submitted via an AJAX POST request. It is then rendered on the page via an AJAX GET request and a Handlebars template.
For Tasks, I focused on the refactoring the filtering options. In the first version of RailsPM, filtering was hacked together using individual routes, controller actions, and views. For example: Viewing all complete project tasks required it’s own route, controller action, logic, and rendered view. This solution is not flexible, scalable, or good for the user experience. User also didn’t have the option to sort by whether they were a task owner or assigned to a task, which is critical.
The refactored Task filtering uses AJAX, JQuery, and Handlebars templates to render JSON responses. I used this solution for both the All Tasks view and Project Tasks view.
I started by upgrading the filter buttons to use AJAX requests so the appropriate tasks would be loaded onto the page, instead of sending the user to an entirely new page. After I figured out how to load the tasks using AJAX, I decided the entire filtering system would make more sense if it was a form instead of buttons tied to specific routes, actions, and views.
The filtering buttons have been replaced with a form. This form submits an AJAX GET request to the application. For each task in the response, a Task object is created, rendered into a Handlebars template, and injected into the page using JQuery. I’m not completely happy with the logic I used for the form filtering but it’s flexible enough that I could add more filtering options without too much work. In the future I would like to revisit this and see how I can make the logic cleaner and more flexible.
I applied the same filtering process for tasks to projects. At this point, I already switched over to using the forms so I was able to quickly implement this; however, since project collaborators and assigned task users are different, I used different functions and methods. However, the base functionality is the same: the form parameters are sent to the application via an AJAX POST request, and the server responds with JSON. For each project in the response, a Project object is created and a Handlebars template rendered with that Project’s attributes. It is then injected into the page using JQuery.
I also scrapped the admin system I had previously developed and used ActiveAdmin instead for the admin panel.
Any feedback or suggestions? Leave them in the comments below or shoot me an email at firstname.lastname@example.org.