Rails中的Fat Model,Skinny Controller,示例为

时间:2015-05-04 03:38:05

标签: ruby-on-rails model-view-controller

我真的想开始学习Rails最佳实践,特别是遵循“胖模型,瘦模控制器”逻辑。

说我有以下评论控制器

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

开始重构代码的好地方是什么? 我想我立即将编辑更新中的 @post @comment 改为单独的方法,然后在方法上调用 before_action 。但这仍然是将所有代码都放在控制器中。

是否有任何代码可以移动到模型中?如果是这样,我应该如何构建它们呢?

2 个答案:

答案 0 :(得分:1)

此代码没有太大的改进空间,这是一个基本的问题,这里有一个像你建议的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方法,使用它,因为如果您在任何时候为评论添加新属性,您将更新该方法,但您可能会忘记此部分和在你注意到你也需要在这里允许之前,你会得到错误的错误。

答案 1 :(得分:0)

如果你想真的全力以赴的瘦控制器模型,那就有这个宝石: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