我想创建一个可在所有控制器和视图中使用的方法。
这个方法实际上是一个db调用来获取数据,所以因为它不会一直用到我希望它被延迟加载。
class ApplicationController < ActionController::Base
def some_method
@object = customdb.call_method(....)
end
end
为了让它懒洋洋地加载,我只是这样做吗?
@object ||= ....
如何将其传播到所有控制器和查看页面?
答案 0 :(得分:4)
在 ApplicationController 中使用 helper_method ,可以在任何控制器或视图中使用some_method:
class ApplicationController < ActionController::Base
helper_method :some_method
def some_method
@object ||= customdb.call_method(....)
end
end
|| =每个请求缓存,而不是延迟加载。延迟加载是deferred initialization模式。
视图中的大范围和控制器方法是代码味道。你应该最小化对象范围和视图逻辑。你可以绊倒并捅一眼。
答案 1 :(得分:1)
您可以使用memoize
ActiveSupport
功能
http://api.rubyonrails.org/classes/ActiveSupport/Memoizable.html
http://ryandaigle.com/articles/2008/7/16/what-s-new-in-edge-rails-memoization
所以可能是这样的:
class ApplicationController < ActionController::Base
def some_method
@object = customdb.call_method(....)
end
memoize :some_method
end
答案 2 :(得分:1)
如果您希望跨越交叉请求可以访问结果,则必须将结果存储在类变量中:
class ApplicationController < ActionController::Base
helper_method :city_list
def city_list
@@city_list =|| City.order(:name)
end
end
结果是延迟加载和缓存。
PS:变量@@city_list
是一个类变量。
答案 3 :(得分:0)
您应该使用before_filter
class ApplicationController < ActionController::Base
before_filter :some_method
def some_method
@object = customdb.call_method(....)
end
end
它将在所有控制器中触发。
请注意,您可以在使用skip_before_filter :some_method
过滤之前跳过此处。您甚至可以阻止此过滤器前面的某些操作。
因为这将在所有已确定的控制器操作之前触发,所以您不需要您的行:
@object ||= ....
因为@object
将被实例化。