title: Dynamic Form in Sinatra
body: <p>In teaching myself Sinatra I wanted to make a web app that monitored devices via ICMP and displayed the results in browser.</p>
  
  <p>I have a config page where the user decides how many devices he wants to monitor and what the IP and description of those devices are. I want the form to be dynamic so I can iterate through the variables easily. I don't want to have to anticipate how many devices the user wants to track. I want something like this.</p>
  
  <pre><code>&lt;form name="config" action="/config" method="post"&gt;
  #of devices to check: &lt;select name="numofdevices"&gt;
  &lt;% case $devices.to_i
    when 1 %&gt;
      &lt;option value=1 SELECTED&gt;1&lt;/option&gt;
      &lt;option value=2&gt;2&lt;/option&gt;
      &lt;option value=3&gt;3&lt;/option&gt;
  &lt;% when 2 %&gt;
      &lt;option value=1&gt;1&lt;/option&gt;
      &lt;option value=2 SELECTED&gt;2&lt;/option&gt;
      &lt;option value=3&gt;3&lt;/option&gt;
  &lt;% when 3 %&gt;
      &lt;option value=1&gt;1&lt;/option&gt;
      &lt;option value=2&gt;2&lt;/option&gt;
      &lt;option value=3 SELECTED&gt;3&lt;/option&gt;
  &lt;% end %&gt;
  &lt;/select&gt; &lt;br /&gt;
  &lt;% $devices.times do |devicenum| %&gt;
       Ip Address: &lt;input type="text" name='&lt;%= devicenum %&gt;[ip]'&gt; Description: &lt;input type="text" name='&lt;%= devicenum %&gt;[desc]'&gt;&lt;br /&gt;
  &lt;% end %&gt;
  </code></pre>
  
  <p>
  </p>
  
  <p>Obviously this won't work though because the hash symbol comes in the form of a string. I would have to access a variable via</p>
  
  <pre><code>deviceOne = params[:"1"]
  </code></pre>
  
  <p>I could not iterate through this</p>
  
  <pre><code>$numofdevices.times do |num|
     devices[num] = params[:num.to_s]
  end
  </code></pre>
  
  <p>Mainly I want to throw all of these devices into an easily accessible array. I don't want to have to prepare for the number of devices the user might track ahead of time. I want the code to count the number of devices they selected and populate an array accordingly.</p>
  
  <p>Ultimately I want to access a device like so. In an array of hashes.</p>
  
  <pre><code>$devices[0][:ip]
  </code></pre>
  
  <p>Then I could iterate through each devices easily.</p>
  
  <pre><code>$devices.each do |device|
     puts "IP: #{device[:ip]}, Desc: #{device[:desc]}"
  end
  </code></pre>
  
  <p>SOmething like this came to mind</p>
  
  <pre><code>$numofdevices.times do |devicenum|
     devices[devicenum] = params[:devicenum]
  end
  </code></pre>
  
  <p>I know for sure I am doing something wrong and that my knowledge of how ruby Hashes/arrays work must be limited. I was hoping there was a better way of doing this rather then the following.</p>
  
  <pre><code>&lt;form name="config" action="/config" method="post"&gt;
  #of devices to check: &lt;select name="numofdevices"&gt;
      &lt;% case $devices.to_i
        when 1 %&gt;
          &lt;option value=1 SELECTED&gt;1&lt;/option&gt;
          &lt;option value=2&gt;2&lt;/option&gt;
          &lt;option value=3&gt;3&lt;/option&gt;
      &lt;% when 2 %&gt;
          &lt;option value=1&gt;1&lt;/option&gt;
          &lt;option value=2 SELECTED&gt;2&lt;/option&gt;
          &lt;option value=3&gt;3&lt;/option&gt;
      &lt;% when 3 %&gt;
          &lt;option value=1&gt;1&lt;/option&gt;
          &lt;option value=2&gt;2&lt;/option&gt;
          &lt;option value=3 SELECTED&gt;3&lt;/option&gt;
      &lt;% end %&gt;
      &lt;/select&gt; &lt;br /&gt;
      &lt;% case $devices.to_i
         when 1 %&gt;
              Ip Address: &lt;input type="text" name='firstd[ip]'&gt; Description: &lt;input type="text" name='firstd[desc]'&gt;&lt;br /&gt;
      &lt;% when 2 %&gt;
              Ip Address: &lt;input type="text" name='firstd[ip]'&gt; Description: &lt;input type="text" name='firstd[desc]'&gt;&lt;br /&gt;
              Ip Address: &lt;input type="text" name='secondd[ip]'&gt; Description: &lt;input type="text" name='secondd[desc]'&gt;&lt;br /&gt;
      &lt;% when 3 %&gt;
              Ip Address: &lt;input type="text" name='firstd[ip]'&gt; Description: &lt;input type="text" name='firstd[desc]'&gt;&lt;br /&gt;
              Ip Address: &lt;input type="text" name='secondd[ip]'&gt; Description: &lt;input type="text" name='secondd[desc]'&gt;&lt;br /&gt;
              Ip Address: &lt;input type="text" name='thirdd[ip]'&gt; Description: &lt;input type="text" name='thirdd[desc]'&gt;&lt;br /&gt;
      &lt;% when 4 %&gt;
              Ip Address: &lt;input type="text" name='firstd[ip]'&gt; Description: &lt;input type="text" name='firstd[desc]'&gt;&lt;br /&gt;
              Ip Address: &lt;input type="text" name='secondd[ip]'&gt; Description: &lt;input type="text" name='secondd[desc]'&gt;&lt;br /&gt;
              Ip Address: &lt;input type="text" name='thirdd[ip]'&gt; Description: &lt;input type="text" name='thirdd[desc]'&gt;&lt;br /&gt;
              Ip Address: &lt;input type="text" name='fourthd[ip]'&gt; Description: &lt;input type="text" name='fourthd[desc]'&gt;&lt;br /&gt;
      &lt;% end %&gt;
  </code></pre>
  
  <p>I would then have to pre-create device variables ready to accept data should the user decide to use that many devices. MY route looks like this.</p>
  
  <pre><code>post '/config' do
    @title = "Config"
    $devices = params[:numofdevices].to_i
    $firstdevice   = params[:firstd]
    $seconddevice  = params[:secondd]
    $thirddevice   = params[:thirdd]
    $fourthdevice  = params[:fourthd]
    erb :config
  end
  </code></pre>
  
  <p>I am certain I am doing this wrong. If I want to track a large number of devices this becomes repetitive and cumbersome. I'm a learning newb. Can anyone out there point me in the right direction? :)</p>
  
  <p>[EDIT]</p>
  
  <p>I'm going to try the following in my post '/config'</p>
  
  <pre><code>params.keys.each do |key|
    @objects.push(params[key])
  end
  </code></pre>
  
  <p>[EDIT EDIT]</p>
  
  <p>Here is the best I have been able to come up with.</p>
  
  <p>In my config erb</p>
  
  <pre><code>&lt;% $numofdevices.times do |id| %&gt;
          Ip Address: &lt;input type="text" name='&lt;%= id %&gt;[ip]'&gt; Description: &lt;input type="text" name='&lt;%= id %&gt;[desc]'&gt;&lt;br /&gt;
      &lt;% end %&gt;
  </code></pre>
  
  <p>In my post 'config'</p>
  
  <pre><code>params.keys.each do |key|
      $devices.push(params[key]) if params[key].include?("ip")
    end
  </code></pre>
  
  <p>Now I don't have to worry what the symbols get named or how they are named. :p</p>
  
  <p>Still if anyone has any other ways of doing this that would be even better I'd appreciate the input! :)</p>