I have built my second original web app! My eWorm Rails Web App was again inspired by my lovely wife who is a high school English teacher. She has been using Goodreads with her students to find books to read and review books they have already read. I decided to work on my own version to see what I could do with Ruby on Rails.

This web app is basic but has more features than my first web app. I again tried to make it user-friendly and somewhat visually appealing. I found a cute bookworm image and decided to use him as my mascot for this project.

One of the focuses of this project has been keeping code DRY(don’t repeat yourself). To this end, I tried a number of things to clean up my code but not everything worked as I hoped. For instance, I tried to encapsulate the check for a current_user vs guest like this:

class BooksController < ApplicationController
  # more methods ...
  def redirect_guests
    if logged_in?
      flash.alert = "You must be logged in to add a book."
      redirect_to new_user_session_path
    end
  end
end

I then placed a redirect_guests at the start of controller actions where I didn’t want guests to have access. This made sense to me! However, I found out that redirect_to does not skip the rest of the code in the controller action method and so this throws a rails error. The rails error message provided a clue, Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return". So, I tried adding and return but this didn’t work. I tried this with my if statement directly in my controller action method and it worked! So, it seems that the return command needed to happen directly in the method I want to exit early. I thought about it and realized I could shorten my redirect_guests method to just the message and redirect I wanted. Then, I thought I just return redirect_guests when no one was logged in. Bingo!

class BooksController < ApplicationController
  def create
    return redirect_guests unless logged_in?
    # create book and redirect_to the book show page
  end

  def redirect_guests
    flash.alert = "You must be logged in to add a book."
    redirect_to new_user_session_path
  end
end

OK, so then I wondered how I could apply this to my reviews controller. I copied over the private redirect_guests method and put my clever little return redirect_guests unless logged_in? in the new, create, edit, and update action methods. Oh yeah! Wait, can’t I share this redirect_guests method between controllers? Of course, so I put it in my ApplicationController where my reviews and books controllers are inheriting from. Nice and DRY!

I implemented all the many requirements of this project one by one. I used devise for secure user login, the Twitter OmniAuth gem for logging in with Twitter, HTML 5 Datalists for my book form, and more!

To test my app, I employed a suite of available gems. I used Faker to create seed data. The RSpec-rails gem coupled with Shoulda and FactoryGirl made testing much easier! This was my first shot at creating a large test suite. I learned quite a bit and found it really useful to run my tests while refactoring my code and adding features. It helped me catch a bunch of errors and loopholes quickly and without having to run my app and click around. I definitely now see the power of test-driven development.

I really have learned a lot here and this was quite fun! I posted a walkthrough video where you can see the user interface. I cannot wait to move forward and continue my adventure with Learn Verified.