RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 623485
Accepted
srghma
srghma
Asked:2020-02-05 05:11:46 +0000 UTC2020-02-05 05:11:46 +0000 UTC 2020-02-05 05:11:46 +0000 UTC

用户有_一个头像但是书有_多个封面怎么办?

  • 772

我想要一个表images(其中包含一个字段file:string),以及类似这个模型结构的东西

class BookCover
  mount_uploader :file, BookCoverUploader
end

class Book
  has_many :covers, class: 'BookCover'
end

class UserAvatar
  mount_uploader :file, UserAvatarUploader
end

class User
  has_one :avatar, class: 'UserAvatar'
end

如何实现这一目标,使用什么?单表继承还是多态关联?我想轻松地抓住images某些user或book(例如,删除而不用imageable_id)。你会如何组织表格?

更新

从理论上讲,这应该可行,对吧?

# прием отсюда https://maulanaruby.wordpress.com/2007/02/17/sti-vs-polymorphic-association/

class CreateImages < ActiveRecord::Migration[5.0]
  def change
    create_table :images do |t|
      t.string :file, null: false

      t.string :type, null: false
      t.integer :source_id, null: false

      t.timestamps
    end
  end
end


class Image < ActiveRecord::Base
end

class Cover < Image
  mount_uploader :file, CoverUploader
  belongs_to :book, foreign_key: 'source_id'
end

class Avatar < Image
  mount_uploader :file, AvatarUploader
  belongs_to :user, foreign_key: 'source_id'
end

class Book < ActiveRecord::Base
  has_many :covers
end

class User < ActiveRecord::Base
  has_one :avatar
end
ruby-on-rails
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    user181100
    2020-02-06T06:55:36Z2020-02-06T06:55:36Z

    你想做的事情(可能是徒劳的,但稍后会详细介绍)实际上是由多态关联完成的。创建一个表,其中“外键”(不是真实的,但它是什么)由两个字段表示:штука_type和штука_id,Rails 在模型中指定时使用它们:

    belongs_to :штука, polymorphic: true
    

    并且,分别设置相反的has_manyor has_one,with as: :штука(因为一切都符合多态,所以没有什么可以猜测选择哪个名称,没有什么可做的,您需要明确指定名称)。

    但总的来说,多态是一个相当肮脏的把戏。在数据库级别为它们组织数据一致性控制将非常困难(如果可能的话 - 我还没有看到一个 RDBMS 允许你为整个表而不是为一小部分创建外键) ,您甚至可以进行涉及此关联尝试的复杂查询。


    为什么不是性传播感染?

    如果你为每个值匹配一个且只有一个所有者类type,那么你将得到一个多态形式的拐杖,而штука_type它只是type,并且不会直接有所有者类型,但是你可以从中学习的东西它。

    它在结构上与多晶型非常相似,也有它的所有缺点。


    也许最好把它UserAvatar作为一个不必要的实体一起扔掉?

    如果在任何给定时间对于每个条目User您期望一个且只有一个条目UserAvatar,那么最好将这两个实体作为一个实体的一部分。为什么不让用户的头像成为模型内部的一个字段?

    还有一个稍微更一般的规则:如果两个实体是一对一的关系,考虑它们是否真的应该是同一个实体?


    可怕实验的领域:PostgreSQL 及其继承

    如果您没有 PostgreSQL,那么您无法继续阅读 :)

    如果您真的非常希望能够一次爬取所有模型的图片,您可以采取骑士行动并使用继承,而不是从 ActiveRecord 继承,而是直接从数据库继承。PostgreSQL 有它,这里是一个迁移和模型的例子:

    class CreateImages < ActiveRecord::Migration[5.0]
      def change
        # Базовая таблица с общими полями
        #                     vvvvvvvvv ВАЖНО
        create_table :images, id: false do |t|
          t.string :url
        end
    
        # Просто модели
        create_table :apples do |t|
          t.timestamps
        end
        create_table :oranges do |t|
          t.timestamps
        end
    
        # А вот тут самое интересное!
        create_table :apple_images, options: "INHERITS (images)" do |t|
          t.references :apple, foreign_key: true
        end
    
        create_table :orange_images, options: "INHERITS (images)" do |t|
          t.references :orange, foreign_key: true
        end
      end
    end
    

    值得一提的是:

    • the schema is exported with losses,继承成功丢失,需要在sql选项中直接schema.rb添加到export中config/application.rb

       config.active_record.schema_format = :sql`
      
    class Image < ApplicationRecord
    end
    
    class Apple < ApplicationRecord
      has_many :apple_images
    end
    
    class AppleImage < ApplicationRecord
      belongs_to :apple
    end
    
    class Orange < ApplicationRecord
      has_many :orange_images
    end
    
    class OrangeImage < ApplicationRecord
      belongs_to :orange
    end
    
    • 子表Image没有主键。而且,不幸的是,它不能,因为 PostgreSQL 不支持在基表上创建唯一键(根据定义,主键是唯一的)。因此,将无法以通常的 ActiveRecord 方式更新表的各个行,并且不支持可以删除文件的回调。

    但如果您愿意,您可以对所有图片提出一般要求。并将字段添加到images也会将它们添加到所有后代表中。

    看看这个解决方案是否可以帮助您。至少,它保留了对外键的一致性控制。作为一种实践,您甚至可以向基表添加外键列,并在后代表中自行创建外键。

    • 1

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    Python 3.6 - 安装 MySQL (Windows)

    • 1 个回答
  • Marko Smith

    C++ 编写程序“计算单个岛屿”。填充一个二维数组 12x12 0 和 1

    • 2 个回答
  • Marko Smith

    返回指针的函数

    • 1 个回答
  • Marko Smith

    我使用 django 管理面板添加图像,但它没有显示

    • 1 个回答
  • Marko Smith

    这些条目是什么意思,它们的完整等效项是什么样的

    • 2 个回答
  • Marko Smith

    浏览器仍然缓存文件数据

    • 1 个回答
  • Marko Smith

    在 Excel VBA 中激活工作表的问题

    • 3 个回答
  • Marko Smith

    为什么内置类型中包含复数而小数不包含?

    • 2 个回答
  • Marko Smith

    获得唯一途径

    • 3 个回答
  • Marko Smith

    告诉我一个像幻灯片一样创建滚动的库

    • 1 个回答
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Алексей Шиманский 如何以及通过什么方式来查找 Javascript 代码中的错误? 2020-08-03 00:21:37 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5