-
Notifications
You must be signed in to change notification settings - Fork 336
Understanding RABL
I am hearing too often misunderstandings of how RABL works for testing, so here's an example of both functional and unit testing with RABL. You often do not need to do both, just test either one depending on your needs. If you are only using RABL for APIs check out the functional or integration testing. If you are using templates in order to serialize for non-API uses, check unit testing. Mix and match basically depending on your needs.
More examples of testing in isolation and using Rabl.render to render templates outside a controller context.
Also helpful to checkout our guide on managing complexity with presenters. RABL does not have to be at odds with using presenters. Exactly the opposite, they are best used together in conjunction. RABL to generate the view structure for JSON, XML, Plist, MsgPack, et al and then the complex logic and state managed where they belong in the presenters and models.
The bottom line is that JSON and XML are data exchange formats but they do fundamentally represent a view of your data not unlike an HTML view or any other format. View templates should not contain object and model logic or complex conditionals. Views are intended to be simple representations of your objects and this is where RABL fits into the picture. RABL works with Sinatra, Rails, Padrino and even outside the context of a web application with standalone rendering.
Serialization should be testable
Agreed and with RABL serialization is testable both in and outside of a web request context. Check out the other gists in this file for examples using Rabl.render to do standalone unit testing.
RABL can't be used for generating push notifications or in background jobs
Not at all true, I use RABL for these purposes in all of my applications. Simply use Rabl.render to render templates in any context.
RABL is linked inextricably to or requires ActionView, Rails, or a controller
See above. Simply not at all true. Simply use Rabl.render to render templates in any context.
Object serialization doesn't belong in templates
JSON and XML are data exchange formats and they do fundamentally represent a view of your data not unlike an HTML view or any other view format. JSON rendering in an API is a view of your data, there's no way around that. Moreso, even in other contexts outside of a controller the template is rendering an object into a representation. A ruby-based DSL such as RABL is a great way to create these representations. In addition, with RABL you can render into JSON, XML, Plist, MsgPack, et al using the same consistent templating language.
RABL templates can become complicated
As with all views, templates should not contain intricate object and model logic or complex conditionals. Views are intended to be simple representations of your objects and this is where RABL fits well into the picture. If you are worried about RABL views getting complex, you should apply best practices and extract RABL partials to reduce code duplication as with any view and use presenters to organize the code correctly.
Test the API response (if template is used an API generation):
require File.expand_path(File.dirname(__FILE__) + '/../test_config.rb')
describe "Post Controller" do
setup do
@post = Factory.generate(:body => "foo")
get :show, :id => @post.id
@result = JSON.parse(last_response.body)
end
it "should render post body" do
assert_equal "foo", @result['post']['body']
end
it "should be have other keys" do
assert_same_elements ['body', 'user_id', 'title'], @result['post'].keys
end
endor use unit tests to validate serialization (if template is used for serializing outside API generation):
require File.expand_path(File.dirname(__FILE__) + '/../test_config.rb')
describe "Post Serialization" do
setup do
@post = Factory.generate(:body => "foo")
@result = Rabl::Renderer.render(@post, 'posts/show', :format => :hash)
end
it "should render post body" do
assert_equal "foo", @result['post']['body']
end
it "should be have other keys" do
assert_same_elements ['body', 'user_id', 'title'], @result['post'].keys
end
end