The action bellow creates a new comment.
How can optimize this action so that head 401 and return
is not repeated many times.
def create
@user = User.where(id: params[:user_id]).first
if @user
if current_user.friend_with?(@user) or current_user == @user
@status = @user.statuses.where(id: params[:status_id]).first
if @status
@comment = @status.comments.build(params[:comment])
@comment.owner = current_user
if @comment.valid?
@comment.save
current_user.create_activity(:comment_status, @comment, @user)
else
head 401 and return
end
else
head 401 and return
end
else
head 401 and return
end
else
head 401 and return
end
end
Thank you.
You have a lot of excessive checking and branching in your code, so it can be simplified to this:
def create
success = false
@user = User.find(params[:user_id])
current_user_is_friend = current_user.friend_with?(@user) || current_user == @user
if @user && current_user_is_friend && @status = @user.statuses.find(params[:status_id])
@comment = @status.comments.build(params[:comment])
@comment.owner = current_user
if @comment.save
current_user.create_activity(:comment_status, @comment, @user)
success = true
end
end
render(status: 401, content: '') unless success
end
A few things I did:
if
conditions, since there was no need for them to be separate. where(id: ...).first
to find(...)
since they're the same. Note that, if the find
fails, it will give a 404. This may make more sense, though (I think it does) @comment.valid?
right before @comment.save
, since save
returns false
if the object wasn't valid. ||
instead of or
for boolean logic ( they're not the same ). render(status: ..., content: '')
instead of head ... and return
. I would advise that you try and pull some of this logic out into models. For example, User#friend_with
should probably just return true if it's passed the same User.
When do you want to return 401
?
Instead of using so many conditionals, you can use methods that raise exceptions. When you do so, you can rescue from that exceptions with the desired behavior (rendering 401
).
So my suggestions for listed conditions are:
find!
instead of where
and then first
. raise
something, preferably custom exception ( NotAFriendError
) find!
create!
, it's an equivalent to new
and then save!
which will raise ActiveRecord::RecordInvalid
exception if it fails on validation. Here's the result:
def create
begin
@user = User.find!(params[:user_id])
raise unless current_user.friend_with?(@user) || current_user == @user
@status = @user.statuses.find!(params[:status_id])
@comment = @status.comments.
create!(params[:comment].merge(:owner => current_user))
rescue ActiveRecord::RecordNotFound, ActiveRecord::RecordInvalid
head 401
end
# everything went well, no exceptions were raised
current_user.create_activity(:comment_status, @comment, @user)
end
def create
@user = User.where(id: params[:user_id]).first
if @user
if current_user.friend_with?(@user) or current_user == @user
@status = @user.statuses.where(id: params[:status_id]).first
if @status
@comment = @status.comments.build(params[:comment])
@comment.owner = current_user
if @comment.valid?
@comment.save
current_user.create_activity(:comment_status, @comment, @user)
everythingOK = true
end
end
end
end
head 401 and return unless everythingOK
end
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.