martes, 27 de septiembre de 2011

Ruby, Camping and...Gateway?


It's been a long time since my last Ruby blog...so I wanted to something nice...instead of emulate any SAP transaction, it was time for me to engage with new SAP technologies, and Gateway really looks promising...so...what's Gateway?
Gateway is based on OData, which allows us to perform CRUD operations on WebService like applications...in other words...it's just awesome technology -;) If you want to find out more, please refer to this homepage on SCN "SAP NetWeaver Gateway Demo System".
So...we can access Gateway using many technologies, for example JavaScript or Java for Blackberry. But for sure, I wanted to go beyond those awesome examples, and searched for other ways to consume Gateway data...on the OData SDK List I found a Ruby gem called Ruby_OData, which works awesome for services like Netflix OData, but didn't work to well for SAP Gateway services...
As you may know...here on SCN, we're like family, so we like to work together on some nice project, so as you can see here...that's what we did -;)

SAP NETWEAVER GATEWAY DEMO SYSTEM


With the gem working, I knew I wanted to blog about it...build a small Ruby application to show how easy is to use the Ruby_OData gem...but of course...having a DOS style black window wasn't very likely...so I decide to use Camping once again -:) and of course...Camping is not very classy...and I think it's not even maintained anymore...so if you're looking for something nicer, you can use Sinatra instead -;)
As I love to say..."Enough talk! Let's go to the source code!"
Camping_Gateway.rb
gem 'ruby_odata'
require 'ruby_odata'

Camping.goes :Camping_Gateway

module Camping_Gateway::Controllers

  class Index < R '/'
    def get
      render :_login
    end
  end
  
  class Login
    def post
      @client = input.client
      @user = input.user
      @password = input.password
      render :_showtable
    end  
  end
  
   class ShowTable 
    def post     
      render :_showtable
    end
  end 
end 

module Camping_Gateway::Views
  def layout
    html do
      head do
        title {"Camping and Gateway - Flight Example"}
      end
      body { _login }
    end
  end

  def _login
    form:action => R(Login), :method => 'post' do
      h1 {"Camping and Gateway - Flight Example"}

      label 'Client ', :for => 'client';
      input :name => 'client', :type => 'text'; br
      label 'User ', :for => 'user';
      input :name => 'user', :type => 'text'; br
      label 'Password ', :for => 'password';
      input :name => 'password', :type => 'password'; br      
      
      input :type => 'submit', :name => 'login', :value => 'Login'
    end
  end

  def _showtable
    svc = OData::Service.new "http://gw.esworkplace.sap.com/sap/opu/sdata/sap/DEMO_FLIGHT",
                             {:username => @user, :password=> @password, 
                              :additional_params=> {'sap-client'=>@client.to_i}}
    svc.z_demo_flightCollection
    flight = svc.execute

    $Data_Names = Array.new
    $Data_Fields = Array.new
    $Data_Split = Array.new
    
    $Data_Names.push("Airline")       #airline
    $Data_Names.push("City From")     #cityfrom
    $Data_Names.push("Airport From")  #airportfr
    $Data_Names.push("Currency")      #curr_iso
    $Data_Names.push("City To")       #cityto
    $Data_Names.push("Airport To")    #airportto    

    for flights in flight do
      puts flights.airline
      $Data_Fields.push(flights.airline + "|" + flights.cityfrom + "|" + 
                        flights.airportfr + "|" + flights.curr_iso + "|" + 
                        flights.cityto + "|" + flights.airportto)
    end    

    $Fields_Len = $Data_Names.length
    $Data_Len = $Data_Fields.length

    table.sample! :cellspacing => 0, :cellpadding => 2 do
      thead do
        tr do
          for i in 0...$Fields_Len
            th "#{$Data_Names[i]}"
          end          
        end
      end
      for i in 0...$Data_Len
        tbody do
          tr do
            $Data_Split = $Data_Fields[i].split("|")
            for i in 0...$Fields_Len
              td "#{$Data_Split[i].to_s.strip}"
            end
          end
        end
      end
    end
  end 
end
To run this example, we need to provide only 3 simple parameters:
Client = 800
Username = GW@ESW
Password = ESW4GW






I know what you're going to tell me after you read the source code...why I'm taking the work of reading the date, putting them on an array and looping that? I know I just could read the field from the model and all that...but...for some reason that I still need to discover...the filtering doesn't work as I expected...for example...I should be able to pass a filter to only select the CITYTO = ' NEW YORK', but it doesn't work even when I don't have any errors...so my approach here (and that's for another blog), it to have all the information stored internally to be able to do the filtering after calling the Gateway service...so...if you're an SAP Gateway expert...please let me how to make the filter work -:( Because, I know that if I pass the VALUE, SCHME_ID and SCHEME_AGENCY_ID it's going to work, but only for 1 record...I want a better filter -;)
Hope you enjoy this one...and see you soon with more Gateway coolness!

Greetings,

Blag.