MYYELP

A business review website.

An application that focuses on local business review and networking site.

  • Frontend
  • Backend
  • Ruby on Rails

Introduction

I came across one of the assignments while i was attending my coding school, and had an opportunity to challenge myself to build a website that could educate myself as well as get accustomed with Rubu on Rails’s performance.

MyYelp is a mocking website inspired by Yelp that intended to show the benefits of Ruby on Rails, it consists of basic CRUD functionality and integrated with Rspec tests.

Planning and research

The app stores data for users, businesses and reviews.
Thus, it also has the models and controller according to database tables.

Additionally, the app is implemented without devise gem, hence the controller needs sessions_controller to control user sign_in and sign_out action; which wouldn’t have any model associated with it, because there is no any table that needs to store data for users session.

Test

Test tools:

Integration Purpose
Rspec-rails controller test
shoulda-matchers rails library test
capybara integration-test
capybara-email integration mailer test
vcr record/capture api
database_cleaner reset test database
selenium-webdriver automated tests
fabricator Ruby object generator
faker Fake data for fabricator

The seed data uses fabricator and faker as well.

Development

Initially the site launches off with UI routes, UIcontroller and UI views design, which are available only for development environment.

Then, it is built with TDD; write tests, moving the view from UI into specified controller#action view, code up associated model and controller#action logic.

Find out more on how I normally work with TDD workflow.

App features

The app is a CRUD application which its routes point to controllers that associated with model for user, review and business as shown below.

# config/route.rb
Rails.application.routes.draw do
  root to: 'reviews#index'
  get 'ui(/:action)', controller: 'ui'

  get '/signup', to: "users#new"
  resources :users, only: [:create, :show]

  get '/login', to: "sessions#new"
  resources :sessions, only: [:create]
  
  get '/logout', to: "sessions#destroy"

  resources :businesses, only: [:index, :show, :new, :create] do
    resources :reviews, only: [:new, :create,:edit, :update] 
  end

  resources :reviews, only: [:index]
end

landing page; /, is responsed by reviews#index, which shows the 10 most newest reviews from our users.

signup for new user; /signup implemented with new action from users controller, the server will response by rendering new view from users.

When users submit the form, users controller create action will handle the POST request at users/create(generated by resources), addtionally, Rails logic in User model will take care of :users parameter validation.

Similary with /login, but with sessions controller instead.

Without model, the POST request params are handled by bcrypt validation, if succeed, will set user session.

resources :users is a Rails helper, which will generate url relative to the action accordingly.

In this case, resources is for a show action which will generate /users/:id, as a result, allowing us to pass in :id as params[:id] in our usersController, then we can query for specified user info with User model and params[:id] and display in our view.

params[:id] could be anything; id, username or token.

# look for a record with params[:id] as username
def show
  @user = User.find_by(username: params[:id])
end

Rails by default call to_param method to link_to view helper(rails helper method to genearte <a>..</a> tag in Rails view), which returns a model’s instance id, overwrite to_param method in the model to return a different value.

#app/models/user.rb
class User < ActiveRecord::Base
  validates_uniqueness_of :username
  #... other code

  def to_param
    #call username method to User's instance
    #which will return an instance's username 
    username
  end
end

logout will send GET request to sessions controller destroy action.

Response for destroy action will set user session to nil

businesses controller has index, show, new and create actions, which implement by Rails resources helper, and will generate /businesses, /businesses/:id, /businesses/new and /businesses/create

The /businesses path is responsed with business#index which will show the most 10 newest created business.

/businesses/:id is responsed with business#show, and will render show template with a business instance variable find from params[:id]

#app/controllers/businesses_controller.rb
class BusinessesController < ApplicationController
  #...other code

  def show
    @business = Business.find(params[:id])
  end
end

/businesses/new will render a new business template, after submited will posted to /businesses/create

Business ratings system is created with checkbox, and Rails form helper, when posted the star ratings will be posted as business[:rating] param.

resources:reviews route that nested inside resources:businesses route will generate url that takes two parameter; :business_id and :id, the later param would detemine from the most inner resources(reviews).

businesses/:business_id/reviews/new sends GET request to reviews#new controller, which will reponse with reviews new template.

businesses/:business_id/reviews/create sends POST request to reviews#create controller, after the server validates the POST params from the submited form and makes changes to the database, reviews#create will send back a response; in this case redirect_to businesses/:business_id url.

reviews#edit and reviews#update are similar with reviews#new and reviews#create, except the reviews#edit action has to look for the data and display in the edit template when responsed back from GET request, after the form submission(POST to the server with edited params), the reviews#update will validate and response back accordingly.