strapyourself.in and flouri.sh
Rendering views without a web request in rails
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:
class FakeView < ActionView::Base include SomeHelper include SomeOtherHelper end class FakeController < ActionController::Base def render_some_view action_view = FakeView.new(File.join(RAILS_ROOT, "app", "views"), {}) action_view.instance_variable_set("@controller", self) markup = action_view.render(:partial => 'facebook/your_profile') end end
By subclasses ActionView::Base, you can mix helpers into the view class, making their
methods available.
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:
class FacebookController before_filter :login_required def your_profile end end
Then, we create and instante a test as follows:
class FacebookTest include ActionController::TestProcess attr_reader :response def initialize require_dependency 'application' unless defined?(ApplicationController) @controller = UserScheduleEntryController.new @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new end def render_your_profile(user) @controller.instance_variable_set("@user", user) # bypass login required get :your_profile @response end end test = FacebookTest.new test.render_your_profile(user) markup = test.response.body
The require_dependency 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.
Sorry, comments are closed for this article.