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

时间:2013-04-11 05:17:43

标签: ruby-on-rails dynamic model

我目前正在开展一个项目,这个项目有一个非常不寻常的要求,我希望得到一些关于处理它的最佳方法的建议,甚至是一些可以帮助我构建解决方案的信息指针。< / p>

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

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

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

我考虑的一个选项是使用属性列表排列,其中数据库表只包含每个媒体文件的每个元数据字段的属性名称和值。然而,当对该解决方案进行原型设计时,很快就会发现它对搜索和检索记录的效率不高,特别是当数据库可能相当大时,例如最近的部署有3000个媒体文件,有20多个元数据字段。此外,快速搜索和检索相关记录的查询变得非常复杂。

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

例如,如果在部署之前不知道配置,则编写单元测试会变得更具挑战性。虽然我可以编写示例配置并以这种方式测试代码,但它不允许我测试特定部署的特定要求。

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

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

我确信这可以通过Rails完成,但是我能够找到的信息非常少,可以指出我在过去几天的研究中如何构建它的正确方向,所以任何非常感谢帮助或建议!

5 个答案:

答案 0 :(得分:4)

如果我理解正确,Rails会有一些巧妙的技巧来帮助你解决这些问题。

在ActiveRecord ORM中,可以使用单表继承模式或polymorphic associations来模拟您在关系数据库中尝试执行的操作(...更复杂但更灵活)。多态关联允许模型属于不同类型的其他模型。最近有一个关于这个主题的轨道广播,但我不会链接到它,因为它需要付费订阅。

在部署方面,听起来你手动做了很多事情,这是在模式出现之前开始的正确方法。一旦您开始看到该模式,就有一些优秀的程序可用于配置,构建和部署自动化,例如Capistrano,OpsCode ChefPuppet,仅举几例。您还可以将配置和部署与源代码存储库集成,以实现更好的工作流程。例如,使用Git,您可以为各种媒体文件类型定义topic branches,并在每个分支中具有与主题分支匹配的不同配置。

你可能想查看Martin Fowler的优秀书籍“PoEAA”以及他website上的一些主题。我希望这个答案有所帮助,即使答案非常通用。你的问题非常广泛,没有一个简单的答案。

答案 1 :(得分:2)

  

应用程序的每个部署都有完全不同的元数据   媒体文件的要求。

我建议您为数据库使用mongoDB,为您的ORM使用Mongoid。这将为您提供根据需要更改架构所需的灵活性,而无需可怕的架构操作,动态模型/表格以及所有这些恐怖。

  

应用程序需要能够轻松检索值和大多数值   重要的是必须能够处理完整的搜索功能   这些领域。

这是一个搜索问题,而不是数据库问题。我建议在最新版本的mongoDB中尝试全文搜索功能。如果这不符合您的需求,请与elasticsearch gem(一个与Rails很好地集成的elasticsearch客户端)一起尝试Tire

答案 2 :(得分:1)

您所描述的内容与使用键值存储的非传统存储机制的定义要求完全相同。

我感觉到这一点:

  • '完全不同的元数据要求'和' - '任意数量的不同类型的字段' - 键值数据存储通常没有架构,并且对于即时更改的不同记录布局非常灵活。

  • 应用程序需要能够轻松检索值,最重要的是必须能够处理这些字段的完整搜索功能。键值存储在检索和过滤查询行方面非常有效。

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

有些选择是:

答案 3 :(得分:1)

我可以看到一些合理的方法来解决这个问题,具体取决于您的具体要求:

  1. 如果为每个元数据集编写模型和迁移并不过分,那么请继续为每个元数据集生成模型和迁移。然后,在您的每个环境配置文件中 - 例如config/development.rb - 将该环境的所需模型加载到全局常量(ModelConfiguration::MetadataModellib/model_configuration.rb}。编写应用程序的其余部分,仅通过此常量与元数据模型进行交互。

    这种方法非常有效;它唯一真正的缺点是你在数据库中为每个模型制作一个额外的表。在运行时,永远不会加载未使用的模型,因此它们根本不会影响您的性能。

  2. 另一方面,你可能有这么多的元数据模型,这种方法太难以考虑,或者你可能没有提前知道元数据模型。在这种情况下,我会做以下事情:

    • 让您的配置将当前所需的模型配置加载到一个易于理解的全局常量中(可能是ModelConfiguration::ModelJSON)。

    • 编写一个模型类,加载后,查看ModelConfiguration::ModelJSON并调用类方法,从此配置中自行安装相应的字段和验证。

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

    这种方法非常通用,它的最大优点是您不需要更改代码就可以进行配置更改,这使您可以自由地存储和部署配置。

答案 4 :(得分:0)

也许使用存储元数据的jsonb字段并创建用于填充这些元数据的动态视图层。