Reputation: 11257
I got the following code in a rake task:
class PdfExporter < ActionView::Base
include Rails.application.routes.url_helpers
include ActionView::Helpers::TagHelper
include ActionView::Helpers::UrlHelper
def generate_pdf_from_html
content = File.read('path/to/view.html.erb')
erb = ERB.new(content)
html_content = erb.result(binding)
# ... some pdf stuff
end
end
The problem - the said view.html.erb is rendering another view in it.
<%= render partial: 'path/to/another_view' %>
And erb.result(binding)
is throwing the following error:
Missing partial /path/to/another_view
If there are no partials, the view renders fine.
I'm sure that the path is right, but seems that I can't render it from a rake task.
Why? Can I include some useful helper?
I don't want to instantiate controllers.
EDIT:
Searched in:
is empty. Probably means that the ActionView don't 'know' where to search for the view.
Upvotes: 3
Views: 1347
Reputation: 9015
Here is an example of a rake task I have that creates an html file from a view. For it to work, you have to appease ActionView by overriding some defaults and by passing in a fake controller and request:
desc 'Example of writing a view to a file'
task :example => :environment do
# View that works with Rake
class RakeActionView < ActionView::Base
include Rails.application.routes.url_helpers
include ::ApplicationHelper
# Include other helpers that you will use
# Make sure this matches the expected environment, e.g. localhost for dev
# and full domain for prod
def default_url_options
{host: 'localhost:3000'}
end
# It is safe to assume that the rake request is legit
def protect_against_forgery?
false
end
end
# build a simple controller to process the view
controller = ActionController::Base.new
controller.class_eval do
include Rails.application.routes.url_helpers
include ::ApplicationHelper
end
# build a fake request
controller.request = ActionDispatch::TestRequest.new
# build the rake view with the path to the app views
view = RakeActionView.new(Rails.root.join('app', 'views'), {}, controller)
# example assigning instance @variables to the view
view.assign( :user => User.first )
# Render the view to html
html = view.render(template: 'relative/path/to/template', layout: 'layouts/example')
# Write html to temp file and then copy to destination
temp = Tempfile.new('example_file')
temp.write(html)
FileUtils.cp( temp.path, 'path/to/exmple_file' )
# optionally set permissions on file
File.chmod(0774, 'path/to/exmple_file')
# close up the temp file
temp.close
temp.unlink
end
Looks like the issue you are having is fixed by RakeActionView.new(Rails.root.join('app', 'views'), {}, controller)
which sets the path that ActionView looks for templates.
Upvotes: 3