2015-05-15 3 views
1

Допустим, у меня есть три классаГде Person и не Person :: Single

Person 

Person::Single < Person 

Person::Married < Person 

Допустим, у меня есть два Лица, которые Single =>Person::Single

Тогда я получаю два человека, когда я делать:

Person.all.count 
=> 2 

Но моя цель состоит в том, чтобы получить только лица, которые являются тип Person и не Person::Single или Person::Married

Я попытался это:

Person.where(type: Person.to_s) 
=> 2 

, но это также возвращает 2, потому что Person::Single и Person::Married наследоваться от Person

Что я могу сделать вместо этого? Есть ли, например, способ сказать, что ::Single и ::Married такие же методы от person, но не такие же? Спасибо

+0

делает 'Person.where (тип: ноль)' работает? – Doon

+1

Похоже, вы хотите использовать композицию вместо наследования. – spickermann

ответ

0

Поскольку это отмечено биркой rails, я предполагаю, что ваш класс Person - это модель ActiveRecord. Существует еще некоторая информация отсутствует, но я только предположить, где я не знаю;)

Ваш класс Person наследует ActiveRecord методы, например, «все», и Person :: Single:: Maried) наследует его через Личность.

Поэтому, естественно, когда вы делаете Person.all это будет просто делать регулярные <#ActiveRecord>.all метод, который не знает и не заботится о :: одиночных и :: Maried.

Что вы можете сделать, это динамически установить default_scope на основе имени класса, с которым вы звоните .all или .where или что-то еще.

class Person < ActiveRecord::Base 
    ... 

    def self.default_scope 
    scope = if self.name == Person.sti_name 
     where(:type => Person.sti_name) 
    else 
     nil 
    end 

    scope 
    end 
end 

Это также будет охватывать ваши запросы (: whatever => x).

Однако, это означает, что у вас есть атрибут, называемый «тип» для вас. Модель Person (столбец в базе данных).

EDIT: Как указал Хольгер, уже существует магия, связанная с рельсами STI. Я по-прежнему считаю, что можно установить диапазон по умолчанию, только вы должны пропустить настройку областей для одиноких и женатых. Если вам не нужна эта область по умолчанию, вы должны просто попробовать Person.where(:type => Person.sti_name) или Person.where(:type => Person.name), так как rails утверждает имя класса sti_name, если класс наследуется от ActiveRecord :: Base.

+0

Столбец 'type' является специальным по умолчанию в Rails, поскольку он принимает участие в [Одиночном наследовании таблицы] (http://api.rubyonrails.org/classes/ActiveRecord/Base.html#class-ActiveRecord::Base-label- одиночный + стол + наследование). Таким образом, вы должны работать с этим механизмом, а не создавать свои собственные области. Ваш ответ несовместим с моделью STI в Rails. И да, Rails действительно очень заботится о подклассах с STI. –

+0

@Holger Ах, действительно колонка типа является специальной. Спасибо, что указали на это, я не знал об этом. Однако это не должно повлиять на решение, и я не понимаю, почему он «несовместим» с моделью STI, поскольку все, что вы делаете, это определение областей для подклассов ... – Ninigi

+0

Во-первых, Rails сохраняет имя подкласса в столбце 'type', по умолчанию, включая полное пространство имен. Таким образом, это будет либо «Person :: Single», «Person :: Married», либо «Person». Значения, таким образом, сильно отличаются. Кроме того, возвращаемые объекты имеют дочерний тип, если они определены. Области, которые вы предложили, делают вещи намного более хрупкими и неочевидными. –

0

Попробуйте это:

Person.where(:type => Person).count 
Смежные вопросы