关于Fat-Model,Skinny-Controller实践的问题

时间:2016-10-25 10:23:06

标签: ruby-on-rails

您如何确定必须将一行代码从控制器移动到模型?

我已经做过一些关于这个最佳实践的研究,这是迄今为止最好的解释,但我希望你们能够扩展这个,因为我的新手大脑无法完全理解它:)

  1. 任何与非响应相关的逻辑都应该放在模型中
  2. 您只需要流程请求参数并在控制器中初始化模型层
  3. 业务逻辑需要在模型层实施
  4. 编辑:假设我想在下面重构我的控制器:

    class TaskController < ApplicationController
      def index
        @tasks = Task.find_all_by_complete(:false, :order => "created_at DESC")
      end
    end
    

    class TaskController < ApplicationController
      def index
        @tasks = Task.find_incomplete
      end
    end
    

    这2个代码块中的哪一个是正确的?

    class Task < ActiveRecord::Base
      def self.find_incomplete
        find_all_by_complete(:false, :order => "created_at DESC")
      end
    end
    

    class Task < ActiveRecord::Base
      def find_incomplete
        self.find_all_by_complete(:false, :order => "created_at DESC")
      end
    end
    

    EDIT2:如果我想在下面重构我的控制器:

    @average_review = @surf_school.surf_school_reviews.average(:rating).round(2)
    

    @average_review = @surf_school.average_review
    

    我在模型中的代码应该是:

    def average_review
      self.surf_school_reviews.average(:rating).round(2)
    end
    

2 个答案:

答案 0 :(得分:0)

通常作为起点,我会在模型中放置任何与CRUD相关的代码。在模型中设置自定义方法,以便您可以致电@user.invalidate@post.replace_owner(@user)@user的这些实例可以在模型中引用为self。 例如:

class Post < ApplicationRecord
  def add_owner(user)
    self.update_attributes(user_id: user.id)
  end
end

因此,将这样的逻辑移动到模型中可以实现更清晰的控制器代码。我还会处理请求,设置变量,使用模型方法并确定在Controller中加载哪个页面。

编辑:我也会使用第一个代码块:

def self.find_incomplete
  find_all_by_complete(:false, :order => "created_at DESC")
end

正是如何手动创建ActiveRecord范围,该范围与以下内容相同:

class Task < ActiveRecord::Base
  scope :find_complete -> { find_all_by_complete(:false, :order => "created_at DESC") }
end

但他们说这只是语法糖。你的第一个块就是我上面的块被转换成的东西,可以这么说。

有关ActiveRecord::Scoping的更多信息,请参阅

答案 1 :(得分:0)

在我的工作中,我们为模型层中的每个模型都有多个类。为简化起见,我们有一个DTO和DAO对象。 DTO包含字段,DAO包含保存,修改和删除数据库条目的方法。

我们的一些DAO还包含带有特殊/更复杂搜索查询的辅助方法,并覆盖标准保存方法,以防止控制器将无效数据输入到我们的模型中。

我们的控制器操作使用DAO将模型填充到某个点并将其新状态保存到数据库中。我们的控制器包含业务逻辑,但是一些DAO具有一些额外的方法来防止无效数据进入数据库。它使业务逻辑更易读,更容易理解。

另外要记住的是,如果您遵循某种做法,它是完美的,但如果它不符合您的要求,请考虑侧身。就像,如果您碰巧在每次保存操作之前必须执行必须执行的业务逻辑,我老实说要么定义一个实用程序/帮助程序类,它具有保存此逻辑的静态方法或覆盖模型对象的save方法并把它移到那里。

注意:DAO代表数据访问对象。这在我们的用例中很常见,但是您只有一个基本上相同但没有多个类的类。这是在我开始在这里工作之前选择的设计模式。

编辑:我要去第二个选项。但是这篇文章可能会对你有所帮助:What does def `self.function` name mean?