红宝石继承。将一个对象转换为另一个对象

时间:2015-04-26 04:35:58

标签: ruby

我不知道我想要做什么的术语因此谷歌搜索已经证明非常困难。

我有2个红宝石课程。

class A < ActiveRecord::Base

end

class B < A

end

A类是命中数据库的原因。 A类中有一列存储了预期的类名。在此示例中,A类中该列的值为&#39; b&#39;。

我的愿望是找到一种方法来调用A,并且实际上得到B.我的想法将来不仅仅是B我最终会得到C,D,甚至是E.所有这些类都可以需要独特的方法。

3 个答案:

答案 0 :(得分:5)

答案 1 :(得分:2)

这称为STI(单表继承)。实现它的正确方法是将一个名为type的列添加到基类表中。 Rails将使用此列来了解要为给定记录实例化的类。 例如,假设我们有三个类PersonTeacherStudentPerson是基类,TeacherStudent从中继承。在这种情况下,我们按如下方式实现它:

迁移:

class CreatePeople < ActiveRecord::Migration
 def change
    create_table :people do |t|
      ... # person attributes name, birthday ...
      ... # Student specific attributes
      ... # Teacher specific attributes 
      t.string :type # this will be Student, Teacher or Even Person.

      t.timestamps null: false
    end
  end
end

模型

# Person
class Person < ActiveRecord::Base
end

# Teacher
class Teacher < Person
end

# Student
class Student < Person
end

所以如果你创建一个新学生

student = Student.new(name: 'studentx',...)
student.save

而不是通过Person

person = Person.first
puts person.type # => Student

当您创建新学生并确保其属性设置正确时,例如,学生没有设置教师的特定属性。你只需通过强参数在控制器中过滤它们(假设这是一个Rails应用程序)

答案 2 :(得分:0)

在纯Ruby中执行此操作的另一种方法是从A上调用的方法返回B.

class A < ActiveRecord::Base
  def b
    return B.new(self)
  end
end

class B
  def initialize(a)
    @a = a
  end

  # if you need to get methods belonging to A 
  def method_missing(*args, &block)
    @a.send(*args, &block)
  end
end