views:

38

answers:

1

I'm trying to encapsulate the logic for generating my sitemap in a separate class so I can use Delayed::Job to generate it out of band:

class ViewCacher
  include ActionController::UrlWriter

  def initialize
    @av = ActionView::Base.new(Rails::Configuration.new.view_path)
    @av.class_eval do
      include ApplicationHelper      
    end
  end

  def cache_sitemap
    songs = Song.all

    sitemap = @av.render 'sitemap/sitemap', :songs => songs
    Rails.cache.write('sitemap', sitemap)
  end
end

But whenever I try ViewCacher.new.cache_sitemap I get this error:

ActionView::TemplateError: 
ActionView::TemplateError (You have a nil object when you didn't expect it!
The error occurred while evaluating nil.url_for) on line #5 of app/views/sitemap/_sitemap.builder:

I assume this means that ActionController::UrlWriter is not included in the right place, but I really don't know

A: 

Does this do what you're trying to do? This is untested, just an idea.

in lib/view_cacher.rb

module ViewCacher
  def self.included(base)
    base.class_eval do
      #you probably don't even need to include this
      include ActionController::UrlWriter
      attr_accessor :sitemap

      def initialize
        @av = ActionView::Base.new(Rails::Configuration.new.view_path)
        @av.class_eval do
          include ApplicationHelper      
        end
        cache_sitemap
        super
      end

      def cache_sitemap
        songs = Song.all

        sitemap = @av.render 'sitemap/sitemap', :songs => songs
        Rails.cache.write('sitemap', sitemap)
      end
    end
  end
end

then wherever you want to render (I think your probably in your SitemapController):

in app/controllers/sitemap_controller.rb

class SitemapController < ApplicationController
  include ViewCacher

  # action to render the cached view
  def index
    #sitemap is a string containing the rendered text from the partial located on
    #the disk at Rails::Configuration.new.view_path

    # you really wouldn't want to do this, I'm just demonstrating that the cached
    # render and the uncached render will be the same format, but the data could be
    # different depending on when the last update to the the Songs table happened
    if params[:cached]
      @songs = Song.all

      # cached render
      render :text => sitemap
    else
      # uncached render
      render 'sitemap/sitemap', :songs => @songs
    end
  end
end
Patrick Klingemann