March 1, 2007
sap4rails updated to support new sapnwrfc
sap4rails has been upgraded to support the new RFC Connector for Ruby - sapnwrfc.Posted by PiersHarding at 9:39 AM
November 2, 2006
Repensando a web com Rails
Fabio Akita has just contacted me to say that his new book "Repensando a web com Rails" has been released for the Brazilian market. The book is primarily about Ruby on Rails, but contains a section on SAP integration with Rails, which I helped (a little) withCongratualtions Fabio - Hope it sells well.
Posted by PiersHarding at 1:27 PM
October 31, 2006
Ruby and the SOAP RunTime (SRT) Handler
Following on from my previous post about Ruby, Ruby on Rails, and SAP Web Services Integration - I would like to show how to switch to using the SOAP RunTime (SRT) Handler, which makes available SAP Web Services via Virtual Interfaces.
Steps
- Follow the steps outlined in Ruby, Ruby on Rails, and SAP Web Services Integration upgrading sapwas to at least version 0.06, and sap4rails to at least version 0.05, making sure that the soap/rfc handler works correctly.
- Create the Virtual Interface, Web Service Definition, and Web Service Config to expose the UserAdmin Function Modules
- Modify app/models/sap_user.rb to point to the new Web Service definition
Create the SAP Web Service
We need to create a web service that exposes the function modules that were used in the UserAdmin Rails application. To do this - go to transaction SE80, go to the Enterprise Services tab, and create a Virtual Interface of type Funciton Group called Z_USERADMIN. Include into this the function modules:
- Z_BAPI_USER_GETLIST
- BAPI_USER_GET_DETAIL
- BAPI_USER_LOCK
- BAPI_USER_UNLOCK
Activate this, and then create a Web Services definiton - again, using SE80, go to the Enterprise Services tab, and create a Web Services definition called Z_USERADMIN - referencing the previously activated Vitual Interface Z_USERADMIN.
Finally - activate this in the ICF configuration (SICF), by using transaction WSCONFIG, referencing the Web Service definition Z_USERADMIN created above.
There is an excellent discussion of the details of this process by Thomas Jung, here, and here.
Modify model sap_user.rb
Now for the final part - in the UserAdmin Rails application, edit the SapUser model file app/models/sap_user.rb. This needs to switch from referencing the method "function_module" for loading the functions, to using "resources", as outlined below:require_gem "sap4rails" class SapUser < SAP4Rails::WS::Base # You must define a list of RESOURCES to preload resources "http://seahorse.local.net:8000/sap/bc/srt/rfc/sap/Z_USERADMIN" ...Now you can test it as in the previous weblogs.
Unicode!
One thing that I neglected to say in my previous post, is a major advantage of using sapwas for accessing SAP is that it has comprehensive Unicode support - free of charge (but not of pain) :-) .
Round Up
For me - this rounds up SAP Web Services and Ruby - you can either access them in Ruby directly by using the library sapwas, or taking advantage of the Rails integration provided by sap4rails.Posted by PiersHarding at 11:12 AM
October 23, 2006
sap4rails 0.07 - SAP RFC and auto-reconnect
I released sap4rails 0.07 this week, which corrects a problem with RFC connections not reconnecting correctly (this is using saprfc as the driver - there is no similar issue wtih the sapwas driver, which uses stateless HTTP). This is especially important when the R/3 (ABAP) application server your Rails application is connected to goes down temporarily (or indeed any other temporary communication disturbance). Before an RFC call is executed, the conection is ping checked, and then a single reconnection attempt is tried if the ping fails. If the reconnect fails then an error is raised so it is a good idea to wrap your code in a rescue block, to deal with the situation in your local conditions. Here is an example log:... [SapUser] missing_method: Z_BAPI_USER_GETLIST [SapUser] ifaces: ["SUSR_USER_LOCKSTATE_GET", "BAPI_USER_GET_DETAIL", "BAPI_USER_UNLOCK", "BAPI_USER_LOCK", "Z_BAPI_USER_GETLIST"] in check connect... Think Im connected - lets check ... RFC PING[]... Something wrong with connection(1) - do it again ... new connection(2) ... allready connected ... [SapUser] missing_method: Z_BAPI_USER_GETLIST [SapUser] ifaces: ["SUSR_USER_LOCKSTATE_GET", "BAPI_USER_GET_DETAIL", "BAPI_USER_UNLOCK", "BAPI_USER_LOCK", "Z_BAPI_USER_GETLIST"] in check connect... Think Im connected - lets check ... RFC PING[true]... ...
Here you can see the first RFC_PING return nil, and the second after reconnect return [true].
Posted by PiersHarding at 3:05 PM
October 18, 2006
sapwas for Ruby and HTTPS
sapwas for Ruby now enables SAP Web Services to be called via HTTPS. This first requires you to setup SSL support in NW4 - which isn't too much trouble if you follow Gregors' excellent advice here. Once that is in place, then it is just a matter of structuring the URL coorectly, as described in this example:
require "SAP/WAS"
@was = SAP::WAS.new(:url => "https://seahorse.local.net:8443/sap/bc/srt/rfc/sap/Z_RFC_READ_REPORT_01",
:lang => "EN",
:client => "010",
:user => "developer",
:passwd => "developer",
:trace => true)
# get a list of users
irep = @was.RFC_READ_REPORT
irep.program.value = 'SAPLGRAP'
irep.call()
puts "qtab no rows are: #{irep.qtab.rows.length.to_s}"
puts "qtab rows are: #{irep.qtab.rows.inspect}"
sapwas fully integrates with sap4rails as an alternative driver for accessing either RFCs or SAP SOAP based Web Services, and is available here.
Posted by PiersHarding at 10:48 AM
October 15, 2006
Ruby, Ruby on Rails, and SAP Web Services Integration
Something I like about Scripting Languages is the way they revel in having "more than one way to skin a cat". So, in this spirit I have built a complementary interface to saprfc (for Ruby) called sapwas, that facilitates RFC calls via SAP Web Services. This has been integrated into sap4rails, and the attached example demonstrates how to substitue Web Services for RFC integration in Ruby on Rails.
SAP Web Services vs RFC?
Other than curiosity, there is another motivation for trying this out - Since there has been discussion of late on the merits of RFC and Web Service technology such as SOAP, I thought that inorder to do the subject justice I would do some further (tangible) investigation.
To me, the most obvious way to draw a comparison, is to develop comparable examples of each, with the only difference being the substitution of the technology in question.
This led to me focusing on a recent article I wrote: Ruby on Rails with AJAX, to use as a base line.
Activating the SAP Web Service support
If we take the example above (Ruby on Rails with AJAX), then the changes are as follows:
- Install sapwas (version 0.02+)
- Upgrade sap4rails (version 0.04+)
- modify the SapUser model
- set your Rails configuration
Install sapwas
Download either the source distribution, or the gem file by following the sapwas project download links. Gem files are easier to deal with - all you need to do is:
gem install sapwas-<version>.gem
And its done (use gem uninstall to remove if its there allready).
You will probably need to install http-access2 inorder to get the basic authentication working correctly. This is a requirement of the SOAP4R library.
Upgrade sap4rails
Download either the source distribution, or the gem file for sap4rails by following the project download links. First remove the old version, and install the new:
gem uninstall sap4rails gem install sap4rails-<version>.gem
If you have used the source distribution previously, then you will have to manually remove the previous one, and install again (the usual ruby setup.rb dance - gems are soo much easier :-).
Modify the SapUser model
In the Rails application, edit the app/models/sap_user.rb, and change the super class for SapUser:
class SapUser < SAP4Rails::WS::Base ...
Set your Rails configuration
Modify the config/sap.yml file - you really should only need to add in the :url line depicted below, but check anyway:
client: "010" url: "http://seahorse.local.net:8000/sap/bc/soap/rfc" user: developer passwd: developer lang: EN
note on WAS configuration
You must ensure that /sap/bc/soap/rfc is configured/activated correctly in transaction SICF.
Go!
Once you have completed these changes, you can then test the Rails application as described in Ruby on Rails with AJAX - it should function in exactly the same manner - wasn't that easy!
Now you have it working - I'll leave you to draw your own conclussions on it's merits :-)
Posted by PiersHarding at 6:11 PM
October 10, 2006
SAP the Enterprise, and Rails interest is building
I've just recently had contact from Lance, at the Engine Yard, who specialise in Rails applicaition development, and Hosting. These guys recognise that for their more Enterprise related clients, there is likely to be an SAP related dimension to their requirements.
To me - this kind of interest shows that Ruby on Rails is making a step change in it's progress through the world of IT, where it will likely start penetrating into the Enterprise software development market.
Posted by PiersHarding at 7:58 AM
September 29, 2006
saprfc Ruby on Rails with AJAX
Since I wrote an article about integration of SAP and Ruby on Rails, it has been great to see the beginnings of a kernel of interest. As a result I decided to package up the sap4rails code and distribute it properly on RAA.Rails and AJAX
One of the interesting things that Ruby on Rails provides is built AJAX functionality by virtue of an API over prototype, and Scriptalicious. In this blog, I would like to show how neatly this integration is implemented in RubyOnRails, using a simple example of Locking, and Unlocking SAP R/3 user accounts.Installation Requirements
For this example you will need to do your own install of Ruby On Rails. Use the instructions for installing Ruby, Ruby On Rails, the RFCSDK, and saprfc in the RadRails blog.Just be sure to install versions Ruby 1.8.4+ and Rails 1.1.2+.
Once you have got this far, the last thing to install is sap4rails. You can either install the source package or download the gem, and install this with:
gem install sap4rails-<version>.gem.
UserAdmin
For this example, most of the standard BAPIs are adequate. We need to be able to list users, with their details, including their lock state. We also need to be able to lock and unlock them.The general functionality of the application is to create two lists of users on a page - locked and unlocked - and for you to be able to drag a user from one to the other to change their lock state in SAP.
The following RFCs are used:
- BAPI_USER_GETLIST - list users, and their address details
- BAPI_USER_LOCK
- BAPI_USER_UNLOCK
BAPI_USER_GETLIST is not quite enough. This, I have had to wrap in another function module and also modify the results table to include the lock status information of users.
Create a new function module called Z_BAPI_USER_GETLIST, and make sure that
you activate it for RFC on the attributes tab (in SE37) (code).
Create a new structure called ZBAPIUSNAME, and include the two structures BAPIUSNAME, and USLOCK like this
.
Make sure that you activate the structure.
The code and interface needs to be completed like this:
FUNCTION Z_BAPI_USER_GETLIST.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" VALUE(MAX_ROWS) TYPE BAPIUSMISC-BAPIMAXROW DEFAULT 0
*" VALUE(WITH_USERNAME) TYPE BAPIUSMISC-WITH_NAME DEFAULT SPACE
*" EXPORTING
*" VALUE(ROWS) TYPE BAPIUSMISC-BAPIROWS
*" TABLES
*" SELECTION_RANGE STRUCTURE BAPIUSSRGE OPTIONAL
*" SELECTION_EXP STRUCTURE BAPIUSSEXP OPTIONAL
*" USERLISTLOCK STRUCTURE ZBAPIUSNAME OPTIONAL
*" RETURN STRUCTURE BAPIRET2 OPTIONAL
*"----------------------------------------------------------------------
*
data:
LOCKSTATE LIKE USLOCK,
userlist like bapiusname occurs 0 with header line.
refresh userlistlock.
CALL FUNCTION 'BAPI_USER_GETLIST'
EXPORTING
MAX_ROWS = 0
WITH_USERNAME = with_username
IMPORTING
ROWS = rows
TABLES
SELECTION_RANGE = selection_range
SELECTION_EXP = selection_exp
USERLIST = userlist
RETURN = return
.
loop at userlist.
move-corresponding: userlist to userlistlock.
if userlistlock-firstname = space.
userlistlock-firstname = userlistlock-username.
endif.
CALL FUNCTION 'SUSR_USER_LOCKSTATE_GET'
EXPORTING
USER_NAME = userlist-username
IMPORTING
LOCKSTATE = lockstate
EXCEPTIONS
USER_NAME_NOT_EXIST = 1
OTHERS = 2
.
move-corresponding: lockstate to userlistlock.
append userlistlock.
endloop.
ENDFUNCTION.
Activate the function module and test it.
The Rails part
The full application can be downloaded from here - but what I'd like to do is quickly describe the meat of what had to be done to get this type of application working.
Config - sap.yml
As described in the RadRails blog, you need to adjust the configuration in config/sap.yml to point to your SAP system:
development: ashost: 10.1.1.1 sysnr: "00" client: "010" user: developer passwd: developer lang: EN trace: "1" ...
Model - sap_user.rb
The SapUser object now inherits from the new SAP4Rails::Base class. This
serves to automatically take care of managing RFC connections based on the
config done above. The two main class methods for use are function_module,
which allows you to declare what RFCs you want to use, and parameter which is
a helper method for declaring attributes of a SapUser (or any other Model
object).
In the interests of simplifying the application, by reducing the amount of
ABAP code to be written, and the number of RFC calls to be made, I have in a
way "cheated", with the arrangement of methods defined in SapUser. Instead of
having a SapUser#find method, I rely on the use of SapUser#find_all and
SapUser#find_cache to reduce a series of SapUser searches down to one RFC call
only. In reality this is probably not good practice, but it suits for this
example.
Read the code comments below for further details:
require_gem "sap4rails"
class SapUser < SAP4Rails::Base
# You must define a list of RFCs to preload
function_module :Z_BAPI_USER_GETLIST,
:BAPI_USER_LOCK,
:BAPI_USER_UNLOCK
# You must define a list of attribute accessors to preload
parameter :last, :first, :userid, :locked
# do your attribute initialisation for each SapUser instance
def initialize(last, first, userid, locked)
@last = last
@first = first
@userid = userid
@locked = locked
@changed = false
end
# what is the lock state
def locked?
return self.locked ? true : false
end
# on #save - flip the lock state of the SapUser, calling the
# appropriate RFC to do it
def save()
RAILS_DEFAULT_LOGGER.warn("[SapUser]#save what did we get: " + self.inspect)
if self.locked?
SapUser.BAPI_USER_LOCK.reset()
SapUser.BAPI_USER_LOCK.username.value = self.userid
SapUser.BAPI_USER_LOCK.call()
else
SapUser.BAPI_USER_UNLOCK.reset()
SapUser.BAPI_USER_UNLOCK.username.value = self.userid
SapUser.BAPI_USER_UNLOCK.call()
end
# just so something happens ...
return true
end
# one RFC call to get them all
def self.find_all
RAILS_DEFAULT_LOGGER.warn("[SapUser]#find_all ")
SapUser.Z_BAPI_USER_GETLIST.reset()
SapUser.Z_BAPI_USER_GETLIST.with_username.value = 'X'
SapUser.Z_BAPI_USER_GETLIST.call()
users = []
SapUser.Z_BAPI_USER_GETLIST.userlistlock.rows().each {|row|
next if row['FIRSTNAME'].strip.length == 0
state = nil
if row['WRNG_LOGON'] == "L" ||
row['LOCAL_LOCK'] == "L" ||
row['GLOB_LOCK'] == "L"
state = true
else
state = false
end
users.push(SapUser.new(row['LASTNAME'],
row['FIRSTNAME'],
row['USERNAME'],
state))
}
return users
end
# find a user base on the results of a SapUser#find_all
def self.find_cache(user, cache)
RAILS_DEFAULT_LOGGER.warn("[SapUser]#find_cache: #{user} ")
cache.each{|row|
return row if user.strip == row.userid.strip
}
end
# get a list of all the locked users
def self.find_locked
RAILS_DEFAULT_LOGGER.warn("[SapUser]#find_locked ")
locked = []
find_all().each{|user|
locked.push(user) if user.locked
}
return locked
end
# get a list of all the unlocked users
def self.find_unlocked
RAILS_DEFAULT_LOGGER.warn("[SapUser]#find_unlocked ")
unlocked = []
find_all().each{|user|
unlocked.push(user) unless user.locked
}
return unlocked
end
end
Controller - lock_controller.rb
There are only 3 basic actions to the only controller in this application. The initial list action, build the starting page presenting the two lists of users (locked and unlocked). From there, as a result of the AJAX enabled calls from the dragndrop feature, two further actions are called - set_locked and set_unlocked.
class LockController < ApplicationController
# gnerate the starting user lists, and hand off to the default list view
def list
RAILS_DEFAULT_LOGGER.warn("[LIST] Parameters: " + @params.inspect)
@locked_users = SapUser.find_locked()
@unlocked_users = SapUser.find_unlocked()
RAILS_DEFAULT_LOGGER.warn("[LIST] of Locked: " + @locked_users.inspect)
RAILS_DEFAULT_LOGGER.warn("[LIST] of UNLocked: " + @unlocked_users.inspect)
end
# check through the list of locked users in the locked sortable_element box
# and set their locked state in necessary
# on completion - render the partial locked_users
def set_locked
RAILS_DEFAULT_LOGGER.warn("[SET_LOCKED] Parameters: " + @params.inspect)
@locked_users = []
cache = SapUser.find_all()
if @params['locked_box']
@params['locked_box'].each {|locked|
next if locked.length == 0
user = SapUser.find_cache(locked, cache)
next if user.first.strip.length == 0
if user && ! user.locked?
user.locked = !user.locked?
user.save
end
@locked_users.push(user)
}
end
render :partial => 'locked_users', :object => locked_users
end
# exact opposite/the same as set_locked
def set_unlocked
RAILS_DEFAULT_LOGGER.warn("[SET_UNLOCKED] Parameters: " + @params.inspect)
@unlocked_users = []
cache = SapUser.find_all()
if @params['unlocked_box']
@params['unlocked_box'].each {|unlocked|
next unless unlocked.length > 0
user = SapUser.find_cache(unlocked, cache)
next if user.first.strip.length == 0
if user && user.locked?
user.locked = !user.locked?
user.save
end
@unlocked_users.push(user)
}
end
render :partial => 'unlocked_users', :object => unlocked_users
end
# called by the rendering action of the partial locked_users
def locked_users
RAILS_DEFAULT_LOGGER.warn("[LOCKED_USERS] of Locked: " + @locked_users.inspect)
@locked_users
end
# called by the rendering action of the partial unlocked_users
def unlocked_users
RAILS_DEFAULT_LOGGER.warn("[UNLOCKED_USERS] of UNLocked: " + @unlocked_users.inspect)
@unlocked_users
end
end
Views
The the overall page template (layout) defines the shape of the page, and what JavaScript libraries are pulled in for the effects (AJAX). All pages inherit from this.layout/application.rhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>User Administration: <%= controller.controller_name %></title>
<meta http-equiv="imagetoolbar" content="no" />
<%= stylesheet_link_tag "administration.css" %>
<%= javascript_include_tag "prototype", "effects", "dragdrop",
"controls" %>
</head>
<body>
<div id="container">
<div id="header">
<div id="info">
<%= link_to "home", :controller=> "/lock", :action => 'list' %>
</div>
<h1><%= link_to "UserAdmin - #{controller.controller_name}", :controller => "/lock" %>
</h1>
</div>
<div id="content">
<h2><%= @page_heading %></h2>
<%= @content_for_layout %>
</div>
</div>
</body>
</html>
lock/list.rhtml
The two most important things in list are the two container div tags - unlocked_box and locked_box. These in turn, have a corresponding partial (unlocked_users, and locked_users), that are responsible for generating the dragable user items.
<% @heading = "User Admin - Lock/UnLock" %>
<div id="user-admin">
<div id="unlocked" class="dropbox">
<h3>Unlocked Users</h3>
<div id="unlocked_box">
<%= render :partial => 'unlocked_users', :object => @unlocked_users %>
</div>
</div>
<div id="cnt-locked" class="dropbox">
<h3>Locked Users</h3>
<div id="locked_box">
<%= render :partial => 'locked_users', :object => @locked_users %>
</div>
</div>
<br clear="all" />
</div>
lock/_unlocked_users.rhtml
the partial unlocked_users either displays a place holder element if there are no users, or calls the render of unlocked_user for each user. It also uses the AJAX function sortable_element which dictates what div container holds the sortable drag and drop elements, and what actions to take when an event is fired with them. This is how we trigger the call to the set_unlocked or set_locked action of the list controller for updating the individual "boxes" of users.
<% if unlocked_users.empty? %>
<div class="target"> You have no Unlocked SAP Users.... </div>
<% else %>
<%= render :partial => 'unlocked_user', :collection => unlocked_users %>
<% end %>
<%= sortable_element "unlocked_box",
:update => "unlocked_box",
:url => {:action=>'set_unlocked'},
:tag => 'div', :handle => 'handle', :containment => ['unlocked_box','locked_box'] %>
<%= sortable_element "locked_box",
:update => "locked_box",
:url=> {:action=>'set_locked'},
:tag => 'div', :handle => 'handle', :containment => ['locked_box','unlocked_box'] %>
lock/_unlocked_user.rhtml
the partial unlocked_user renders a dragble_element for each SapUser.
<div id="unlockeduser_<%= unlocked_user.userid %>" class="dragitem">
<h4 class="handle"><%= unlocked_user.userid %></h4>
<p><%= unlocked_user.last + ", " + unlocked_user.first %></p>
</div>
<%= draggable_element "unlockeduser_#{unlocked_user.userid}" %>
lock/_locked_users.rhtml
the same as for the partial unlocked_users
<% if locked_users.empty? %>
<div class="target"> You have no Locked Users ... </div>
<% else %>
<%= render :partial => 'locked_user', :collection => locked_users %>
<% end %>
<%= sortable_element "unlocked_box",
:update => "unlocked_box",
:url => {:action=>'set_unlocked'},
:tag => 'div', :handle => 'handle', :containment => ['unlocked_box','locked_box'] %>
<%= sortable_element "locked_box",
:update => "locked_box",
:url=> {:action=>'set_locked'},
:tag => 'div', :handle => 'handle', :containment => ['locked_box','unlocked_box'] %>
lock/_locked_user.rhtml
the same as for the partial unlocked_user
<div id="lockeduser_<%= locked_user.userid %>" class="dragitem">
<h4 class="handle"><%= locked_user.userid %></h4>
<p><%= locked_user.last + ", " + locked_user.first %></p>
</div>
<%= draggable_element "lockeduser_#{locked_user.userid}" %>
In config/routes.rb add:
map.connect '', :controller => "lock", :action => 'list'and make sure that you delete public/index.html
This makes sure that any requests to the root of the server eg. http://localhost:3000, are forwarded onto the list action of the lock controller.
firing Up
Start the Rails WEBrick server by running the script:
ruby scripts/serverOpen your broswer and point to http://localhost:3000.
When you connect to http://localhost:3000 (there will be an inital delay as
sap4rails caches the RFC calls), you should get a screen that looks like this
A Flash movie of this in action can be seen here.
Posted by PiersHarding at 11:08 AM
September 22, 2006
saprfc and RadRails
Ruby On Rails and SAP
Last August, I wrote a weblog about SAP on Rails. In a follow up to that I'd like to explain how to import the example into an Eclipse environment called RadRails. RadRails is a specialised Eclipse install that contains a set of plugins for developing native Ruby, and Ruby on Rails applications.The point of this blog entry is to explain how to import that example into RadRails, thus enabling all the IDE lovers out there to explore the example in their favourite environment.
All kidding aside - RadRails is a nice way to break into Rails development as it aids in visualising how a Rails application holds together.
Getting the necessary packages
The instructions for installation vary according to your OS. I will explain for both Linux, and win32.The basic breakdown is as follows:
- Make sure that you have the RFCSDK
- Install Ruby
- Install RubyGems
- Install Rails
- Install RadRails
- Import and configure the Exrates example
- Install SAP::Rfc for Ruby
Install the RFCSDK
Ensure that you have the RFCSDK installed on your platform available from http://service.sap.com/connectors. For Linux this must be in /usr/sap/rfcsdk - check that librfccm.so is available in /usr/sap/rfcsdk/lib, and that it can be found at run time (you may have to add /usr/sap/rfcsdk/lib into /etc/ld.so.conf, and run ldconfig to do it).For win32 (I've tested this on XP SP2) - make sure that the RFCSDK has been installed correctly, most likely as part of the SAP GUI client install, if you can't get it from http://service.sap.com/connectors.
Install Ruby, RubyGems, and Ruby on Rails
Detailed instructions for installing Ruby On Rails are found on the rails Website. The following is the guide for the impatient:
- Install Ruby from here - it is *VERY* important to use this version for windows. For Debian: apt-get install ruby1.8 ruby-1.8-dev irb ri (more details here ). For other flavours of Linux, I'm afraid you'll have to figure that out for yourself, as I use Ubuntu a Debian derivative.
- Install Ruby Gems - get gems from here, extract the archive, and then from the command line execute "ruby setup.rb" in the zip files root directory.
- Install Rails - from the command line execute "gem install rails --include-dependencies"
- For windows users it's a good idea to reboot now, as not everything that is running will have picked up the new path etc. pointing to ruby
Install RadRails
Make sure you have a working JRE - you can get one from here - I used version 5 update 06.Obtain and install RadRails - 0.6.2 can be downloaded from here. This is availble as a standalone IDE, and as a Plugin - what I show here is only dealing with the standalone version.
Importing the Exrates example
- Download the Eclipse project directory for the ExRates example from here. Unpack the archive, somewhere handy.
- launch RadRails, and when it asks for a workspace, point it at the rails sub directory that was unpacked above.
- Once the application is launched we need to get some settings right:
- ruby installation - navigate to Window => Preferences => Ruby => Installed Interpreters. Change the entry "mine" to point to your installed ruby. For windows, this will most likely be C:\ruby\bin\ruby.exe.
- Again, in the preferences panel - set the locations of rdoc, and ri
You should now have a workspace that looks like this:
Installing SAP::Rfc for Ruby
This part is dependent on you successfully installing the RFCSDK above.If you are running win32 then download the saprfc 0.16 gem and install from the command line with: "gem install saprfc-0.16-mswin32.gem". Because this is a gem based install, the way that this is loaded into an application for use is different. Because of this you will need to modify SAP4Rails.rb. Navigate to this file in RadRails Exrates/lib/SAP4Rails.rb. change line 3 from: require 'SAP/Rfc'
to:
require 'rubygems' require_gem 'saprfc'
Under Linux, get the SAP::Rfc software, unpack and follow the build instructions in the README file, which are basically:
ruby extconf.rb make make install
Running the Exrates example
- Reconfigure the SAP RFC connection information - navigate in the left hand file panel to the config/sap.yml file. Modify the connection setting here, before launching the server, to point to your own R/3 system.
- Run the ExRates WEBRick server (bottom Servers tab), and then check the console to see if the server started correctly (botton Console tab) - then point browser at http://localhost:3000
You should now see a running server:
Trouble Shooting
If the WEBrick server does not appear to start correctly, then check the console, and the rails/Exrates/server.log, and development.log. Most times the problems are going to be with the ruby, and rails install.As this example was developed under Linux, I have noticed that the ExratesServer defined in the bottom panel Servers tab of RadRails, needs to be recreated under windows. To do this, highlight the entry, and delete (Red X for "Remove" at top of panel). Then go File => New => Server => WEBRick Server. This should give you a dialog box with Project, Name, and Port - accept the defaults, and try starting the server again.
If there is a problem with the RFC connection, then this will appear on the console log, and further debug information should be available in the rails/Exrates/dev_rfc file.
Wrapping it up
Hopefully, you now have everything up and running - Now all I need to do is to get Craig to add this one into the "Box" :-)
Credits:
- Thanks go to Olivier Boudry, who tirelessly helped out with debugging win32 gem build issues.
- Thanks also to Craig for picking up the ball and running with it
Posted by PiersHarding at 11:06 AM
September 1, 2006
sap4rails now has SAP::WAS - SAP Web Services Integraton
Following on from creating SAP::WAS for Ruby (SAP Web Services integration), sap4rails, has been enhanced to take advantage of SAP::WAS as an alternate "driver" for SAP connectivity. The latest version (0.04) can be obtained here, and an article showing an example of usage is here on SDN.
Posted by PiersHarding at 11:41 AM