instructure / pandarus

A Ruby library for the Canvas API (and code generator for other languages, eventually)
34 stars 25 forks source link

Nested hashes raises error #28

Open jiverson002 opened 6 years ago

jiverson002 commented 6 years ago

When a nested Hash is passed like so

content = {
  "wiki_page": {
    "title": "Test",
    "body": "<p>Test</p>"
  }
}

client.update_create_page_courses(course, url, content)

the following trace is produced

8: from test.rb:13:in `<main>'
7: from test.rb:13:in `each'
6: from test.rb:28:in `block in <main>'
5: from .../pandarus-0.7.0/lib/pandarus/client.rb:50:in `method_missing'
4: from .../pandarus-0.7.0/lib/pandarus/v1_api.rb:19172:in `update_create_page_courses'
3: from .../pandarus-0.7.0/lib/pandarus/api_base.rb:62:in `underscored_merge_opts'
2: from .../pandarus-0.7.0/lib/pandarus/api_base.rb:72:in `underscored_flatten_hash'
1: from .../pandarus-0.7.0/lib/pandarus/api_base.rb:82:in `dot_flatten_hash'
.../pandarus-0.7.0/lib/pandarus/api_base.rb:82:in `[]': invalid number of elements (4 for 1..2) (ArgumentError)

It looks like the problem is that dot_flatten_recur produces an Array of the form [["wiki_page.title", "Test", "wiki_page.body", "\

Test\

"]], which is then used to construct a Hash. The correct form would be [["wiki_page.title", "Test"], ["wiki_page.body", "\

Test\

"]]. This is the result of flattening the Array produced by mapping the recursive call to dot_flatten_recur. Thus eliminating the [[k1,v1], [k2,v2],...] structure. I believe the correct logic would be

def dot_flatten_recur(hash)                                                  
  hash.map do |k1, v1|                                                       
    if v1.is_a?(Hash)                                                        
      dot_flatten_recur(v1).map do |k2, v2|                                  
        ["#{k1}.#{k2}", v2]                                                  
      end                                                                    
    else                                                                     
      [[k1, v1]]                                                             
    end                                                                      
  end.flatten(1)                                                             
end 

Here, the final Array is flattened instead of each nested Array, which produces the correct form of an Array to create a Hash from.