Passing :methods to to_json...sometimes

In my application I have a class, Group, which has_many
GroupMemberships, and has_many GroupMembers
through :group_memberships. My UI is almost purely JS, so my actions
render everything in JSON, which I accomplish through a generic
“build_response” method that takes the data to be rendered, adds some
elements to a hash, and eventually to_json is called on the whole
thing (by virtue of the fact that I’m calling render :json).

For most of my “views” showing a collection of Groups, I’m not
interested in the associated GroupMembers. But there’s one action in
one controller where I need to display them (/groups/show). I can
easily show GroupMembers in to_json thusly:

def to_json(options = {})
super({:methods => [:group_members]}.merge(options))

…but this causes a somewhat expensive database query that isn’t
needed in most cases. The trick is figuring out how to cause to_json
to include the :group_members association only in the case I need it
to. If models could see controller instance variables, it’d be a no-
brainer - but they can’t. It would also be easy if I were calling
to_json directly and could then pass something in the options param,
but I never do. to_json is always called on my behalf because my
collection of Groups is a member of a larger hash which is being
rendered as json by a controller action.

I’m stuck. Anyone have any ideas (preferably ones that don’t require
me to re-architect my model of using a generic method to construct my
data for JSON rendering)?


My solution:

class Group < ActiveRecord::Base

def to_json(options = {})
methods = [:somethings] # Always include somethings
methods << :group_members if options[:include_group_members]
super({:methods => methods}.merge(options))

…and in the one action in the single controller where I want to show
GroupMembers, I call to_json directly on the larger hash that contains
my array of Groups (among other things): render :json =>
that_hash.to_json(:include_group_members => true)

It turns out that when to_json recurses into nested elements, it
passes the options hash down the chain, so in my case it trickles down
to my Group#to_json method.

class Foo
def to_json(options = {})
puts “f was #{options[:f]}”
=> nil

{:foo =>}.to_json(:f => ‘biff’)
f was biff
=> “{“f1”:}”