PORO 可以访问数据库吗?

can a PORO access the database?

作为我的第一个 Rails 应用程序,我正在构建一个家庭作业管理应用程序,其中包含这些 tables:

与我发现的 course/grading 应用程序的大多数示例不同,这个应用程序从不关心所有学生在特定课程中的所有成绩,而只在学生和学生之间建立 1:many 关系培训班。所以这些例子并没有真正帮助我。

为了计算用户在任何给定课程中的当前成绩(这需要访问课程模型和作业模型中的数据),我正在遵循 Stack Overflow 上的建议并在 app/models 名为 GradeCalculator 的目录。

但这是我第一次将 PORO 构建到 Rails 应用程序中,而且我在网上找到的大部分文档都是为更复杂的用户准备的。我假设它不需要控制器(如果我错了请纠正我),而且我看到构建它非常简单:

app/models/gradecalculator.rb

Class GradeCalculator

  def calculate_current_course_grade(course_id)
    @graded_course_assignments = Assignment.where(user_id: current_user.id, course_id: course_id, graded: true)
    #grab weights for each type of assignment in @graded_course_assignments from courses table
    #do some calculations
    #return the array
  end

  def calculate_user_GPA(current_user.id)
    #more of the same
  end

end

我的问题是:

  1. PORO 能否访问数据库(从课程和作业中获取数据 tables)。或者我是否需要在调用它时将来自其他 classes(如作业)的所有相关数据作为参数传递给它?

    1a。如果一个简单的 class 可以访问数据库,语法是否与模型中的语法不同?上面的代码能访问Assignment.where吗?

    1b。我怎么称呼这个PORO?例如,我如何从 views/assignments/index.html.erb?

  2. 中调用它
  3. 它可以访问 Devise 的 current_user 助手吗?

  4. 顺便说一句,我刚刚意识到我 可以 在分配 table 中存储分配权重。我在按时间顺序思考(用户在输入新课程时输入家庭作业、测验等的数量,这决定了每种类型作业的权重),但我可以通过编程让每个新作业填充自己的权重字段参考其父课程中类似作业的数量。这意味着,从逻辑上讲,我可以在作业模型中直接进行成绩计算。但是,如果课程中增加了额外学分或其他更改,则所有作业可能都必须重新计算它们的权重。哪种方式更正确?

写这些问题让我怀疑我只是将我认为的相关数据传递给我的 PORO,让它对这些数据进行计算并 return 评分。但无论如何我都会post,以防万一我错了。

像这样将业务逻辑分解为 PORO 的原因通常是为了让您的代码更容易推理并且更容易(和更快)测试。为此,您不希望 GradeCalculator 知道或关心 Assignment 是如何工作的。您应该只向 GradeCalculator 传递它需要的所有数据(或关系,它像 Enumerable 一样嘎嘎作响)。让 GradeCalculator 调用 Assignment.where 意味着您的测试将依赖于 ActiveRecord 和数据库,这意味着它们会很慢。如果 GradeCalculator 只需要一个数组,那么在你的测试中你只需要模拟一个对象数组来响应 GradeCalculator 需要知道的任何属性方法,你将能够 运行 它们而无需加载 Rails 完全没有。 (通常有一个单独的 spec_helper.rbrails_helper.rb,这样不需要 Rails 的规范可以 运行 而无需加载 Rails,这使得它们 所以快得多。)

对于你的第二个问题,我的建议是相似的:尽可能将你的 PORO 与 Rails 和 Devise 分离。