Rails 中的胖模型、瘦控制器以及示例
Fat Model, Skinny Controller in Rails with example
我真的很想开始学习 Rails 最佳实践,尤其是遵循 "fat model, skinny controller" 逻辑。
假设我有以下评论控制器
class CommentsController < ApplicationController
def create
@post = Post.find(params[:post_id])
@comment = @post.comments.create(comment_params)
@comment.user_id = current_user.id if current_user
@comment.save!
if @comment.save
redirect_to post_path(@post)
else
render 'new'
end
end
def edit
@post = Post.find(params[:post_id])
@comment = @post.comments.find(params[:id])
end
def update
@post = Post.find(params[:post_id])
@comment = @post.comments.find(params[:id])
if @comment.update(params[:comment].permit(:comment))
redirect_to post_path(@post)
else
render 'Edit'
end
end
def destroy
@post = Post.find(params[:post_id])
@comment = @post.comments.find(params[:id])
@comment.destroy
redirect_to post_path(@post)
end
private
def comment_params
params.require(:comment).permit(:comment)
end
从哪里开始重构代码比较好?
我立即认为我可以在 edit 和 @post 和 @comment 和update 到一个单独的方法中,然后在该方法上调用 before_action。但这仍然是将所有代码放在控制器中。
是否有任何代码可以移动到模型中?如果是这样,我应该如何构建它们?
这段代码没有太大的改进空间,它是一个基本的垃圾,这里有一个 before_action 的例子,就像你建议的那样
before_action :load_post_and_comment, only: %i(edit update destroy)
def load_post_and_comment
@post = Post.find(params[:post_id])
@comment = @post.comments.find(params[:id])
end
还有一些其他注意事项
def create
# ...
@comment.save!
if @comment.save
# ...
else
# ..
end
end
在这个条件下你应该删除额外的@comment.save!
你只需要保存一次。
def update
# ...
if @comment.update(params[:comment].permit(:comment))
# ...
else
# ...
end
end
您已经有了 comment_params
方法,请使用它,因为如果您在任何时候向评论添加新属性,您将更新该方法,但您可能会忘记这部分,并且您'在你注意到你也需要在这里允许之前,你会遇到奇怪的错误。
如果你想真的全力以赴使用瘦控制器模型,有这个gem:https://github.com/NullVoxPopuli/skinny_controllers
在哪里,您可以像这样配置 CommentsController
:
class CommentsController < ApplicationController
include SkinnyControllers::Diet
def create
if model.errors.present?
render 'new'
else
redirect_to post_path(model)
end
end
def update
redirect_to post_path(model)
end
# ... etc
private
def comment_params
params.require(:comment).permit(:comment)
end
end
我真的很想开始学习 Rails 最佳实践,尤其是遵循 "fat model, skinny controller" 逻辑。
假设我有以下评论控制器
class CommentsController < ApplicationController
def create
@post = Post.find(params[:post_id])
@comment = @post.comments.create(comment_params)
@comment.user_id = current_user.id if current_user
@comment.save!
if @comment.save
redirect_to post_path(@post)
else
render 'new'
end
end
def edit
@post = Post.find(params[:post_id])
@comment = @post.comments.find(params[:id])
end
def update
@post = Post.find(params[:post_id])
@comment = @post.comments.find(params[:id])
if @comment.update(params[:comment].permit(:comment))
redirect_to post_path(@post)
else
render 'Edit'
end
end
def destroy
@post = Post.find(params[:post_id])
@comment = @post.comments.find(params[:id])
@comment.destroy
redirect_to post_path(@post)
end
private
def comment_params
params.require(:comment).permit(:comment)
end
从哪里开始重构代码比较好? 我立即认为我可以在 edit 和 @post 和 @comment 和update 到一个单独的方法中,然后在该方法上调用 before_action。但这仍然是将所有代码放在控制器中。
是否有任何代码可以移动到模型中?如果是这样,我应该如何构建它们?
这段代码没有太大的改进空间,它是一个基本的垃圾,这里有一个 before_action 的例子,就像你建议的那样
before_action :load_post_and_comment, only: %i(edit update destroy)
def load_post_and_comment
@post = Post.find(params[:post_id])
@comment = @post.comments.find(params[:id])
end
还有一些其他注意事项
def create
# ...
@comment.save!
if @comment.save
# ...
else
# ..
end
end
在这个条件下你应该删除额外的@comment.save!
你只需要保存一次。
def update
# ...
if @comment.update(params[:comment].permit(:comment))
# ...
else
# ...
end
end
您已经有了 comment_params
方法,请使用它,因为如果您在任何时候向评论添加新属性,您将更新该方法,但您可能会忘记这部分,并且您'在你注意到你也需要在这里允许之前,你会遇到奇怪的错误。
如果你想真的全力以赴使用瘦控制器模型,有这个gem:https://github.com/NullVoxPopuli/skinny_controllers
在哪里,您可以像这样配置 CommentsController
:
class CommentsController < ApplicationController
include SkinnyControllers::Diet
def create
if model.errors.present?
render 'new'
else
redirect_to post_path(model)
end
end
def update
redirect_to post_path(model)
end
# ... etc
private
def comment_params
params.require(:comment).permit(:comment)
end
end