Reflections — My first Rails Application

Milan Parmar
3 min readDec 14, 2020

--

Reflections Login Page utilising Facebook OmniAuth

What a journey! Rails has been quite the framework that has put me on some challenging roads however I am grateful for all that I have learnt and applied.

As with every project/app, I begin with what purposeful application I would like to build. I wanted to create an application that allows users to sign up, add their inspirational/spiritual books to their profile and finally add their reflective thoughts on these books.

Which models and attributes do I need then? Simple: User, Books & Reflections.

A user would have many books, many reflections and many “reflected” books through reflections.

has_many :owned_books, foreign_key: :owner_user_id, class_name: "Book"
has_many :reflections, foreign_key: :reflection_user_id
has_many :reflection_books, through: :reflections

A books would belong to a user, have many reflections and many “reflection” users through reflections. I also included a has_one_attached :image in order to upload a book cover image for each book.

has_one_attached :image
has_many :reflections, foreign_key: :reflection_book_id
has_many :reflection_users, through: :reflections
belongs_to :owner_user, class_name: "User", optional: true

A reflection would belong to both a user and a book.

belongs_to :reflection_user, class_name: "User"
belongs_to :reflection_book, class_name: "Book"

After creating the database and association models, I moved onto the routes that are required and then I worked on my controllers. Working on the controller methods, I saw a lot of repetition and we all know the drill…DRY! So, I either created before action methods under private and helper methods in my application_controller.rb file.

For example, in my User controller:

class UsersController < ApplicationController
...
before_action :set_user, only: [:show, :edit, :settings, :destroy]
...

private
def set_user
@user = User.find(params[:id])
end
def access_self
if @user = current_user
@user
end
end
def user_params
params.require(:user).permit(:username, :password, :email)
end
end

I had to deal a lot with form_for which is a brillant helper to create forms requiring models. Form_for is pretty neat when dealing with validation errors as you can simply call the instance variable with .errors to get standard error messages. Apart from form_for, I also saw many button_to helpers across my application. DRY, DRY, you guessed it…DRY!

I had to find a way to clean up my app and so used partials to help me access embedded ruby code across my erb files and create helper methods, where necessary.

I must admit, that the scope method took a lot of thinking power as I seemed to over complicate what I was trying to achieve. My aim was to join the reflections table with my users > access every user that has at least one reflection > show the user’s in descending order from the time they were created > show the particular user with the book that they just reflected on. Well…yeah 🙃 So instead I did:

scope :with_reflections, ->{ joins(:reflections).order(created_at: :DESC) }

Which does everything I wanted except for showing the particular user with the book that they just reflected on. I can live with that, not too bad. 😁

I love the idea of nested routes and objects. What a brilliant way of associating objects smoothly. First step: create the nested routes:

(In my case)

resources :books do
resources :reflections, only: [:new, :edit, :show]
end

Next, using build within my controller to associate the reflection with the book:

@reflection = @book.reflections.build

Then, seeing the lovely URL e.g.,

http://localhost:3000/books/42/reflections/39

I saw many similarities with Sinatra and at times, I was extremely lost when hands on with the project but what a great way to learn hey — being stuck and tackling through it! I’m looking forward to the next project and creating other rail web applications! 💻

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Milan Parmar
Milan Parmar

Written by Milan Parmar

Software Engineer 👨🏽‍💻 | Full Stack Web Development 💻 | Smartphone Tech Enthusiast📱

No responses yet

Write a response