Question

Can't help but think there's a way to DRY up this proc a little but across files, but I'm a bit of a ruby n00b and I guess objectifying/exposing/referencing the proc is still out of my grasp conceptually. Is it doable?

# controller_1.rb
caches_page :flu, :if => Proc.new{ |c| c.request.format && !c.request.format.json? && !is_google_bot? && flash[:notice].nil? && flash[:error].nil? }
caches_page :baz, :if => Proc.new{ |c| c.request.format && !c.request.format.json? && !is_google_bot? && flash[:notice].nil? && flash[:error].nil? }
# controller_2.rb
caches_page :foo, :if => Proc.new{ |c| c.request.format && !c.request.format.json? && !is_google_bot? && flash[:notice].nil? && flash[:error].nil? }
caches_page :bar, :if => Proc.new{ |c| c.request.format && !c.request.format.json? && !is_google_bot? && flash[:notice].nil? && flash[:error].nil? }
Was it helpful?

Solution

Firstly you can add more than one action to caches_page. This simplify the code to:

# controller_1.rb
caches_page :flu, :baz, :if => Proc.new{ |c| c.request.format && !c.request.format.json? && !is_google_bot? && flash[:notice].nil? && flash[:error].nil? }

# controller_2.rb
caches_page :foo, :bar, :if => Proc.new{ |c| c.request.format && !c.request.format.json? && !is_google_bot? && flash[:notice].nil? && flash[:error].nil? }

Secondly, all your controllers should inherit from your ApplicationController, hence you can place this method there:

class ApplicationController < ActionController::Base
  #...

  private

  def should_cache_pages?
    request.format && request.format.json? && !is_google_bot? && flash[:notice].nil? && flash[:error].nil?
  end
end

Which will simplify those lines to:

# controller_1.rb
caches_page :flu, :baz, if: :should_cache_pages?

# controller_2.rb
caches_page :foo, :bar, if: :should_cache_pages?

However you can go even one step further - if you always call caches_page method with this if key, I would consider overriding this method (not tested):

class ApplicationController < ActionController::Base
  #...

  def self.caches_page(*args)
    options = args.extract_options!
    options[:if] = Array.wrap(option[:if]) << :should_cache_pages?
    super *args, options
  end

  private

  def should_cache_pages?
    request.format && request.format.json? && !is_google_bot? && flash[:notice].nil? && flash[:error].nil?
  end
end

Then it simplifies to:

# controller_1.rb
caches_page :flu, :baz

# controller_2.rb
caches_page :foo, :bar

OTHER TIPS

I'm pretty sure caches_page's :if option can take a method name so you could have a simple mixin:

module CacheHelpers
  def should_be_cached?(c)
    c.request.format && !c.request.format.json? && !is_google_bot? && flash[:notice].nil? && flash[:error].nil?
  end
end

and then include CacheHelpers in your controller classes and say:

# controller_1.rb
caches_page :flu, :if => :should_be_cached?
caches_page :baz, :if => :should_be_cached?

# controller_2.rb
caches_page :foo, :if => :should_be_cached?
caches_page :bar, :if => :should_be_cached?

If you're doing this sort of thing in most of your controllers then skip the separate CacheHelpers and throw it straight into ApplicationController.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top