问题描述
我有一个包含一些图片的模型重新presenting一个内容
项。作为这些图像的引用是非常具体的内容图像的数量是固定的。例如,内容
模式指的是图片
模型两次(资料图片,和背景图像)。我试图避免通用的has_many
,并坚持到多个 HAS_ONE
的。当前数据库结构如下:
I have a model representing a Content
item that contains some images. The number of images are fixed as these image references are very specific to the content. For example, the Content
model refers to the Image
model twice (profile image, and background image). I am trying to avoid a generic has_many
, and sticking to multiple has_one
's. The current database structure looks like:
contents
- id:integer
- integer:profile_image_id
- integer:background_image_id
images
- integer:id
- string:filename
- integer:content_id
我只是无法弄清楚如何建立正确的关联这里。在内容
模型可以包含一个图像两个
的,但似乎并不语义权利原因理想的图像所属的内容,或者换句话说,该内容具有两个图像。 belongs_to的
引用
I just can't figure out how to setup the associations correctly here. The Content
model could contain two belongs_to
references to an Image
, but that doesn't seem semantically right cause ideally an image belongs to the content, or in other words, the content has two images.
这是我能想到的最好的(通过打破语义):
This is the best I could think of (by breaking the semantics):
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
我是遥远,并且有更好的方法来实现此关联?
Am I way off, and there a better way to achieve this association?
推荐答案
答案很简单设置你在你所拥有的,像这样的反向关联:
The simple answer is to setup your associations in reverse of what you have, like so:
# 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在内容表中都没有。
You don't need the foreign keys 'background_image_id' and 'profile_image_id' in the content table at all.
然而,有一个更优雅的解决方案:单表继承。现在把它架在你想要的背景和图像轮廓表现甚至略有不同,今后的情况下,再加上它今天澄清你的code。
However, there's a more elegant solution: single table inheritance. Set it up now in case you want background and profile images to behave even slightly differently in the future, plus it will clarify your code today.
首先,列添加到您的图像表称为类型:
First, add a column to your images table called type:
# command line
script/generate migration AddTypeToImages type:string
rake db:migrate
现在设置你的模型是这样的:
Now setup your models like this:
# 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
现在,你可以做各种事情好像让所有的背景图片的列表:
Now you can do all kinds of things like getting a list of all background images:
# script/console
BackgroundImage.all
这是更真实你想创建数据模型,使得在未来的最简单的可扩展性,和凉爽的今天一些新的方法给你。
This is more true to the data model you're trying to create, allows the easiest expandability in the future, and gives you some cool new methods today.
更新:
因为我已经创建了一个名为一个博客文章Single-Table与测试是继承进入更多的细节,并覆盖测试。
I've since created a blog article called Single-Table Inheritance with Tests that goes into more detail, and covers testing.
这篇关于Rails的HAS_ONE VS belongs_to的语义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!