Note that there are some explanatory texts on larger screens.

plurals
  1. PODynamically creating a multi-dimensional hash in Ruby
    text
    copied!<p>I'm a PHP developer who's trying to gain some proficiency in Ruby. One of the projects I'm cutting my teeth on now is a source-code auditing tool that scans webapp files for potentially dangerous functions in several web programming languages. When matches are found, the script saves the relevant information in a <code>poi</code> (point-of-interest) class for display later on.</p> <p>An example instance of that class would look something like this (modeled in YAML):</p> <pre><code>poi: file_type: "php" file: "the-scanned-file.php" line_number: 100 match: "eval()" snippet: "echo eval()" </code></pre> <p>On display, I want to organize these points of interest like so:</p> <pre><code>- file_type -- file --- match (the searched payload) </code></pre> <p>Thus, before presentation, I'm trying to structure a flat array of <code>poi</code> objects into a hash mirroring the structure above. This will allow me to simply iterate over the items in the hash to produce the desired on-screen organization. (Or at least, that's the plan.)</p> <p>And now, for my question: how do I do that in Ruby?</p> <p>In PHP, I could do something like this really easily:</p> <pre class="lang-php prettyprint-override"><code>&lt;?php $sorted_pois = array(); foreach($points_of_interest as $point){ $sorted_pois[$point-&gt;file_type][$point-&gt;file][$point-&gt;match][] = $point; } ?&gt; </code></pre> <p>I've tried translating that thought from PHP to Ruby like this, but to no avail:</p> <pre><code>sorted_pois = {} @points_of_interest.each_with_index do |point, index| sorted_pois[point.file_type.to_sym][point.file.to_sym][point.match.to_sym].push point end </code></pre> <p>I've spent a few hours on this, and I'm kind of banging my head against the wall at this point, so presumably I'm way off-base. What's the proper way to handle this in Ruby?</p> <p><strong>Update:</strong></p> <p>For reference, this is the precise method I have defined:</p> <pre><code># sort the points of interest into a structured hash def sort sorted_pois = {} @points_of_interest.each_with_index do |point, index| sorted_pois[point.file_type.to_sym][point.file.to_sym][point.match.to_sym].push point end end </code></pre> <p>This is the error I receive when I run the code:</p> <pre><code>./lib/models/vulnscanner.rb:63:in `sort': undefined method `[]' for nil:NilClass (NoMethodError) from /usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `each_with_index' from ./lib/models/vulnscanner.rb:62:in `each' from ./lib/models/vulnscanner.rb:62:in `each_with_index' from ./lib/models/vulnscanner.rb:62:in `sort' from ./webapp-vulnscan:69 </code></pre> <p>Line 62 (as you can likely infer) is this line in particular:</p> <pre><code>@points_of_interest.each_with_index do |point, index| </code></pre> <p>As an additional reference, here's what (a snippet of) <code>@points_of_interest</code> looks like when converted to YAML:</p> <pre><code>- !ruby/object:PoI file: models/couponkimoffer.php file_type: php group: :dangerous_functions line_number: "472" match: ` snippet: ORDER BY `created_at` DESC - !ruby/object:PoI file: models/couponkimoffer.php file_type: php group: :dangerous_functions line_number: "818" match: ` snippet: WHERE `company_slug` = '$company_slug' - !ruby/object:PoI file: models/couponkimoffer.php file_type: php group: :dangerous_functions line_number: "819" match: ` snippet: ORDER BY `created_at` DESC </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload