The ELC Community Blog
A knowledge exchange on Ruby on Rails and Agile Development
Rendering views without a web request in rails
by stevend on November 14, 2007
Why the heck do you want to do that?
Views are very well integrated into the rails framework, but they're only typically rendered when an http request comes in. ActionMailer is the main exception, but what if you want to render a view for use in another backend application? These days, document fragments are being used everywhere, and often times I'll need rendered HTML for a use other than just sending it back to the requesting user.
A solution: instantiate a controller and view
Controllers are just objects, and so are views. We can instantiate a controller, instantiate a view, then point the view to the controller and we're ready to go. The only think we're missing is the session and the request objects, but not every view needs those. I used this once for updating a facebook profile using a backgroundrb worker:
1 class FakeView < ActionView::Base
2 include SomeHelper
3 include SomeOtherHelper
4 end
5
6 class FakeController < ActionController::Base
7 def render_some_view
8 action_view = FakeView.new(File.join(RAILS_ROOT, "app", "views"), {})
9 action_view.instance_variable_set("@controller", self)
10 markup = action_view.render(:partial => 'facebook/your_profile')
11 end
12 end
By subclasses , you can mix helpers into the view class, making their
methods available. 1 ActionView::Base
Another solution: use the test framework!
The rails TestProcess is the only place where views are rendered. If you really want to simulate a real experience when rendering a view, use the test process. First, you'll need an actual controller with an actual action you want to render in it, like this one:
1 class FacebookController
2 before_filter :login_required
3
4 def your_profile
5 end
6 end
Then, we create and instante a test as follows:
1 class FacebookTest
2 include ActionController::TestProcess
3 attr_reader :response
4
5 def initialize
6 require_dependency 'application' unless defined?(ApplicationController)
7 @controller = UserScheduleEntryController.new
8 @request = ActionController::TestRequest.new
9 @response = ActionController::TestResponse.new
10 end
11
12 def render_your_profile(user)
13 @controller.instance_variable_set("@user", user) # bypass login required
14 get :your_profile
15 @response
16 end
17 end
18
19 test = FacebookTest.new
20 test.render_your_profile(user)
21 markup = test.response.body
The was something I threw in because backgroundrb didn't
have some of the
required classes loaded at that point, it may not be something you need in your application. 1 require_dependency
Timeline
- Ruby on Rails primer for Java developers
- OpenSocial container plugin 0.0.1
- Ultraviolet syntax highlighting in Mephisto
- Creating new generator commands
- Testing Libraries
- Rendering views without a web request in rails
- Can I Take a Test Drive?
- Points and Velocity in Trac Reports
- Installing Freeimage + image_science on Leopard
- Writing view helpers with 'yield'
- Duplicate Migrations in Rails Plugin
Comments
This is really awesome! Great post.
I used this:
template = ERB.new(File.readlines(‘app/views/dir/my_view.rhtml’).join(’’), nil, ’-’) html = template.result(binding)
That I found here: http://whynotwiki.com/Rails