2

I do not know the terminology of what I am trying to do so googling it has proven very hard.

I have 2 ruby classes.

class A < ActiveRecord::Base

end

class B < A

end

class A is what hits the database. There is a column in class A that stores the intended class name. In this example the value of that column in class A would be 'b'.

My desire is to find a way to call A, and actually get B. My thought being there will be more than just B in the future I could end up having C, D, and even E. All of these classes could require unique methods.

1

3 Answers 3

5

Rails' Single Table Inheritance can help you: http://api.rubyonrails.org/classes/ActiveRecord/Base.html#class-ActiveRecord::Base-label-Single+table+inheritance

Sign up to request clarification or add additional context in comments.

Comments

2

This is called STI (Single Table Inheritance). The correct way to implement it is to add a column named type to the base class table. Rails will use this column to know what class to instantiate for a given record. For example lets assume we have three classes, Person, Teacher and Student. Person is the base class and Teacher and Student inherits from it. In this case we implement it as follows:

Migration:

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

Models

# Person
class Person < ActiveRecord::Base
end

# Teacher
class Teacher < Person
end

# Student
class Student < Person
end

so if you create a new student

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

than get it throught the Person class

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

When you create a new student, and to be sure that its attributes are set correctly, so that for example, a student does not have teacher's specific attributes set. you just filter them in the controller through strong parameters( assuming this is a Rails application)

Comments

0

An alternative way to do that in pure Ruby would be to return B from a method called on A.

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.