У меня есть модель, представляющая 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
Я - путь прочь и там лучший способ достигнуть этой ассоциации?
Простой ответ - настроить ваши ассоциации в обратном направлении того, что у вас есть, например:
# 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
Это Более верно для модели данных, которую вы пытаетесь создать, позволяет самым простым расширением в будущем и дает вам несколько прохладных новых методов сегодня.
Обновление:
Я со временем создал блог по имени одностатистого наследства с тестами , который входит в более подробную информацию и охватывает тестирование.
На основании Руководство ассоциаций AR , я думаю, вы должны использовать HAS_ONE
. Это не имеет смысла к изображению владеть контентом ... Содержание обязательно владеет изображением. Из руководства:
Различие находится в том, где вы находитесь внешний ключ (он идет на стол для класса, объявляющего принадлежащий_то ассоциация), но вы должны дать некоторые думал о фактическом значении данные также. Отношения HAS_ONE. говорит, что один из чего-то твой - то есть что-то указывает на ты.
Наконец, я не уверен, что вам нужно как содержимое, так и изображения, имеющие иностранные ключи. Пока изображения ссылаются на содержимое content_id, я думаю, что вы в порядке.