How to override the 'as_json' or 'to_json' method in order to 'respond_to' without including specified information?
Asked Answered
O

2

11

I am using Ruby on Rails 3 and I would like to override (possibly in the model file) the as_json or to_json method in order to respond_to an HTTP request without including some information.

In my Account model I have

def as_json(options = {})
  super(
    :except => [
      :password
    ]
  )
end

In my controller I have

format.json {
  render :json => @account, :status => 200
}

When I make a request, for example, to /account/1.json I have back also the password attributes that, for security reasons, I don't want.

So, how can I prevent to include specified information?


I can do this and it works

format.json {
  render :json => @account.to_json(:except => [:password]), :status => 200
}

but it I need to refactor.

Overeager answered 4/3, 2011 at 12:43 Comment(1)
my following solutions are working for me without refactoring. Aren't they working in your environment?Mcchesney
M
16

If it is only in one action you can try:

format.json { render :json => @account, :except => :password }

if you need it for more than one action than the override would be better:

# Exclude password info from json output.
def to_json(options={})
  options[:except] ||= :password
  super
end 

the same is good for as_json

# Exclude password info from json output.
def as_json(options={})
  options[:except] ||= :password
  super
end
Mcchesney answered 4/3, 2011 at 12:56 Comment(7)
In order to work, I MUST use 'render :json => @account.to_json' instead of 'render :json => @account'. I think there is some way to do that without include '.to_json'...Overeager
in rails 3 if you override the as_json method in the model and then put format.json { render :json => @account } in the controller it works without calling to_jsonMcchesney
Does it work if you override "serializable_hash" instead of "as_json"?Wertz
This works. I added the slightly different syntax for excluding multiple attributes.Increasing
Maybe nice to know: It is sufficient to just write super, as it automatically takes the same arguments the parent method has, unless you specify them yourself.Valueless
It would be better to use options[:except] = Array(options[:except]) | [:password] if you wanted to guarantee that the :password could never be sent as json.Dishman
@Ryan McGeary: Actually, the syntax options[:except] ||= :password seems strange to me as well. It would be equivalent to options[:except] if this term is truthy, to :password otherwise. Doesn't it?Krumm
L
1

The best solution is to override as_json methods in your model as following:

def as_json options={}
   super(
     include: {ADD THE RELATIONS YOU WANT TO INCLUDE}).merge({YOU CAN MERGE EXTRA PARAMETER HERE})
end

You could use only (which means that the only parameters that you've listed will be return) or use except (which means return all parameters except the listed ones).

Lifetime answered 22/2, 2017 at 8:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.