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))   end

...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))   end end

...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]}" end end

=> nil

{:foo =>}.to_json(:f => 'biff')

f was biff => "{\"f1\":}"