向application_controller添加一个方法,以便所有控制器和视图都可以看到它

时间:2011-05-27 21:50:07

标签: ruby-on-rails ruby

我想创建一个可在所有控制器和视图中使用的方法。

这个方法实际上是一个db调用来获取数据,所以因为它不会一直用到我希望它被延迟加载。

class ApplicationController < ActionController::Base


  def some_method
    @object = customdb.call_method(....)
  end

end

为了让它懒洋洋地加载,我只是这样做吗?

@object ||= ....

如何将其传播到所有控制器和查看页面?

4 个答案:

答案 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将被实例化。