Rails的HAS_ONE VS belongs_to的语义 [英] Rails has_one vs belongs_to semantics

查看:145
本文介绍了Rails的HAS_ONE VS belongs_to的语义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含一些图片的模型重新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.

更新:

因为我已经创建了一个名为一个博客文章<一个href=\"http://kconrails.com/2010/01/26/single-table-inheritance-with-tests-in-ruby-on-rails/\">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的语义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆