Назад к вопросам
Middle+
136
questionbank

Как реализовать наследование моделей или полиморфные ассоциации в Ruby on Rails?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

В Ruby on Rails наследование моделей реализуется через Single Table Inheritance (STI) или с помощью полиморфных ассоциаций.

Single Table Inheritance (STI)

STI подходит, когда у разных типов объектов схожие атрибуты, но разное поведение. Все данные хранятся в одной таблице, а тип объекта определяется по колонке type.

  1. Создание таблицы и колонки type:

    # migration
    create_table :animals do |t|
      t.string :name
      t.string :type
      t.timestamps
    end
    
  2. Создание классов моделей, наследующих от базового:

    # app/models/animal.rb
    class Animal < ApplicationRecord
      # Общая логика для всех животных
    end
    
    # app/models/dog.rb
    class Dog < Animal
      # Специфическая логика для собак
      def bark
        "Woof!"
      end
    end
    
    # app/models/cat.rb
    class Cat < Animal
      # Специфическая логика для кошек
      def meow
        "Meow!"
      end
    end
    
  3. Использование:

    # console
    dog = Dog.create(name: "Buddy")
    cat = Cat.create(name: "Whiskers")
    
    animal = Animal.find(dog.id) # Вернет объект Dog
    

Полиморфные ассоциации

Полиморфные ассоциации используются, когда модель может принадлежать разным другим моделям.

  1. Добавление колонок _id и _type в ассоциируемую модель: Например, если Comment может принадлежать Article или Photo:

    # migration
    create_table :comments do |t|
      t.text :body
      t.references :commentable, polymorphic: true, null: false
      t.timestamps
    end
    
  2. Объявление ассоциации в моделях: В модели Comment:

    # app/models/comment.rb
    class Comment < ApplicationRecord
      belongs_to :commentable, polymorphic: true
    end
    

    В моделях Article и Photo:

    # app/models/article.rb
    class Article < ApplicationRecord
      has_many :comments, as: :commentable
    end
    
    # app/models/photo.rb
    class Photo < ApplicationRecord
      has_many :comments, as: :commentable
    end
    
  3. Использование:

    # console
    article = Article.create(title: "Rails Tips")
    photo = Photo.create(caption: "Beautiful Sunset")
    
    article.comments.create(body: "Great article!")
    photo.comments.create(body: "Lovely photo!")
    
    Comment.first.commentable # Вернет Article
    Comment.last.commentable  # Вернет Photo
    

Выбор между STI и полиморфными ассоциациями зависит от структуры данных и отношений между моделями. STI для "is-a" отношений (Dog is a Animal), полиморфные ассоциации для "has-a" отношений (Article has a Comment, Photo has a Comment, где Comment может принадлежать Article ИЛИ Photo).