DEV Community

emi kojima
emi kojima

Posted on

RAILS Final Project: I HAVE THAT! (v.2)

Draft

RAILS Final Project: I HAVE THAT! (v.2)

For my Rails Final Project, I decided to convert my Sinatra Final Project app, I Have That!, into a Rails app and to add functionality that I wished that I had added when making this app using Sinatra.

I Have That! is a community lending app that allows users to sign up and list items they want to lend out to their community and borrow things from the list of available items. My hopes in creating this app are to help foster a more sustainable world through sharing the resources we already have and to create community with people who are willing to do the same who happen to live in your area. The Sinatra version of this app did not have a location attribute for the user, so users could not filter the list of items by location. This was a function that I wanted to add to the Rails version of this app. Another functionality I wanted to add was an ability to have each item belong to a category and to list items by category instead of having one big list of items.

In order to build out these functionalities, I first needed to decide on my models and their relationships. I did this with a pen and paper, making models with their attributes and deciding which models will have a belongs_to and which will have the has_many and has_many through relationship. After a few passes, I decided to have a User model, Item model, and Category model. The Item model would act as my join table and have the user_id and category_id attributes. The User model would have :username, :email, :password_digest (for has_secure_password), :state, and :city attributes. The Category model would have :name and :description as its attributes.

After I had drawn up my models and felt sure of them, I began the task of building my rails app. In my terminal, I ran rails new i-have-that-v2 to get the file structure of my rails app. After that, I added my models and built my migrations by running rails g migration name_of_my_migration to create my migration files. To fulfill the nested resources requirement, I decided that I would nest my Items in my Users. Which means that rather than having /items/new, I would have users/:id/items/new.

My routes.rb looks like this:

Rails.application.routes.draw do
  get 'auth/:provider/callback', to: 'sessions#create'
  get 'auth/failure', to: redirect('/')
  resources :categories
  resources :users, except:[:show]
  resources :users, only:[:show] do
  resources :items 

So, to make a new item (through my nested resource, I would have to pass in the user and the item to the form. It took me a while to figure out how to do this, but this is my Items Controller :new action code:

class ItemsController < ApplicationController
def new 
@user = find_user 
@item = Item.new(user_id: @user.id) 
end

After setting the @user and @item, I passed both of these variables into the item/new/htmll.erb form:

<%= form_for [@user, @item] do |f| %>
  <%= f.hidden_field :user_id %>
  <%= f.label :name %>
  <%= f.text_field :name %><br>
  <%= f.label :description %>
  <%= f.text_field :description %><br>
  <%= f.label :category_id, "Item Category" %>
  <%= f.collection_select(:category_id, Category.all, :id, :name, { :prompt => 'Select a Category' }) %><br>
  <%= f.label :available, "Check this box if this item is available for lending"%>
  <%= f.check_box :available %><br>
  Didn't see a category for your item? Create one <%= link_to "here:", new_category_path %><br>
  <%= f.submit %>
<% end %>

In this form, the f.hidden_field :user_id is a hidden field that is acting as the connector between the item and the user. When this form is submitted, this field will be in the params as item[:user_id] and its value will be assigned as the id of the @user in the creation of this item object.

I built all of my app and made sure everything was working before I added OmniAuth and I am so glad that I did this. This is because the biggest challenge that I had (and I had a lot of challenges completing this project!) was to get my OmniAuth Google to work. I tried installing OmniAuth google from this tutorial . I ran into problems right away when my omniauth google gem would not bundle. After a lot of help from an amazing TC (JENN!), we (and by we, I mean Jenn) figured out that to get omniauth google to bundle, we had to have the latest version of it specified in the gemfile (gem ‘omniauth-google-oauth2’, ‘~> 0.5.3’), unlike omniauth-facebook, which bundles just fine without specifying a version. The only other hiccup I ran into with OmniAuth Google was an error that kept popping up in my SessionsController.

The error kept saying that I did not have a method ‘env’ in this line of code: @user = User.from_omniauth(env["omniauth.auth"]); after some googling, I found a quick fix. All I had to do was add ‘request’ before the env: @user = User.from_omniauth(request.env["omniauth.auth"]);.

Once I got my OmniAuth working, I felt like I had just completed running a marathon and I took myself out for icecream and maybe I cried a little out of joy!

Here’s the video walkthrough of my project!

Thanks for reading.

Top comments (0)