Rails as_json weirdness
#
While fixing a broken test, I came across this weirdness with as_json:
- It returns a
Hash
, not aHashWithIndifferentAccess
- Attributes are keyed by their name as a string
- If method names are provided as symbols,
as_json
uses a symbol in the Hash - If method names are provided as a string,
as_json
uses a string in the Hash
Huh?
Here’s an example with a class called Post with attributes for id, title, and body. It also has an instance method:
class Post < ActiveRecord::Base def hello_world "hello world" end end
The output from as_json is a Hash and all the keys are strings:
>> post.as_json => {"body"=>"test body", "id"=>30, "title"=>"Hi"} >> post.as_json.class => Hash
When referring to a method in Ruby, you usually use a symbol, but this will use that symbol as the key:
>> post.as_json(:methods => [:hello_world]) => {"body"=>"test body", "id"=>30, "title"=>"Hi", :hello_world=>"hello world"}
However, you can also use a string as the method name, and it will use a string instead:
>> post.as_json(:methods => ['hello_world']) => {"body"=>"test body", "id"=>30, "title"=>"Hi", "hello_world"=>"hello world"}
Strange! It doesn’t usually matter because this output gets passed to to_json and the symbols are converted to strings, but it was inconvenient in my test case, because I was using strings as keys. Once I figured it out I was able to work around it.
This was tested in Rails 3.2.5.