2010-04-12 20 views
10

Chcę użyć zadania Rake, aby buforować moją mapę witryny, aby żądania dotyczące sitemap.xml nie trwały wiecznie. Oto co mam do tej pory:render_to_string z zadania rake

@posts = Post.all 

    sitemap = render_to_string :template => 'sitemap/sitemap', :locals => {:posts => @posts}, :layout => false 
    Rails.cache.write('sitemap', sitemap) 

Ale gdy próbuję uruchomić to pojawia się błąd:

undefined local variable or method `headers' for #<Object:0x100177298> 

Jak mogę renderowania szablonu sznurku od wewnątrz Rake?

+0

ten artykuł jest pomocny http://stackoverflow.com/questions/30725119/render-a -view-from-a-rake-task –

Odpowiedz

9

Oto jak to zrobiłem:

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

    include ActionController::UrlWriter 
    default_url_options[:host] = 'mysite.com' 

    posts = Post.all 

    sitemap = av.render 'sitemap/sitemap', :posts => posts 
    Rails.cache.write('sitemap', sitemap) 

pamiętać, że przekształcone mój szablon częściowy do tej pracy

+0

gdzie używasz hash default_url_options? –

4

Istnieje post o tym, jak uzyskać dostęp do metod i kontekstu ActionView :: Base z zadania rake.

Jest to jednak monkeypatch. Dlaczego nie skorzystać z szyn "cache mechanism do wykonania buforowania? :)

Późniejsza edycja: Funkcja render_to_string jest zdefiniowana w kontekście ActionController :: Base.

Poniżej znajduje się rozwiązanie pozwalające na sprawne działanie zadań rake, wykonanych od omninerd.

# In a rake task: 
av = ActionView::Base.new(Rails::Configuration.new.view_path) 
Rails.cache.write(
    "cache_var", 
    av.render(
    :partial => "view_folder/some_partial", 
    :locals => {:a_var => @some_var} 
) 
) 
+0

Mechanizm pamięci podręcznej jest świetny, ale czasami naprawdę po prostu chcesz okresowo generować zawartość offline w pliku. Zadanie rake to idealne miejsce na to - dobry link. –

+0

Nie mogę używać buforowania, ponieważ nie mogę renderować mapy witryny nawet raz w odpowiedzi na żądanie HTTP, ponieważ zajmuje to więcej niż 30 sekund, a Heroku przekracza limit czasu żądań HTTP o 30 sekund. –

+0

Masz rację. Czy podejście z wklejonego łącza działa dla Ciebie? –

1

Ostatnio chciałem zabrać zadanie natarcia zdefiniowany jak Horace Loeb wspomniano i przetłumaczyć go na samodzielną pracę w tle, ale niełatwo to przetłumaczyć.

Oto moje wdrożenie dla Rails 2.3.x, ponieważ znalezione Rails 3 implementation nie działa.

# Public: Template to render views outside the context of a controller. 
# 
# Useful for rendering views in rake tasks or background jobs when a 
# controller is unavailable. 
# 
# Examples 
# 
# template = OfflineTemplate.new(:users) 
# template.render("users/index", :layout => false, :locals => { :users => users }) 
# 
# template = OfflineTemplate.new(ProjectsHelper, PermissionsHelper) 
# template.render("projects/recent", :projects => recent_projects) 
# 
class OfflineTemplate 
    include ActionController::UrlWriter 
    include ActionController::Helpers::ClassMethods 

    # Public: Returns the ActionView::Base internal view. 
    attr_reader :view 

    # Public: Convenience method to 
    delegate :render, :to => :view 

    # Public: Initialize an offline template for the current Rails environment. 
    # 
    # helpers - The Rails helpers to include (listed as symbols or modules). 
    def initialize(*helpers) 
    helper(helpers + [ApplicationHelper]) 
    @view = ActionView::Base.new(Rails.configuration.view_path, {}, self) 
    @view.class.send(:include, master_helper_module) 
    end 

    private 

    # Internal: Required to use ActionConroller::Helpers. 
    # 
    # Returns a Module to collect helper methods. 
    def master_helper_module 
    @master_helper_module ||= Module.new 
    end 
end 

Jest to dostępne w formie: https://gist.github.com/1386052.

Następnie można użyć klasy powyżej stworzyć OfflineTemplate aby uczynić swoje poglądy w zadaniu natarcia:

task :recent_projects => :environment do 
    template = OfflineTemplate.new(ProjectsHelper, PermissionsHelper) 
    puts template.render("projects/recent", :projects => recent_projects) 
end 
Powiązane problemy