作为我的第一个Rails应用程序,我正在构建一个包含这些表格的家庭作业管理应用程序:
与我发现的课程/评分应用程序的大多数示例不同,此课程从不关注特定课程的所有学生的所有成绩,但在学生和课程之间只有1:多的关系。所以这些例子对我没有帮助。
为了在任何给定的课程中计算用户的当前成绩(需要在课程模型和作业模型中访问数据),我在此处遵循Stack Overflow上的建议并在其中创建PORO app / models目录名为GradeCalculator。
但这是我第一次将PORO构建到Rails应用程序中,我在线查找的大部分文档都是针对更复杂的用户。我假设它不需要控制器(如果我错了,请纠正我),我看到构建它就像:
应用程序/模型/ 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
我的问题是:
PORO可以访问数据库(从课程和作业表中获取数据)。或者,在调用它时,是否需要将其他类(如赋值)中的所有相关数据作为参数传递给它?
1a上。如果一个简单的类可以访问数据库,那么语法是否与模型中的语法不同?以上代码是否能够访问Assignment.where?
1b中。我怎么称呼这个PORO?例如,我如何从我的views / assignments / index.html.erb中调用它?
可以访问Devise的current_user助手吗?
切线,我刚刚意识到我可以在分配表中存储分配权重。我按时间顺序思考(用户在输入新课程时输入家庭作业的数量,等等,这决定了每种类型的作业的权重),但我可以通过编程方式让每个新作业填充自己的权重字段引用其父课程中类似作业的数量。从逻辑上讲,这意味着我可以在Assignment模型中进行等级计算。但是,如果课程中添加了额外学分或其他更改,则所有作业可能必须重新计算其权重。哪种方式更正确?
写下这些问题让我怀疑我只是从我的视图中传递我的PORO相关数据,让它对该数据进行计算并返回一个等级。但无论如何我会发帖,以防万一我错了。
答案 0 :(得分:2)
将业务逻辑分解为像这样的PORO的原因通常是让您的代码更易于推理并且更容易(和更快)地进行测试。为此,您不希望GradeCalculator知道或关心Assignment如何工作。你应该只传递GradeCalculator所需的所有数据(或者一个像Enumerable一样嘎嘎叫的Relation)。让GradeCalculator调用Assignment.where
意味着你的测试将依赖于ActiveRecord和数据库,这意味着它们会很慢。如果GradeCalculator只需要一个数组,那么在测试中你只需要模拟一个对象数组,这些对象响应了GradeCalculator需要知道的任何属性方法,并且你将能够在不加载Rails的情况下运行它们。 (通常有一个单独的spec_helper.rb
和rails_helper.rb
,这样不需要Rails的规范就可以在不加载Rails的情况下运行,这使得它们所以更快。)
根据您的第二个问题,我的建议是相似的:尽可能多地将您的PORO与Rails和Devise分离。