2013-02-13 80 views
2

我有一个使用ActiveRecord的Sinatra应用程序,我希望添加一个功能,可以为一组记录生成指纹(SHA1)。正确的设计:在ActiveRecord或辅助方法中包含模块

我实现这一点的方式是通过定义模块和包括内ActiveRecord::Relation,如下所示:

module Fingerprints 
    def sha1 
    Digest::SHA1.hexdigest map{ |record| record.attributes.values.join }.join 
    end 
end 

ActiveRecord::Relation.send :include, Fingerprints 

我现在可以称之为“SHA1”上ActiveRecord::Relation得到我所需要的价值。

我的问题是这是否是“首选”的方式来做到这一点(扩展ActiveRecord与额外的功能)?

使用send的最后一行对我来说感觉不太清楚,简单的事实是,我将特征绑定到不属于我自己的类上的特征也感觉像是黑客。我知道这是Ruby中的一种标准模式,但以这种方式进入ActiveRecords的内核并修补它对我来说是陌生的。

另一种方法是创建一个需要ActiveRecord::Relation并返回指纹的Sinatra助手。虽然这感觉更清洁,但我不禁感到sha1方法应该属于ActiveRecord::Relation类,以更好地描述它的意图。

这可能只是个人喜好,但我会对其他人如何做这件事感兴趣,以及是否有这样做的“正确”方式的感觉。

感谢

+1

为什么把它添加到ActiveRecord的时候可以将其添加到各个模型类? – iain 2013-02-14 00:50:48

+0

因为我希望能够为一组记录生成指纹。例如,当您执行'Model.scoped'时,将返回一个包含模型对象的'ActiveRecord :: Relation'实例。这是我想为其生成指纹的集合,而不是单个模型(我已经为单个模型添加了指纹识别) – 2013-02-14 10:12:58

回答

0

说实话,我不能看到你所做的任何实际问题。 也许调用方法fingerprint_sha以防止破坏,也许添加自定义异常,以便如果发生任何问题,您知道它在您的代码中开始,而不是AR的。

就我个人而言,我可能已经将这个帮助器传递给了关系,如果方法是在帮助器中为其他人定义的,那么它可能会更加明显,但像我说的我没有看到问题与你所做的一样,并认为这是一个很好的解决方案。

也许别人会来,说不同的,我们俩在这里学到一些东西:)

+1

这就是主意。我在我自己的时间里编写了我个人项目中的大部分Ruby代码,因此难以从其他开发人员那里以“正确”的方式进行操作。我有一种感觉,帮助者会更清楚,但它仍然是50/50在我心中 – 2013-02-14 13:13:18

+1

@philostler我可以推荐Russ Olsen的“雄辩红宝石”作为一种习惯写作方法。除此之外,阅读Sinatra等项目的源代码真的很有帮助,但是很多最知名的项目最少有评论...:/ – iain 2013-02-14 13:38:30

+1

我有他的“Ruby设计模式”,这也是一个很好的阅读。这看起来也值得一读。感谢提示,非常有价值 – 2013-02-14 14:18:05