Ruby on Rails banner

Days 6–8: Fixing Bugs, Adding Features

The rest of this series can be found here.

Over the weekend, I worked on this project on my wife’s laptop instead of my main machine, so ran into a couple of issues getting set up. First, rails wouldn’t run, but $ bundle install took care of that problem. Then I had to run $ rake db:migrate to get the database set up, but ran into similar issues as yesterday. At some point, I changed the name of the constant used to add the boolean field, but the migration file still had the old class name. Once I changed that, $ rake db:migrate ran just fine.

Next, I needed to add a few todo items to have some data to work with. For whatever reason, adding new todos worked fine on my main machine, but when I tried to add a new item, I was getting a “First argument in form cannot contain nil or be empty” error. Turns out I had never defined the “new” action in the controller. Took care of that and the app was back in business.


Adding some features

  • It only makes sense to be able to create and delete items from the main list of to-do items, so added that feature.
  • It also makes sense to sort the list into “open” vs. completed to-do items; time for a crash-course in Ruby conditional syntax—turned out not to be a very hard crash.
  • It also makes sense to have a one-click “complete” button on the list of items, but that is a bit tricky. The current method (going to the edit screen for that item) is a bit clunky.
    • My first thought was to build a `<form>` in the actions column for each item, complete with an `<input type=”hidden” name=”completed” value=”true”>` element, but realized that it would likely clear out the the other two fields.
    • My next thought was to add hidden inputs for the title and notes fields, but then the app is printing a bunch of hidden content, plus I’d have to come back and update the form here every time I added or changed fields. I possibly could extend the `_form.html.erb` partial for use here, but there’s still the “bunch of hidden unnecessary content” issue.
    • Time to try writing a custom route and controller action to update just the one field from a one-click button. Took some working through to get the syntax just right; more info below.

Custom Route and Controller Action

To accomplish the one-click update, I needed a new route pointing the PATCH method at a new controller action that would update the completed field. Here’s what I eventually came up with:

patch 'todos/:id', to: 'todos#complete': a new route that points the patch method to the complete action.

Speaking of the complete action in todos_controller.rb, here it is:

def complete
  @todo = Todo.find(params[:id])

  if @todo.update(completed: true) #updates just the completed field and ignores the rest
    redirect_to todos_path
  end
end

The only other change was updating the one-click link path and method: link_to '✓', todo_path(todo), method: :patch

One more enhancement

If we can have one-click completion, why not one-click “uncompletion” as well? No reason not to….

The only changes necessary were updating the link_to in the completed section and adding a wrapping condition to the complete action; it tests whether completed is true or false and toggles it.

At this point, I also added a backup: if the @todo.update call fails, then the app will render the edit screen, where the change can be manually made.

Screenshot

Just for fun, this is how the app looks right now: Ruby on Rails checklist app day 8


Wrap-up

I haven’t made as much progress the last few days as I had hoped, but ran into some interesting and fun challenges today.

Code

The code is located on GitHub here.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.