0

Я пытался найти решение на 2 дня, придумал еще ничего.Как можно смешивать полиморфизм и наследование в Rails (5.0.0.1)

У меня есть модель под названием Course, которая имеет следующие столбцы:

create_table :courses do |c| 
    c.integer :member_limit 
    c.string :color 
    c.float :rating 

    c.timestamps 
end 

У меня также есть Content модель, которая имеет столбцы, Course выгоды от, но и приносит пользу и другие модели в моей базе данных, таких как:

create_table :contents do |c| 
    c.references :contentable, polymorphic: true, index: true 
    c.string :title 
    c.text :description 
    c.text :script 
    c.string :cover 
    c.string :media_type 
    ... 
    c.integer :creator_id, index: true, foreign_key: :user_id 
end  

Я не могу установить Course < Content, потому что я потеряю столбцы, конечно, имеет внутренне, такие как member_limit и так далее, поэтому я пошел с Полиморфным. Однако я хочу избежать необходимости звонить course.content.title и просто писать course.title, но также получить доступ course.member_limit таким же образом и сохранить оба этих поля, используя course.save.

Что вы рекомендуете для лучшего подхода?

текущая структура.

курс:

class Course < ApplicationRecord 
    has_one :content, as: :contentable, dependent: :destroy 

    after_initialize :init 

    def init 
     if self.new_record? 
     self.content ||= build_content  
     end 
    end 
end 

Содержание:

class Content < ApplicationRecord 
    belongs_to :creator, optional: true, class_name: 'User' 
end 

ответ

0

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

То, что вы хотите, может быть сделано с помощью вспомогательных методов, как так:

class Course < AR 
    def title 
    content.title 
    end 
end 

Что некрасиво, нарушает все кодирования аргумент когда-либо написанных, и его просто плохая практика. Но, кроме некоторой метамагии, которая могла бы избежать необходимости писать вспомогательные методы один за другим (обратите внимание, что я написал запись, потому что в конечном итоге они будут реализованы), конечный результат должен быть таким. Другого способа это не делать. Так что мой ответ, не делай этого.

Понимание полиморфизма непросто. Его легко реализовать, но трудно узнать, когда. Вам нужен абстрактный блок, содержащий столбцы нескольких других ресурсов только потому, что. Вы не принимаете никаких аргументов в пользу решения о создании «... модели контента, в которой есть столбцы, которые могут извлечь из курса, а также приносит пользу другим моделям в моей базе данных». Я спрашиваю. Зачем? В чем польза? зачем это делать? Он работает так же хорошо, как и ожидалось? проще ли его использовать и расширять? он заключен в капсулу? Является ли оно сухим, отдохнувшим, твердым, и все остальные аббревиатуры, используемые в наши дни?

Короткий ответ НЕТ. Это не так. Так что не делай этого. У класса курса есть название. Если другая таблица также имеет заголовок, то что? Знаете ли вы, сколько таблиц в мире имеет столбец «имя»? Если бы мы все хотели его реализовать, у нас было бы что-то вроде этого:

class School < Ar 
    belongs_to :name 

    def full_name 
    name.body 
    end 
end 

class Student < Ar 
    belongs_to :name 

    def full_name 
    name.body 
    end 
end 

, что явно нецелесообразно. Поэтому, если это не полезно для одного столбца, почему он становится полезным для большего количества столбцов?

Вывод:

  1. Полиморфизм не используется, чтобы повторно использовать столбцы, никогда.
  2. STI используется для повторного использования столбцов (вид)
  3. Полиморфизм можно понимать как нечто, что можно прикрепить к нескольким ресурсам. Например: Уведомления, журналы, адреса ... В основном говорят, что у курса есть адрес, а также у Студента есть адрес. Оба студента и курс являются адресными. НО НИКОГДА, НИКОГДА, НИКОГДА НЕ говорите, что контент - это ТИП адреса. Это просто неверно, форма или форма.
  4. В ИППП ресурс СТАНЕТ типом родителя, поэтому в ИППП курс будет ТИПОМ содержания. Также Студент будет ТИПОМ содержания. НО НИКОГДА, НИКОГДА, НИКОГДА НЕ СКАЗЫВАЙТЕСЬ С КОНЕЦ. Это просто неверно, форма или форма.

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

Итак, короткий ответ (немного поздно нет?). Нет, вы не можете делать то, что хотите. Вы можете

  1. Просто повторите столбцы каждого ресурса (предпочтительный способ для первой реализации, легко, быстро и стандарт)
  2. Использование STI и одну таблицу, чтобы представить все ресурсы, которые бы «совместно» содержимое информация
  3. Используйте полиморфизм и используйте вспомогательные методы, чтобы делать то, что вы хотите. Но не забывайте, что аксессоры - не единственные. Подумайте о таких методах, как def title=. Вы собираетесь перепрофилировать их все?

Извините за длину, просто повторил эту ошибку слишком много раз.