在ruby中构建对象关系时隔离依赖关系

时间:2017-05-21 16:53:18

标签: ruby class oop relationship

我是第一次通过将我的应用程序域(公立高中)建模为对象来练习OOP,并且我坚持如何在不引入大量外部依赖关系的情况下创建类之间的关系。 / p>

我想要建立很多关系,所以为了学习一般原则,我在这里给出两个课程和样本对象来说明我遇到的困难。

我有两个班级GradeTranscriptTranscript的每个实例都有一个实例变量@mark,现在它是一个字符串。我收集了每个类的所有实例grades哈希和transcripts哈希。

问题:如何修改这些类,以便@mark引用相应的Grade实例?

(或者,这完全是错误的方法吗?)

Grade有一个学生可以获得的每个可能的最终成绩的实例

class Grade
  attr_accessor :mark, :alpha_equivalent, :numeric_range_low, :numeric_range_high, :numeric_qquivalent, :pass_fail_equivalent, :description

  def initialize(args)
    @mark = args["Mark"]
    @alpha_equivalent = args["AlphaEquivalent"]
    @numeric_range_low = args["NumericRangeLow"]
    @numeric_range_high = args["NumericRangeHigh"]
    @numeric_equivalent = args["NumericEquivalent"]
    @pass_fail_equivalent = args["PassFailEquivalent"]
    @description = args["Description"]
  end
end

成绩对象来自成绩哈希:

grades["100"] =>
#<Grade:0x007f9fcb077d68
 @alpha_equivalent="100",
 @description="100 out of 100",
 @mark="100",
 @numeric_equivalent="100",
 @numeric_range_high="100",
 @numeric_range_low="100",
 @pass_fail_equivalent="P">

Transcript有学生为他们所学过的所有课程收到的每个最终成绩的实例

class Transcript
    attr_accessor :student_id, :last_name, :first_name, :grade, :official_class, :school, :year, :term, :course, :course_title, :mark, :pass_fail, :credits

    def initialize(args)
        @student_id = args["StudentID"]
        @last_name = args["LastName"]
        @first_name = args["FirstName"]
        @grade = args["Grade"]
        @official_class = args["OffClass"]
        @school = args["school"]
        @year = args["Year"]
        @term = args["Term"]
        @course = args["Course"]
        @course_title = args["Course Title"]
        @mark = args["Mark"]
        @credits = args["Credits"]
        @grade_entry_cohort = args["GEC"]
  end
end

来自成绩单散列的示例对象:

transcripts["foobar-COURSE1-100"] =>
  #<Transcript:0x007f9fce8786b8
   @course="COURSE1",
   @course_title="Example Course",
   @credits="5",
   @first_name="FOO",
   @grade="100",
   @grade_entry_cohort="V",
   @last_name="BAR",
   @mark="100",
   @official_class="000",
   @school="1",
   @student_id="0123",
   @term="1",
   @year="2000">

我实例化了CSV源文件中的所有对象,然后将它们收集到哈希中,因为我希望能够直接解决它们。

2 个答案:

答案 0 :(得分:2)

听起来您需要Transcript#grade返回Grade个实例。因此,让我们为此制定方法:

class Grade
  def self.all
    @all ||= {}
  end

  def self.find(mark)
    all[mark]
  end
end

现在,需要填充Grade.all。这可以通过CSV实现:

grade_args = %w[alpha_equivalent description mark numeric_equivalent numeric_range_high numeric_range_low pass_fail_equivalent]
CSV.parse { |row| Grade.all.merge(csv['mark'] => Grade.new(row.slice(*grade_args)}

现在,我们可以像这样修改Transcript

class Transcript
  def initialize(args)
    @args = args
  end

  def grade
    @grade ||= Grade.find(args['mark'])
  end

  private

  attr_reader :args
end

答案 1 :(得分:2)

假设您之前已创建grades哈希:

# read args from csv
# id built from first, last, course, and grade
transcripts[id] = Transcript.
  new(args.merge('Mark' => grades[args['Mark']])

它使用Hash#merge扩展args,并使用之前构建的Grade实例。