这样的事情:
班级类别
SOME_CATEGORY = find_by_name("some category")
端
类别:: SOME_CATEGORY
尝试没有问题,但想知道这是不是一个坏主意,以及原因,如果有的..
感谢
答案 0 :(得分:6)
如果您不想在每次必须缓存模型时都访问数据库。有几种方法可以做到这一点,但一种快速方法是使用Memoization。这是在Rails 2.2中引入的。
class Category < ActiveRecord::Base
class << self
extend ActiveSupport::Memoizable
def named(name)
find_by_name(name)
end
memoize :named
end
end
像这样使用它。
Category.named("some category") # hits the database
Category.named("some category") # doesn't hit the database
缓存应该在请求之间保持持久性。您可以通过将true
作为最后一个参数来重置缓存。
Category.named("some category", true) # force hitting the database
答案 1 :(得分:0)
你想做什么?
也许:
class Category
def self.some_category
Category.find_by_name("some category")
end
end
所以你可以打电话:
Category.some_category
=> <Category#2....>
答案 2 :(得分:0)
这不是一个可怕的想法,但它也不是一个好主意。它并没有真正符合Rails做事的方式。首先,你会得到很多丑陋的常量代码。太多的ALL_CAPS_WORDS和你的Ruby开始看起来像C ++。 Bleah。
另一方面,它不灵活。你打算为每个类别制作这些常量之一吗?如果您在两个月后添加新类别,您是否记得更新Rails代码,添加新常量,重新部署并重新启动服务器?
如果您能够非常轻松地访问类别并且不重复数据库查询,那么这里有一些元编程,它会自动查找它们并在第一次访问时为您创建像Lichtamberg这样的静态方法:
def self.method_missing(category, *args) # The 'self' makes this a class method
@categories ||= {}
if (@categories[category] = find_by_name(category.to_s))
class_eval "def self.#{category.to_s}; @categories[#{category}]; end"
return @categories[category]
end
super
end
使用此方法,无论何时第一次调用Category.ham
,它都会创建一个返回值find_by_name("ham")
的类方法 - 这样查询和method_missing()
都不会运行下次你打电话的时候再来一次。这就像 OpenStruct 类的工作方式一样,BTW;如果你想了解更多信息,请在Pickaxe书中查阅。
(当然你仍然有风险,因为这些都是记忆,你的Rails应用程序不会反映你对你的类别对象所做的任何改变。这假设改变不会发生或不做'真的很重要。由你决定这个假设对你的应用程序是否有效。你可以在你的代码中放置一个after_update
回调,如果这是一个问题就会重置@@categories
;但是在这一点上开始变得复杂。)