HAML rendering as_json with hash rocket instead of colon - ruby-on-rails

I'm trying to render a ruby hash to a json string in haml. (the ! tells haml not to escape the output)
! { :name => "Paul" }.as_json
I expect this output
{ "name":"Paul" }
but I get a hash rocket instead of a colon
{ "name"=>"Paul" }
How do I make haml or as_json output a colon instead of a hash rocket for the property/value separator?

as_json is essentially a method that allows you to specify how an object is represented in JSON. It doesn't actually go as far as returning a JSON encoded string. to_json is needed for that.
The reason for this is that you might want to decide which fields your model returns when JSON encoded (say, removing the password from the User model), but by using to_json, you no longer have the ability to nest that within another JSON object, as it's become an encoded and escaped string.
to_json will call as_json, and will encode the return value.
Referenced from:
http://jonathanjulian.com/2010/04/rails-to_json-or-as_json/

Related

Parse Hash in Ruby

How can I parse a hash in ROR?
I have a hash in string format(enclosed by double quotes) and i need to parse them to a valid hash.
eg.
input_hash = "{"name" => "john"}"
desired
output_hash = {"name" => "john"}
This is the wrong approach. String representation of a ruby hash is not a good way to serialise data. It is well structured, and definitely possible to get it back to a ruby hash (eval), but it's extremely dangerous and can give an attacker who has control over the input string full control over your system.
Approach the problem from a different angle. Look for where the string gets stored and change the code there instead. Store it for example as JSON. Then it can easily and safely be parsed back to a hash and can also be sent to systems running on something that is not ruby.

Rails 4: render string field as JSON / hash

I have a Rails model in which one of the text fields contains a JSON string. While rendering it in views with JSON format (such as through index or show) I want to convert the string to a JSON hash. How can I do this with jbuilder or otherwise?
In general, how to apply a transform on a field by calling some function, before rendering it via jbuilder.
Of course, the naive solution is to build the JSON manually and use render json: my_json_here but I am looking for a better way.
Well a JSON is a string already... Maybe you want to convert it back to an object...
This will transform you string into a hash or array object.
JSON.parse(string)
If you want to make the other way around, transform you hash or array into a JSON string:
{ foo: 'bar' }.to_json # "{\"foo\":\"bar\"}"
EDIT: As you are looking for something more advanced, I recommend using the gem ActiveModelSerializer, where you create serializer objects that can be used to render ActiveModel data into any format, like JSON.
I think you could use "serialization" to do this where all of the conversion from JSON object to string and back is handled by ruby.
apidock

jRuby hash iteration newbie here

I am very new to rails in general and what I have is a hash being passed as json for one format and now I need to pass it to the view to work with but I have no idea how to iterate over the hash to make it work in the view as I need to do some type of each loop over it. Its a 2 dimensional hash dunno if that means anything or not.
edit
example
{"status":"successful","service_list":[{"service_name":"mySQL","status":"RUNNING","status_message":"No errors reported","host":"1"},{"service_name":"PHP","status":"RUNNING","status_message":"No errors reported","host":"1"},{"service_name":"APache","status":"RUNNING","status_message":"No errors reported","host":"1"},{"service_name":"Jetty","status":"RUNNING","status_message":"No errors reported","host":"1"}]}
This renders fine when I do it as JSON, but using the same thing to render it out in an HTML based view is where I am getting stuck
You have converted a Ruby has to a JSON hash, which is a Javascript format. In Ruby you would access a hash as follows:
hash = {"foo": "bar"}
puts hash["foo"] # This returns "bar"
JSON is similar to Ruby, and can be accessed in the same manner:
var hash = {"foo": "bar"};
alert(hash["foo"]); # This alerts "bar"
If you want to iterate through this collection in Javascript, you can use a for loop:
var data = {"status":"successful","service_list":[{"service_name":"mySQL","status":"RUNNING","status_message":"No errors reported","host":"1"},{"service_name":"PHP","status":"RUNNING","status_message":"No errors reported","host":"1"},{"service_name":"APache","status":"RUNNING","status_message":"No errors reported","host":"1"},{"service_name":"Jetty","status":"RUNNING","status_message":"No errors reported","host":"1"}]};
for(x=0;x<data["service_list"].length;x++) {
alert(data["service_list"][x]["service_name"]); # This returns "mySQL", ...
};
If you are wanting to convert this JSON object to a Ruby has you can call "JSON.parse" with your JSON string as an argument.

Symbols used as Hash keys get converted to Strings when serialized

When I assign an Array or Hash to an attribute of a Mongo document, it gets properly
serialized except for Symbols when they are used as Hash keys. Simple example:
irb>MyMongoModel.create :some_attr => {:a => [:b,:c]}
=> #<MyMongoModel _id: 4d861c34c865a1f06a000001, some_attr: {:a=>[:b, :c]}>
irb>MyMongoModel.last
=> #<MyMongoModel _id: 4d861c34c865a1f06a000001, some_attr: {"a"=>[:b, :c]}>
Please, note that some_attr is retrieved as {"a"=>[:b, :c]}, not as
{:a=>[:b, :c]}
This also happens for nested Hashes (e.g., inside of Arrays or other Hashes). Is there a way to preserve Symbols in such cases?
Solution
I'm using YAML to manually serialize some_attr - YAML.dump (or Object#to_yaml) before storing, and YAML::load after reading the attribute. YAML preserves the serialized object better. ActiveRecord is using YAML to implement its serialize class method on ActiveRecord::Base.
More than likely this has to do with the ORM you are using to provide the persistance layer for the model. You can probably wrap some_attr with a method that returns it in the form of a HashWithIndifferentAccess which you can then access with either strings or arrays. Since you are using Rails, this functionality can be activated by calling the with_indifferent_access method on the Hash object. (If you have an array of Hash objects, you'll need to call it on each one of course) The method will return the same hash, but then symbol lookups will work.
From your code:
new_hash = MyMongoModel.last.some_attr.with_indifferent_access
new_hash[:a] # Will return the same as new_hash['a']
Hope this helps!
the culprit here is the BSON serialization. when you serialize a symbol used as a key for hashes, it is actually translated to a string and when you ask it back you get the string instead of the symbol.
i'm having the same problem as you and i'm thinking of extending the Hash class to include a method to convert all the "string" keys to :symbols.
unfortunately i'm not on Rails so i cannot use the with_indifferent_access as suggested by ctcherry.
I'm not sure about preserving symbols but you can convert the strings back to symbols.
str.to_sym
Found this, works well and you have define the field as Hash:
https://github.com/mindscratch/mongoid-indifferent-access

Is it okay to use strings everywhere and never use symbols in Ruby on Rails?

There are some annoyances with using symbols in hashes. For example, the JSON gem that we use always returns strings from any JSON string that's parsed, so wherever we reference a hash generated from decoding JSON, we have to use a combination of strings and symbols to access hashes.
Style-wise, is it ok to keep things consistent throughout by using strings only?
Strings are mutable, hence each time you reference "foo" ruby creates a new object. You can test that by calling "foo".object_id in irb. Symbols, on the other hand, are not, so each time you reference :foo ruby returns the same object.
Regarding the "style" and "consistency" you can always use hash.symbolize_keys! for your received json data, this will turn all string keys into symbols. And vice-versa - hash.stringify_keys! to make them strings again.
There is no rule that says a hash key should be a symbol.
The symbol-as-key is seen a lot in Rails as a convention ... Rails makes a lot of use of passing hashes to allow multiple parameters, and the keys in such hashes are often symbols to indicate that they are expected/permissible parameters to a method call.
For the indecisive among us:
http://as.rubyonrails.org/classes/HashWithIndifferentAccess.html

Resources