28

I am using the to_json method on an object, and trying to get the :methods argument to work. I have a method on my model (Drop) called is_favorited_by_user?. This method takes an argument of the current_user, and then checks to see if the drop is favorited by the user. How can I pass this argument through the to_json method.

render :json => @drops.to_json(:methods => :is_favorited_by_user?(current_user))
JJD
  • 50,076
  • 60
  • 203
  • 339
James Finley
  • 485
  • 1
  • 5
  • 15

2 Answers2

49

You can add current_user attribute to your model and set it before executing to_json

  attr_accessor :current_user

  def is_favorited_by_user?(user=nil)
    user ||= current_user
    # rest of your code
  end


@drops.current_user = current_user
render :json => @drops.to_json(:methods => :is_favorited_by_user?)
JJD
  • 50,076
  • 60
  • 203
  • 339
Tatjana N.
  • 6,215
  • 32
  • 29
  • 4
    How do I extend this solution when I'm doing render :json => Drop.all in the index action. Where do I assign the current_user? – Vijay Dev Jun 01 '11 at 16:34
  • 3
    `cattr_accessor :current_user` in model and then `Model.current_user = current_user` in controller. – Sergey Kishenin Jun 01 '13 at 19:39
  • 4
    Assigning your model to a class attribute won't work if your environment is multi-threaded. You could be in the process of converting something to JSON and then the current_user all of a sudden changes and now half your JSON is for one user and half is for another. – Reid Main Aug 26 '15 at 03:34
4

The methods to_json takes aren't intended to be ones that take arguments, but just "getter" methods. (Typically the ones created based on your db attributes.)

See examples here, none pass arguments:

http://apidock.com/rails/ActiveRecord/Serialization/to_json

If you want to do something custom, you'll need to create a method that builds up the hash of info you want, then convert that hash to json.

  • 1
    Is there a way that I can get the current_user variable within my Model, so I don't need to pass the argument? – James Finley Apr 30 '10 at 15:35
  • 1
    @JamesFinley Models are not (and should not be) aware of the state of controllers or http request. current_user is part of the request and should not be exposed to models in a global way due to the multithreaded issue stated above. It should be passed only as a method parameter. – hammady Oct 19 '16 at 07:39