Skip to content
This repository

Easy filtering or specifying of additional fields #274

Closed
travisp opened this Issue · 4 comments

2 participants

Travis Pew David Sommers
Travis Pew

Sometimes when designing an API, it's good to give clients the ability to specify a more limited set of fields to return (e.g. Google, LinkedIn, Facebook) , or allow specifying additional fields (e.g. Bugzilla):

http://blog.apigee.com/detail/restful_api_design_can_your_api_give_developers_just_the_information/

It would be great if something like this could be built into rabl so that rabl could just skip attributes that were not specified somewhere instead of something like:

object @user
if @fields.nil? || @fields["lists"]
  child :lists do
     ....
  end
end

Any thoughts on this, or is there a good way to do this now?

David Sommers
Collaborator

Check out some of the examples on the wiki under Referencing objects in extended views

That should get you one step closer.

An approach that I like is to use a node and place some logic in there to optionally call partial. Which happens to be the last example on the page above.

Travis Pew

@databyte, conditionally calling a partial could help some, but it would be nice to make returning any attribute optional when the optional "fields" parameter is passed. As is, attempting to implement this design makes the views very messy since each attribute would require its own conditional check.

David Sommers
Collaborator

Attributes that don't exist are optional. In other words, if you had two objects like Kitten and Tiger which both have name and cuteness_level but only Bar has the attribute will_kill_you.

object @cat

attributes :name, :cuteness_level, :will_kill_you

Then if you pass it either object, RABL will output it for you ignoring :will_kill_you for the objects that don't have it.

The way I would do optional conditional checks on when to display or not to display attributes wouldn't be in the view (which is RABL) but in an object itself.

Create a new composite object, use the Presenter pattern, or the Decorator pattern. See Draper for decorator and display_case for an "Exhibit" pattern (where decorators and presentation patterns were get'n it on).

A simple presentation object could be:

class UserWithList
  def initialize(user)
    @user = user
  end

  def fields
    [:name, :created_at, :lists]
  end

  def method_missing(method, *args)
    args.empty? ? @user.send(method) : @user.send(method, args)
  end
end

Then your template would be something like:

object UserWithList.new(@user)
attributes *fields

Of course I typed that all out and there's most likely a typo somewhere. You can also use a cleaner DRY-er DSL with SimpleDelegator or Draper.

David Sommers
Collaborator

If you have any other questions, just reopen.

David Sommers databyte closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.