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

Rails:使用具有相似复杂属性的ActiveRecord模型保持干燥

  •  5
  • Greg  · 技术社区  · 14 年前

    这似乎应该有一个直截了当的答案,但在谷歌上花了很多时间,所以我找不到它。这可能是因为缺少正确的关键字。

    在我的RoR应用程序中,有几个模型共享一种特定的字符串属性,该属性具有特殊的验证和其他功能。我能想到的最相似的例子是一个表示URL的字符串。

    这会导致模型中出现大量重复(在单元测试中甚至出现更多重复),但我不确定如何使其更干燥。

    我能想到几个可能的方向。。。

    1. 按照以下步骤创建一个插件: “验证url格式”插件, 但这只会让 验证干燥
    2. 给这根特殊的弦赋予它自己的模型,但这似乎是一个非常复杂的问题 重溶液
    3. 为这个特殊的字符串创建一个ruby类,但是我如何获得 ActiveRecord来关联这个类 模型属性是 数据库中的字符串

    第3个似乎是最合理的,但我不知道如何扩展ActiveRecord来处理基本数据类型之外的任何东西。有什么建议吗?

    最后,如果有办法做到这一点,那么在文件夹层次结构中,您会将非模型的新类放在哪里?

    非常感谢。

    使现代化 :

    下面是一个使用Matt的mixin建议(并使用URL示例)的潜在解决方案。注意,这更接近于伪代码而不是真正的ruby,旨在传达原则,而不是完美的语法。

    首先,创建一个 url 混音:

    module Url
      def url_well_formed?
        [...]
      end
    
      def url_live?
        [...]
      end
    end
    

    Site 型号,包括本模块:

    Class Site < ActiveRecord:Base
      include Url
    
      validate :url_well_formed?
    end
    

    当我需要检查URL上的站点是否处于活动状态时,请。。。

    if site.url_live?
      [...]
    end
    

    这并不能解决的问题是如何使单元测试干燥。如果我有另一个模型 Page ,它也使用 Url 在mixin中,仍然需要对URL进行一组重复的单元测试。当然,我可以把这些放在助手里,但这看起来很混乱。

    有没有更根本的解决方案,或者这是最好的解决方案?

    2 回复  |  直到 14 年前
        1
  •  6
  •   Harish Shetty    14 年前

    创建一个抽象模型:

    class CommonBase < ActiveRecord::Base
      self.abstract_class = true # makes the model abstract
      validate_format_of :url_field, :with => /.../
    end
    

    从抽象模型继承模型:

    class User < CommonBase
    end
    
    class Post < CommonBase
    end
    
        2
  •  2
  •   Matt Grande    14 年前

    您可以使用所有常用方法创建一个模块,然后导入该模块?谷歌搜索 mixins .