Создание шаблонов ActiveRecord: два столбца с одинаковым типом данных

Еще один базовый вопрос Rails:

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

Гипотетический пример: я создаю базу данных видеоигр. У меня есть таблица «Компании». Я хочу иметь ровно одного разработчика и только одного издателя для каждой записи «Видеоигры».

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

script/generate Videogame company:references

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

Кажется, ответ должен быть довольно очевидным, но я не могу найти его нигде в Интернете.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
24
0
14 080
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я не знаю, как это сделать с помощью script / generate.

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

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

В вашем файле миграции есть:

create_table :videogames do |t|
  # all your other fields
  t.int :developer_id
  t.int :publisher_id
end

Затем в вашей модели:

belongs_to :developer, class_name: "Company", foreign_key: "developer_id"
belongs_to :publisher, class_name: "Company", foreign_key: "publisher_id"

Вы также упоминаете, что хотите, чтобы две компании были разными, что вы могли бы обработать при валидации в модели, которая проверяет этот developer_id != publisher_id.

В качестве примечания, параметр foreign_key здесь не нужен, поскольку по умолчанию используется имя ассоциации + "_id". Для получения дополнительной информации см. spacevatican.org/2008/5/6/….

Max Wallace 15.08.2015 22:19
Ответ принят как подходящий

Чтобы немного навести порядок, в процессе миграции теперь вы также можете:

create_table :videogames do |t|
  t.belongs_to :developer
  t.belongs_to :publisher
end

И поскольку вы вызываете ключи developer_id и publisher_id, модель, вероятно, должна быть такой:

belongs_to :developer, :class_name => "Company"
belongs_to :publisher, :class_name => "Company"

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

Я пробовал это, и теперь у меня есть developer_id, но нет доступа к game.developer. У меня в моей видеоигре есть класс attr_accessible: developer.

quantumpotato 04.06.2013 21:22

Вероятно, это уже было решено, но добавили ли вы has_many: games (или что-то в этом роде) в свою модель разработчика?

MrWater 27.09.2013 20:27

Как сделать обратное сопоставление?

Gaurav Agarwal 19.06.2014 10:47

Если есть какие-либо методы или проверки, которые вы хотите использовать для определенного типа компании, вы можете подклассифицировать модель компании. При этом используется метод, называемый наследованием одной таблицы. Для получения дополнительной информации ознакомьтесь с этой статьей: http://wiki.rubyonrails.org/rails/pages/singletableinheritance

Тогда у вас будет:

#db/migrate/###_create_companies
class CreateCompanies < ActiveRecord::Migration
  def self.up
    create_table :companies do |t|
      t.string :type  # required so rails know what type of company a record is
      t.timestamps
    end
  end

  def self.down
    drop_table :companies
  end
end

#db/migrate/###_create_videogames
class CreateVideogames < ActiveRecord::Migration
  create_table :videogames do |t|
    t.belongs_to :developer
    t.belongs_to :publisher
  end    

  def self.down
    drop_table :videogames
  end
end

#app/models/company.rb
class Company < ActiveRecord::Base 
  has_many :videogames
  common validations and methods
end

#app/models/developer.rb
class Developer < Company
  developer specific code
end

#app/models/publisher.rb
class Publisher < Company
  publisher specific code
end

#app/models/videogame.rb
class Videogame < ActiveRecord::Base 
  belongs_to :developer, :publisher
end

В результате у вас будут модели «Компания», «Разработчик» и «Издатель».

 Company.find(:all)
 Developer.find(:all)
 Publisher.find(:all)

Другие вопросы по теме