4

Рассмотрите эту настройку. Пожалуйста, поймите, что наша настройка намного подробнее, но это простой пример.Rails: Это прецедент для одиночного наследования (STI)?

competition, который имеет name. Это ежегодный конкурс.
competition_instances который имеет location, starts_at.
Каждый конкурс имеет sports, который имеет name.

Пример:
competition. name: «Супер Боул» имеет разные competition_instances каждый год, но sport остается неизменным.
И, наоборот, competition. name: «Олимпиада» имеет разные competition_instances и разные sports в каждом competition_instance.

Было бы лучше всего создать competition_sports и competition_instance_sports с competition_instance_sports в качестве подкласса competition_sports?

ЦЕЛЬ: Используйте competition_instance_sports записей, если они существуют, в противном случае используйте запись competition_sports. В нашем приложении для реального мира каждый конкурс/contest_instance может иметь 20-50 спортивных записей. Как мы можем достичь наилучшего результата?

ответ

1

Я просто думаю о случае, когда есть стандартные виды спорта, которые всегда находятся на Олимпийских играх, и некоторые из них добавляются, например, предложенные принимающей страной.

Я бы использовал Polymorphic Associations, в "reverse manner".

class Competition < ActiveRecord::Base 
    has_many :competition_instances 
    has_many :competition_sports, as: :event 
end 

class CompetitionInstance < ActiveRecord::Base 
    belongs_to :competition 
    has_many :competition_sports, as: :event 

    def events_array # neater by sacrificing ActiveRecord methods 
    competition.competition_sports + competition_sports 
    end 

    def events  # messier, returns ActiveRecord relationship 
    CompetitionSport.where(" (event_id = ? AND event_type = 'Competition') OR 
           (event_id = ? AND event_type = 'CompetitionInstance')", competition_id, id) 
    end 
end 

class Sport < ActiveRecord::Base 
    has_many :events, as: :competition_sport 
end 

class CompetitionSport < ActiveRecord::Base 
    belongs_to :sport 
    belongs_to :event, polymorphic: true 
end 

Это позволяет:

competition.competition_sports   # standard sports 
competition_instance.competition_sports # only those specific for this instance 
competition_instance.events    # includes sports from both 
2

Основываясь на том, что я понимаю из вопроса, я не вижу, где ИППП будет полезной в этой ситуации. Однако таблица соединений поможет вам, где вы хотите.

Предлагаю создать новую таблицу sports, эта модель будет иметь все конкретные детали каждого вида спорта. У competition_instance.rb будет один/много sport.rb. competiton.rb будет иметь много sports через competition_instance.rb.

competition.rb

Class Competition < ActiveRecord::Base 
    has_many :competition_instances 
    has_many :sports, through: :competition_instances 
end 

competition_instance.rb

Class CompetitionInstance < ActiveRecord::Base 
    belongs_to :competition 
    belongs_to :sport 
end 

sport.rb

Class Sport < ActiveRecord::Base 
    has_many :competition_instances 
end 

По используя эту конструкцию, вы сможете достичь следующих целей:

1- У вас будут определенные предопределенные виды спорта в вашей базе данных, а также их конкретные свойства.

2- Каждый конкурс будет иметь .sports, который предоставит все виды спорта в этом соревновании для случая олимпийских игр.

3- Вы можете установить конкретные свойства для каждого экземпляра соревнования (пример event_start_time и event_end_time) в таблице экземпляров конкурса.

0

Это не место для одной таблицы наследования, потому что competition_instance не является заменой для competition и 1 competition может иметь много competition_instances.Так у вас есть 3 таблицы:

competitions 
sports 
competition_instances 

competition_instances имеет внешний ключ к competitions потому что 1 competition может иметь много competition_instances но каждый competition_instance имеет ровно один competition.

Прилагаете ли вы sports к competitions или competition_instances, зависит от конкретных ограничений вашего прецедента. Я точно не знаю, что вы подразумеваете под «каждый competition/competition_instance может иметь 20-50 sport записей». Я ожидал бы, что у каждого competition_instance будет ровно один sport, поэтому вы можете его оставить, или вы можете приложить коллекцию sports к competition, чтобы вы могли получить новый competitions на sport, прежде чем появится competition_instance. Мне понадобится дополнительная информация о вашем случае использования, чтобы дать вам дополнительные советы.

1

Прицеливание на оригинальный вопрос «Является ли это случай использования для STI», это будет трудно сказать, является ли это или нет, не видя всю сложность вашей среды. Но вот некоторые вещи, чтобы рассмотреть следующие вопросы:

Сокращенные из How (and When) to Use Single Table Inheritance in Rails - eugenius blog:

STI должен быть считается при работе с модельными классами, доля много тех же функциональности и полей данных, но вам требуется более подробный контроль над расширением или добавлением к каждому классу отдельно. Вместо того, чтобы дублировать код или отказаться от отдельных функций, STI позволяет использовать данные, хранящиеся в одной таблице, при написании специализированных функций.

Вы упростили свой пример, но это звучит как competition и competition_instance НЕ по существу тот же объект, с небольшими различиями в поведении. С помощью того, что вы описали, я бы, вероятно, переименовал эти объекты в event и competition, или что вам больше нравится, с точки зрения иллюстрации того, что представляют собой эти объекты. Я думаю о «Олимпиаде» как об общем событии, и о «100 м тире» в качестве соревнования, проводимого на Олимпиаде. Или «SuperBowl» только один конкурс в 2014 году, «SuperBowl XLIX».

Вы также отметили этот вопрос database-normalization, который STI не поможет. Если атрибуты немного отличаются между вашими общими объектами, вы получите нулевые поля везде.

Я отсылаю вас к другим ответам здесь, чтобы узнать, как вы, вероятно, должны установить, что эти объекты будут вести себя по своему желанию.