代码之家  ›  专栏  ›  技术社区  ›  Anurag

Rails有一个属于语义的

  •  18
  • Anurag  · 技术社区  · 15 年前

    我有一个代表 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
    

    我只是不知道如何在这里正确地设置关联。这个 内容 模型可以包含两个 belongs_to 引用 图像 但这在语义上似乎不正确,因为理想情况下图像属于内容,或者换句话说,内容有两个图像。

    这是我能想到的最好的方法(通过破坏语义):

    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
    

    我是不是还有更好的方法来实现这种联系?

    2 回复  |  直到 15 年前
        1
  •  23
  •   Jaime Bellmyer    15 年前

    简单的答案是将关联设置为与所拥有的内容相反的形式,如下所示:

    # 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”(背景图像)和“profile”(配置文件)图像。

    不过,还有一个更优雅的解决方案: 单表继承。现在就设置它,以防将来背景图像和配置文件图像的行为稍有不同,而且它今天将澄清您的代码。

    首先,向图像表中添加一个名为“类型”的列:

    # 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
    

    这更符合您试图创建的数据模型,允许将来最简单的可扩展性,并且今天为您提供了一些很酷的新方法。

    更新:

    从那以后我就写了一篇名为 Single-Table Inheritance with Tests 这涉及到更多的细节,包括测试。

        2
  •  1
  •   Eli    15 年前

    基于 the AR associations guide ,我想你应该用 has_one . 一个图像拥有一个内容是没有意义的…内容肯定拥有形象。从指南:

    区别在于你所处的位置 外键(放在桌子上) 对于声明属于的类 但是你应该给一些 思考的实际意义 数据也是如此。有一种关系 说有件事是你的 也就是说,有些东西指向 你。

    最后,我不确定您是否需要内容和图像都有外键。只要图片引用了内容,我想你没事。