Railsberry Lightning Talk: Playing with Render


Published on

Railsberry Lightning Talk: Playing with Render

Slides from the lightning talk I gave at Railsberry* on how you can wrap Rails' render function to expose universal options and and additional security to an API. It's an appetizer: I'll be talking in more detail about API uniformity and control at the Barcelona Ruby Conference in September 2012.

Best part of the talk: afterward, Yehuda Katz (yes, that @wycats) came by to tell me he had the same initial reaction [wrapping render = bad idea], but that no, the approach is quite fine. The signature is stable and ActionController::Metal does it too. Score.

* one of the sweetest Rails conferences I've been to, incidentally.

Published in: Technology, Business
  • Be the first to comment

  • Be the first to like this

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Railsberry Lightning Talk: Playing with Render

  1. 1. SOME INTERESTING THINGSYOU CAN DO WITH RENDER Being a Brief Treatise on Matters of Efficiency & Security Alex Koppel - Railsberry
  2. 2. BACKGROUND/GOALS  Wunderkit: an API-driven app  Give clients control over the data returned  Provide secured output  Universal implementation
  3. 3. THE RENDER METHOD  Stable signature (2.3-4.0beta)   For our purposes  Arguments => options hash  This hash is provided to renderers   to_json, to_xml, ActiveModel::Serializers, etc.  Controller action   Complete access to user state
  4. 4. DEF RENDER# /actionpack/lib/abstract_controller/rendering.rb (3.2)def render(*args, &block) options = _normalize_render(*args, &block) self.response_body = render_to_body(options)end
  5. 5. EXAMPLE: DATASET SIZE  Problem: different devices want different amounts of data   Web: full record at first encounter   iOS: only what’s needed  Ideal solution   Serialization solution handles dataset contents Model#as_json, serializer, etc.     API exposes universal options
  6. 6. MAKE IT SOdef render(*args, &block) # ensure we have an options hash options = args.find {|a| a.is_a?(Hash)} args << (options = {}) unless options # set the dataset option options[:dataset] = params[:dataset] || "full" # proceed superend
  7. 7. EXAMPLE: CURRENT USER INFO   Example: current user info   Problem: some info should only be shown to the current user   Billing status, location info   ActiveModel::Serializers provides this automatically   Ideal solution   Serializer/model knows what (if any) sensitive data they contain   Controllers filter that data transparently
  8. 8. ENGAGE def render(*args, &block) # ensure we have an options hash options = args.find {|a| a.is_a?(Hash)} args << (options = {}) unless options # store the current user options[:user] = current_user # proceed super end
  9. 9. SECURITY  Can we use a similar approach?   Prevent unauthorized data access?  Sure! But…
  10. 10. ACTIVATE SHIELDSdef render(*args, &block) # ... if data = options[:json] # remove any items that the user shouldnt see secure_content!(data) end # ... superend
  11. 11. GENERAL DOWNSIDES  Patching render somehow feels wrong   Is it?  Other libraries may handle options hash badly   Occasionally seen options defaulted to nil  Low risk of the render signature changing
  12. 12. SECURITY DOWNSIDES  Huge risk of accidental overhead   Structure carefully to only use data in memory  Not bulletproof   Handling non-Array data types gets tricky   Misses data as_json’d in the controller   Inflexible (though probably for the best)
  13. 13. THANKS! @arsduo I work for @6wunderkinderI’ll talk about this at @baruco2012 too