I upgraded to rails 3.0.9 and there is a new yaml gem. Unfortunately the way to_yaml is outputting a rather large hash has changed somehow. Now, I am getting a lot of "!map:ActiveSupport::HashWithIndifferentAccess" after elements that I wasn't getting before which as far a开发者_运维知识库s I am concerned is a bug because I am trying to make my .yml as human readable as possible. Is there a way to get rid of "!map:ActiveSupport::HashWithIndifferentAccess" from the yaml output? It doesn't affect the way it is loaded into my code so I don't see the point having it in the output. I could just gsub it out but I think there is something else happening here that I am unaware of.
Typical hash input:
{"All" =>
{"A test" => {"string"=>"This is just a test",
"description" => "This is a description for a test string",
"alternatives" => [{"new" => "woot"}]}}
Yaml output:
All:
A test: !map:ActiveSupport::HashWithIndifferentAccess
string: This is just a test
description: This is a description for a test string
alternatives:
- !map:ActiveSupport::HashWithIndifferentAccess
new: woot
What I want (and what I was getting before):
All:
A test:
string: This is just a test
description: This is a description for a test string
alternatives:
- new: woot
Note: My output must be in UTF-8.
I suspect your hash comes from params
in controller, which has the type ActiveSupport::HashWithIndifferentAccess
. One way to fix the output is by monkey patching its to_yaml
method to convert itself to normal hash before converting it to YAML.
# config/initializers/hash_with_indifferent_access.rb
class HashWithIndifferentAccess < Hash
def to_yaml(opts = {})
self.to_hash.to_yaml(opts)
end
end
I am in the same issue, I have been thinking in the @htanata solution, also is possible to implement this monkey patch:
class HashWithIndifferentAccess < Hash
def to_yaml_typea
""
end
end
But it is also very danger.
I have been thinking in implement my own YAML::Emitter but it looked like technology overkill.
This also worked:
JSON.parse(my_hash_with_indifferent_access.to_json).to_yaml
But didn't look too much efficient :)
Also crossed my mind:
my_hash_with_indifferent_access.to_yaml.gsub( " !map:ActiveSupport::HashWithIndifferentAccess", "" )
Still thinking is a possibility but all of us agree that this smells bad.
My final solution has been:
# config/intializers/hash_with_indifferent_access_extension.rb
# use it like `params.to_hash_recursive.to_yaml`
class HashWithIndifferentAccess < Hash
def to_hash_recursive
result = self.to_hash
result.each do |key, value|
if(value.is_a? HashWithIndifferentAccess)
result[key] = value.to_hash_recursive
end
end
result
end
end
It is also a monkey patch but at least it is monkey patching a non-existing method so the possibilities to interfere with third party code behavior is very weird.
PD: any suggestion for cleaning up this code please refer to the gist
精彩评论