Rails has_one vs belongs_to semantics

后端 未结 2 1768
猫巷女王i
猫巷女王i 2020-12-24 14:30

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.

2条回答
  •  清歌不尽
    2020-12-24 14:51

    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
    

    You don't need the foreign keys 'background_image_id' and 'profile_image_id' in the content table at all.

    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.

    UPDATE:

    I've since created a blog article called Single-Table Inheritance with Tests that goes into more detail, and covers testing.

提交回复
热议问题