在Rails中动态创建模型和/或表格

13

我目前正在处理一个项目,其中有一个非常不寻常的需求,希望能得到一些建议,以便最好的方法来处理它,甚至可以提供一些指针来帮助我建立一个解决方案。

好的,这就是我需要做的。应用程序存储和管理各种类型的媒体文件,但每个应用程序的部署都具有完全不同的媒体文件元数据要求。

这些元数据可以包含任意数量的不同类型的字段(单行文本、多行文本、复选框、选定值等),通常需要验证,特别是存在性和唯一性验证。

应用程序需要能够轻松检索值,并且最重要的是必须能够处理这些字段的完整搜索功能。

我考虑的一种选择是使用属性列表排列,其中数据库表仅包含每个媒体文件的每个元数据字段的属性名称和值。然而,在原型设计此解决方案时,很快变得明显,当数据库可能相当大时,即使对于记录的搜索和检索而言,它也不能足够高效,例如最近的部署有3000个媒体文件,有超过20个元数据字段。此外,执行搜索和检索相关记录的查询很快变得非常复杂。

系统当前使用的另一种选择是预先定义元数据配置,并在部署期间运行迁移以创建具有标准名称的表和模型,以便媒体模型可以与其关联,然后系统将使用该模型。这通常工作得很好,但它确实会导致一些重大的部署和测试问题。

例如,当您不知道配置信息直到部署时,编写单元测试变得更加具有挑战性。虽然我可以编写一个示例配置并通过那样来测试代码,但它不允许我测试特定部署的具体要求。

同样,在开发中,它目前需要我将配置文件中的迁移复制到主文件夹中,并运行它,进行所有的测试和开发,然后我必须记住回滚并从主文件夹中删除该迁移,以使应用程序处于标准状态。当我进行错误修复并需要将应用程序置于特定配置以进行测试和调试时,这尤其具有挑战性。尝试在各种配置之间切换成为一个真正的噩梦。

理想情况下,我希望能够在服务器启动时从配置文件动态创建包括验证等在内的表格和模型。更好的情况是,如果我可以在一个数据库中维护多个元数据设置,并且每个设置都有自己的表格,那么我只需要改变应用程序当前使用的配置文件即可在它们之间切换。

我相信这可以通过Rails来实现,但在过去几天的研究中,我找到的关于如何构建它的信息非常少,因此任何帮助或建议将不胜感激!

5个回答

4
如果我理解正确的话,Rails有一些巧妙的技巧可以帮助您解决这些问题。在ActiveRecord ORM中,可以使用单表继承模式或多态关联来对关系型数据库进行建模(后者更加复杂但更加灵活)。多态关联允许一个模型属于不同类型的其他模型。最近有一篇关于这个主题的railscast,但我不会链接到它,因为它需要付费订阅。
在部署方面,听起来你正在手动完成很多事情,这是开始的正确方式,直到出现模式。一旦开始看到模式,就有优秀的程序可用于配置、构建和部署自动化,例如Capistrano、OpsCode ChefPuppet等。你还可以通过将配置和部署与源代码存储库集成,实现更好的工作流程。例如,使用Git,你可以为各种媒体文件类型定义主题分支,并在每个分支中具有不同的配置,以匹配主题分支。
你可能想要查看马丁·福勒(Martin Fowler)的优秀书籍 'PoEAA' 以及他 网站 上的一些主题。我希望这个答案能够帮到你,即使这个答案相当通用。你的问题非常广泛,没有一个简单的答案。

2
每个应用程序部署都需要完全不同的媒体文件元数据要求。
我建议使用 mongoDB 作为数据库,Mongoid 作为 ORM。这将为您提供所需的灵活性,以便根据需要更改模式,而无需进行可怕的模式操作、动态模型/表等等。
应用程序需要能够轻松检索值,最重要的是必须能够处理这些字段的全面搜索功能。
这是一个搜索问题,而不是数据库问题。我建议尝试使用最新版本的mongoDB中的全文本搜索功能。如果不能满足您的需求,请尝试elasticsearch与Rails良好集成的Tire gem(一个elasticsearch客户端)。

1

您所描述的情况正是使用键值存储的非传统存储机制所需的定义要求。

我从以下几点感觉到这一点:

  • "完全不同的元数据要求"和“任意数量的不同类型字段” - 键值数据存储通常没有架构,并且非常灵活,可以适应不断变化的记录布局。

  • 应用程序需要能够轻松检索值,最重要的是必须能够处理这些字段上的完整搜索功能。键值存储被设计为极其高效地检索和过滤查询行。

"属性列表安排,其中数据库表仅包含每个元数据的属性名称和值"基本上就是一个键值存储。

一些选项包括:


1
是的,那也是我的第一反应,也是我最初打算做的事情。但当我实现了一个原型解决方案后,基本搜索只检索字段的速度大约比基于表格的解决方案慢10倍。而且当你加上运行搜索以过滤记录的成本时,它很快就变得无法承受,特别是考虑到搜索功能对整个应用程序的操作非常基础。 - richard

1

根据您的具体要求,我可以看到几种合理的方法来解决这个问题:

  1. 如果编写每个元数据集的模型和迁移不会产生障碍,则可以为每个元数据集生成一个模型和迁移。然后,在您的每个环境配置文件中 - 例如 config/development.rb - 将所需的模型加载到全局常量中(可能是 lib/model_configuration.rb 中的 ModelConfiguration::MetadataModel)。编写应用程序的其余部分,只通过这个常量与元数据模型交互。

    这种方法非常高效;它唯一的缺点是你要为每个模型在数据库中生成一个额外的表。在运行时,未使用的模型甚至没有被加载,因此它们根本不会影响性能。

  2. 另一方面,您可能有很多元数据模型,这种方法过于繁琐,或者您可能无法预先知道元数据模型。在这种情况下,我会采取以下措施:

    • 将当前所需的模型配置以某种易于消化的形式加载到全局常量中(可能是 ModelConfiguration::ModelJSON)。

    • 编写一个单一模型类,在加载时查找ModelConfiguration::ModelJSON并调用一个类方法,从该配置中安装相应的字段和验证。

    • 编写一个 Rake 任务以构建与您的配置相匹配的表。有关如何编写 Rake 任务的快速概述,请参见 http://edgeguides.rubyonrails.org/command_line.html#custom-rake-tasks。最简单的方法可能是从您的配置生成一个一次性迁移,然后运行该迁移(通过调用.up)。这里的缺点是一次性迁移在任务运行后将消失,因此您将无法访问rake db:rollback

    这种方法非常通用,其最大优点是您不需要更改代码即可获得配置更改,这使得您在存储和部署配置方面具有很大的自由度。


0
也许可以使用存储元数据的jsonb字段,并为这些字段创建一个动态视图层,以便进行CRUD操作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接