开发者

Yaml output filled with !map:ActiveSupport::HashWithIndifferentAccess

开发者 https://www.devze.com 2023-03-17 02:03 出处:网络
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::HashWithInd

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

0

精彩评论

暂无评论...
验证码 换一张
取 消