Рельсы has_one против belongs_to семантики

У меня есть модель, представляющая a Content пункт, который содержит некоторые изображения. Количество изображений зафиксировано, поскольку эти ссылки изображения очень характерны для содержания. Например, Content модель относится к Image смоделируйте дважды (аватар и фоновое изображение). Я стараюсь избегать дженерика has_many, и придерживание нескольких has_one. Текущая структура базы данных похожа:

contents
  - id:integer
  - integer:profile_image_id
  - integer:background_image_id

images
  - integer:id
  - string:filename
  - integer:content_id

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

Это является лучшим, я мог думать (ломая семантику):

class Content
  belongs_to :profile_image, :class_name => 'Image', :foreign_key => 'profile_image_id'
  belongs_to :background_image, :class_name => 'Image', :foreign_key => 'background_image_id'
end

Я - путь прочь и там лучший способ достигнуть этой ассоциации?

18
задан Anurag 25 January 2010 в 22:18
поделиться

2 ответа

Простой ответ - настроить ваши ассоциации в обратном направлении того, что у вас есть, например:

# app/models/content.rb
class Content < ActiveRecord::Base
  has_one :profile_image, :class_name => 'Image'
  has_one :background_image, :class_name => 'Image'
end

# app/models/image.rb
class Image < ActiveRecord::Base
  belongs_to :content
end

Вам не нужны иностранные клавиши «Background_image_ID» и «Profile_image_id» в таблице контента вообще.

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

Во-первых, добавьте столбец на ваши изображения таблицы называется Тип:

# command line
script/generate migration AddTypeToImages type:string
rake db:migrate

Теперь установить такие модели, как это:

# app/models/content.rb
class Content < ActiveRecord::Base
  has_one :profile_image
  has_one :background_image
end

# app/models/image.rb
class Image < ActiveRecord::Base
  belongs_to :content
end

# app/models/background_image.rb
class BackgroundImage < Image
  # background image specific code here
end

# app/models/profile_image.rb
class ProfileImage < Image
  # profile image specific code here
end

Теперь вы можете сделать все виды таких вещей, как получить список всех фоновых изображений:

# script/console
BackgroundImage.all

Это Более верно для модели данных, которую вы пытаетесь создать, позволяет самым простым расширением в будущем и дает вам несколько прохладных новых методов сегодня.

Обновление:

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

23
ответ дан 30 November 2019 в 08:32
поделиться

На основании Руководство ассоциаций AR , я думаю, вы должны использовать HAS_ONE . Это не имеет смысла к изображению владеть контентом ... Содержание обязательно владеет изображением. Из руководства:

Различие находится в том, где вы находитесь внешний ключ (он идет на стол для класса, объявляющего принадлежащий_то ассоциация), но вы должны дать некоторые думал о фактическом значении данные также. Отношения HAS_ONE. говорит, что один из чего-то твой - то есть что-то указывает на ты.

Наконец, я не уверен, что вам нужно как содержимое, так и изображения, имеющие иностранные ключи. Пока изображения ссылаются на содержимое content_id, я думаю, что вы в порядке.

2
ответ дан 30 November 2019 в 08:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: