A PHP Dev Writing My First Rails App – Many Questions

I am a PHP dev that has been learning Ruby and Rails, and am starting to write my first Rails application.

For my first rails app, I am wanting to write a page that basically scans IP addresses and returns a list of ones that responded. I want each "scan" to be saved as a job that can be referenced later on, and the job itself tell me if the scan completed or if it is still in progress.

To keep things simple, the first page would have a form with fields for a start IP and an end IP. The IPs I am scanning are Proliant iLOs, so I will be using the ipmiutil command in linux to carry this out. The syntax I'm shooting for would be something similar to (the grep is to just show only the IPv4 addresses that return a response):

ipmiutil discover -b -e | grep -Eo '(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])'

I don't know of any ipmiutils ruby wrappers out there, so am unsure how to get ruby to execute the ipmiutils command.

The 2nd page would be the "results" page which should show me what has returned, and if possible, if anything is still pending, for the current scan I just executed.

The 3rd page would be a list of jobs that were executed.

So in Rails, I've read guides on generating controllers, views, etc. Would I be correct in saying that I need to first generate a scaffold for my "jobs"? Or do I first begin by simply generating a controller? This is sort of where I'm stuck.

My other question is, in PHP, it's very clear to me how to pass POST values in a form from one page to another, and how to store those in a SESSION if necessary. I'm not 100% certain how this is handled in Rails (though it looks like it would be handled with the controller via routes, correct?). Is the best approach for this application to store POST values in a SESSION in cache?

Thanks for any info - I know this is sort of a non-specific, generalized question (or rather group of questions), but honestly I have no one around me who is a Rails expert, so have no one to ask these types of questions to. I've been reading a lot of material and am currently in the middle of the Agile Web Dev with Rails 5 book, but I need to start applying the things I've read to retain the knowledge, and I keep having questions like these.

In any case, I appreciate any info.

2 thoughts on “A PHP Dev Writing My First Rails App – Many Questions”

  1. Good questions. I’m not familiar with ipmiutil wrappers either, so I can’t help you there, but the other questions I believe I can.

    Let’s start first with the page displaying your jobs. It sounds like what you really wants to run is:

    rails generate resource job_list KEY:DATATYPE KEY2:DATATYPE

    I’m a big fan of generating resources for things like a simple index page as generating scaffolds assumes you’ll need a full CRUD API for each resource, while generating resource lets you write them in yourself, i.e., your JobsController will look like this after generation:

    class JobListsController < ApplicationController end This also means that the rails generator will not create any views for you, so you just add in the specific ones you need. Every other part of the generation (model, migration, tests) will be the same. Depending on how many addresses you're checking at a time, session may be the best storage option, but it may also be to drop them into a database. As far as POST, controllers, and routes are concerned, let's use your IP scanner as an example, starting with the controller: class IpController < ApplicationController def scanner end def completed_scans end def scan end end ``` Now, in your routes, add: get '/scanner', to: 'ip_scanner#scanner', as: 'scanner' get '/completed_scans', to: 'ip_scanner#completed_scans', as: 'completed_scans' post '/scan', to: 'ip_scanner#scan', as: 'scan' root 'ip_scanner#scanner' # this could also be written as: resources :ip_scanner do collection do get :scanner get :completed_scans post :scan end end Now, in `app/views` add the folder `ip_scanner` and add into it two files - `scanner.html.erb` and `completed_scans.html.erb`. You now have helper tags for these pages you can use: <%= link_to completed_scans_path %>
    <%= link_to scanner_path %>
    # or
    <%= link_to root_path %>

    Let’s add a form to that page that will post to the scan url (it will default to post, but I’ll be explicit so you can see it):

    <%= form_tag scan_path, method: :post do %>
    <%= text_field_tag :start_ip %>
    <%= text_field_tag :end_ip %>
    <%= submit_tag %>
    <% end %>

    When Rails renders the form, it’ll add some other parameters, but the two you care about are `params[:start_ip]` and `params[:end_ip]`. Let’s head back to the controller and add this:

    def scan
    session[:start_ip] = params[:start_ip]
    session[:end_ip] = params[:end_ip]

    Obviously that’ll leave you very open to malicious injection, but do some googling on rails strong parameters and you can see how to clean that up. You now have those two data points saved into your session. So now let’s display them. Update the scan method to read:

    def scan
    session[:start_ip] = params[:start_ip]
    session[:end_ip] = params[:end_ip]
    # do scanning job with those values here #
    render :completed_scans

    # note, this means that until the scan job is completed, unless you use a worker to run
    # it in the background, the page will not render

    Then, make this change:

    def completed_scans
    @start_ip = session[:start_ip]
    @end_ip = session[:end_ip]

    Now, in `completed_scans.html.erb` you can add:

    Started with IP Address: <%= @start_ip %>

    Ended with IP Address: <%= @end_ip %>

    And that’s how you’d save the data to session and have it persist through. Hopefully that all makes sense!

    Edit: I’m freehanding all of this right now so there may be a slight error somewhere, I’ll validate all of it in a bit.

  2. So I have made some progress with my controller and am starting to understand how POST works in relation to views. This is what I have for my controller thus far:

    require ‘rubyipmi’

    class IloscansController < ApplicationController def scanner end #page that receives post data def scan @start_ip = params[:start_ip] @end_ip = params[:end_ip] @ilo_username = params[:username] @ilo_password = params[:password] #First scan for available iLOs and return available ones (use split to turn each line into element of array) @ipmi_scan = `ipmiutil discover -b #{@start_ip} -e #{@end_ip} | grep -Eo '(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])'`.split #Take each returned IP and grab the model and serial @ipmi_scan.each do |address| @result = Rubyipmi.connect(@ilo_username, @ilo_password, address).fru.list @model = @result["builtin_fru_device"]["product_name"] @serial = @result["builtin_fru_device"]["product_serial"] puts "iLO IP #{address}, Server Model: #{@model}, Server Serial #{@serial}" end end end My question is...how do I save `puts "iLO IP #{address}, Server Model: #{@model}, Server Serial #{@serial}"` into a variable that I can use in my view? I doubt the solution is putting the for loop into the view. Thanks for any advice.


Leave a Comment