Rails: In The Pursuit Of Writing Boring Code
Putting RailsConf talks to use
I attended RailsConf in Phoenix last week. It was a wonderful experience even as introverted as I am. It was great meeting people I knew from their podcasts, DHH, fellow Flatiron students, and other developers during lunch. The talks were very informative and really got me thinking about ways I can be a better developer.
The first talk I attended was thoughbot’s Derek Prior’s In Relentless Pursuit of REST. The whole talk all I could think about is how I was doing everything wrong in my Schedule App. Well, not everything. There were plenty of places I did not use REST and now I was feeling awfully guilty about it. His closing three slides form a motto to code by: Be CRUDdy, Be Boring, Be RESTful.
I was again reminded about the importance of REST in michelada.io’s David Padilla’s talk Tips and Treats for New Developers.
Combining these two I have a new motto: Be CRUDdy, Be Boring, Be RESTful All the Time.
Time to get RESTful
My Schedule App that I have been building for my wife, has some very unRESTful practices. The schedules_controller
has a set_shifts
action to create and edit a schedule’s shifts. It also has actions add_employees
and remove_employees
for associating them with a schedule. There is a print_schedule
action for showing the schedule with minimal styling. The employees_controller
has an action for toggling their status. There is a lot to change but with full test coverage, I can go to town without worry of breaking something.
The schedules and shifts controllers
The first change is the one I thought would be the trickiest. Moving the set_shifts
from the schedules_controller
to the create
action in the shifts_controller
. This will be a two stage process. Step one, completed in this commit, was not as bad as I thought. It was essentially moving private methods, updating routes, and changing a few things in the views.
The index
action is basically a combination of new
and edit
. I have mixed feelings about this but ultimately think it is fine. When editing or creating shifts, it is being done in bulk. You are not visiting a page to create or edit one shift. It is being done for every single shift, every single day, every single employee. The index
action usually shows all the model, and this is all the shifts.
For step two of this process, I was thinking about splitting the create
action into create
and update
actions. This is another one I have mixed feelings about and may not make the change. When you click Set schedule
on a schedule’s show page, your form allows you to create and update shifts on the same page. Now that I think about it, you can also delete shifts at the same time. I will revisit this later for potential refactoring.
Adding and removing employees
After making the above changes, I was feeling pretty good about this one. Adding and removing employees from a schedule was creating and destroying the associations between the two. I would create an associate_employe_controller
with a create
and a destroy
action. This would handle the previous add_employee
and remove_employee
actions in the schedules_controller
.
This commit was pretty straightforward. It had the above changes, updates to the routes, and changes to the url paths in the view. All tests are passing so time to move to the next section.
Employee status toggle
Following the steps from the previous changes, I first started with the controller. I created status_controller
to handle the toggle functionality with its update
action. I moved the code over from the employees_controller toggle_status
action.
By default, all employees start with a status of active. This allowed me to use only the update
action to handle toggling an employee’s status. You can see the full commit here.
Print schedule
Alright, down to our final non-CRUDdy action! When you viewed a schedule, you could click the “Print schedule” button to see the print schedule page. It seems all well and good except that the page is exactly like the show schedule page minus the buttons at the top. It gets an added variable, @printable_view
, which hides all the employees’ availability slots. There was no reason to have this be a separate view.
In this commit, I removed the print schedule page, action, and route. Now when you hit “Print schedule”, a param called print: true
is passed into the show action which sets the @printable_view
variable. I now have the same functionality without what was essentially a duplicate page.
The other thing I did was change how the page renders buttons. The schedule show page has buttons for “Adding/Removing all employees”, “Set schedule”, and “Print schedule”. To control the viewable buttons, I created a couple of helper methods.
The which_buttons?
method shows the “Adding/Removing all employees” and “Set schedule” buttons if admin == schedule.admin && @printable_view.nil?
. The print_view?
method shows the “Print schedule” button only if @printable_view.nil?
.
The last thing I changed was in the print view. I had the words “Printable schedule” show at the top of the page where the buttons use to be. My test for this page would look for that text. I removed the text from the view and edited the test to expect the page to not have the test “Set schedule”. If the helper method is working, this will not show on the page.
All green
After each set of changes, my test suite was still green. Since I had 100% coverage, I could be confident is working. This was yet another great example why testing is so important. There is more work to be done on this app but I am feeling pretty good with it being RESTful.
Follow me on Twitter @thebrianemory. Follow me here, click the green heart to show some love, leave a comment, and get in touch!