Skip to content

Instantly share code, notes, and snippets.

@MaiAbuthraa
Last active November 24, 2020 11:26
Show Gist options
  • Save MaiAbuthraa/58f6fe89f76cfd297d83ed130f4c8391 to your computer and use it in GitHub Desktop.
Save MaiAbuthraa/58f6fe89f76cfd297d83ed130f4c8391 to your computer and use it in GitHub Desktop.
Rails Best Practices
## The first exercise: Fat Model Skinny Controller
# Fat Model, Skinny Controller: refers to how the M and C parts of MVC ideally work together.
# Namely, any non-response-related logic should go in the model, ideally in a nice, testable method.
# Meanwhile, the “skinny” controller is simply a nice interface between the view and model.
# Chaeck this artical: https://dev.to/kputra/rails-skinny-controller-skinny-model-5f2k
#### Bad Code ####
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
# share this in your wall
def reshare
post = Post.find(params[:id])
if post.user == current_user
flash[:notice] = "Sorry, you can't reshare your own post"
elsif post.reshare.where(user_id: current_user.id).present?
flash[:notice] = "You already shared this post"
else
new_post = Post.new
new_post.status = "Share #{post.user.name} #{post.status}"
new_post.origianl_post = post
new_post.user = current_user
new_post.save
flash[:notice] = "Succesfully shared"
end
redirect_to post
end
end
#### Good Code / V1 ####
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
def reshare
post = Post.find(params[:id])
flash[:notice] = post.posted_by(current_user)
redirect_to post
end
end
# app/models/post.rb
class Post < ActiveRecord::base
def posted_by(user)
if self.user == user
"Sorry, you can't reshare your own post"
elsif self.reshare.where(user_id: user.id).present?
"You already shared this post"
else
# this is not good code
new_post = Post.new
new_post.status = "Share: #{self.user.name} #{self.status}"
new_post.origianl_post = self
new_post.user = user
new_post.save
"Succesfully shared"
end
end
end
#### Good Code / V2 ####
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
before_action :set_post, only: [:reshare]
def reshare
flash[:notice] = @post.posted_by(current_user)
redirect_to @post
end
private
def set_post
@post = Post.find(params[:id])
end
end
# app/models/post.rb
class Post < ActiveRecord::base
def posted_by(user)
if self.user == user
"Sorry, you can't reshare your own post"
elsif self.reshare.where(user_id: user.id).present?
"You already shared this post"
else
user.posts.create(
status:"Share: #{self.user.name} #{self.status}",
origianl_post: self
)
"Succesfully shared"
end
end
end
## Scope It Out
#### Bad Code ####
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
# In the Index function
# I want to have my posts & most 5 trending posts
def index
@posts = Post.where(user_id: current_user.id).
order("created_at desc").
limit(10)
@trending = Post.where('start_trending > ', 1.day.ago).
order("mentions desc").
limit(5)
end
end
#### Good Code ####
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
@posts = current_user.posts.limit(10)
# we can ignore our default_scope
# @posts = current_user.posts.unscoped.order(:status).limit(10)
@trending = Post.trending(5)
end
# app/models/post.rb
class Post < ActiveRecord::base
default_scope order("created_at desc")
scope :trending, lambda do |num = nil|
where('start_trending > ', 1.day.ago).
order("mentions desc").
limit(num)
end
# why we use lambda function: if we call this scope again, we will get 1.day.ago (ex: Mon, 23 Nov 2020 07:54:55 UTC +00:00)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment