ActiveRecord и двухуровневые иерархии - PullRequest
1 голос
/ 22 июля 2011

Допустим, у меня есть личный стол, и я хочу, чтобы он классифицировал всех людей как альфы или омеги. У всех омег есть только одна альфа, но нет омеги, у всех альф есть любое количество омеги, но нет альфы.

Это простая двухуровневая иерархия, которую я могу кодировать, используя один внешний ключ:

CREATE TABLE people (
  id INTEGER NOT NULL PRIMARY KEY,
  alpha_id INTEGER FOREIGN KEY REFERENCES people, 
  -- alpha_id is NULL if and only if this person is an alpha
  -- other stuff we know about people...
);

Теперь я могу создать класс для обычного человека, но он становится немного неловким, когда я добираюсь до отношений альфа-омега.

class Person < ActiveRecord::Base
  # ... stuff I know about people

  # if alpha_id is NULL
    has_many :omegas, :as => :alpha, :class_name => Person
  # else 
    belongs_to :alpha, :class_name => Person
end

Было бы неплохо разделить человека на два подкласса: один для Альф, другой для Омегаса, но я не уверен, насколько хорошо это сыграет с ActiveRecord.

В идеале я бы хотел что-то вроде этого:

class Person < ActiveRecord::Base
  # ... stuff I know about people
end
class Alpha < Subset(Person)
  column_is_null :alpha_id
  has_many :omegas
end
class Omega < Subset(Person)
  column_is_not_null :alpha_id
  belongs_to :alpha
end

Этот вид подклассов или что-то приближающее его доступно в ActiveRecord?

1 Ответ

1 голос
/ 22 июля 2011

Используйте named_scope :

 class Person < ActiveRecord::Base
   # ... stuff I know about people
   named_scope :alphas, :conditions => { :alpha_id => nil }
   named_scope :omegas, :conditions => "alpha_id IS NOT NULL"

   # if alpha_id is NULL
   has_many :omegas, :as => :alpha, :class_name => Person
   # else 
   belongs_to :alpha, :class_name => Person
 end

Теперь вы можете ссылаться на Person.alphas и Person.omegas , чтобы получить объекты, которыми вы являетесьнаходясь в поиске.Это помогает?

...