Skip to Content


Ruby on Rails is an exciting new (in an old sense) way of developing Web Services.  It neatly combines convention with Best Practice, to help reduce the drag on development with the removal of declaritive cruft, allowing you to concentrate on the specifics of your application.  What I want to achieve with this article, is to give you a taste for what Rails can do, and show how access to SAP business related functions can be easily integrated.
</p>

Ruby



Rails takes full advantage of the dynamic scripting language Ruby, which allows you to make most changes to your code without server restart, or the requirement of deployment tools.  Ruby is a worthy contender in the rapid development space of web languages such as Perl and Python, with OO concepts built into the core, from the word go.  With a natural intuitive style, and powerful text processing capabilities – it has all the things necessary for easy but scaleable Web Service development.
</p>

Rails Convention


Naming standards are used to reduce the amount of configuration required eg: tables relate specifically to Models, Ruby class naming conventions map directly to Controllers, Actions, and Views. Typically – the only configuration required in a Rails application is to specify the database connection parameters. Unlike some frameworks, which require extensive configuration in various incarnations of XML.


Rails Best Practice



Rails adheres to the industry design standard that is MVC , giving good separation of the data model, the application flow control, and the presentation layer composition.

On top of this, the Rails framework offers standard ways of handling errors, and error notification, templating and page componentisation, and the ability to swap these presentation formulas for different delivery channels.


Rails also has built in AJAX support available, to take advantage of the latest interest in DHTML, and flicker-free user experience.
</p>


Rails fundamentals


In order to cover the Rails fundamentals, I am going to digress here for a minute – it is important to get your head round this so that we can see where SAP integration may fit in, so please bare with me.


As was previously mentioned, Rails used the design principals of MVC (Model, View, Controller).  These parts of the architecture are not configured, but are bound together through naming convention.  So, if we take the classic example application of the  Cookbook then the Recipe model has a module name of recipe.rb, the associated views are held in a directory ./app/views/recipe/[list|show|…].rhtml, and the controller is RecipeController in recipe_controller.rb.
</p>


Model


Classic Rails applications are centred around the ActiveRecord suite. This manages connections to a given supported database (MySQL, Postgresql, Oracle etc.). It also takes care of the auto-discovery of tables and schema, and the mapping of row/column information to OO access routines for creating, updating, deleting, and interrogating data points.

Extending the reference to the Cookbook application – the Recipe object will, by convention, be expecting a recipes table. Rails does this all automatically with some clever gramatical interogation tricks (Recipe becomes recipe, becomes recipes).

This allows a basic Model complete with CRUD operations, to be a simple incantation like this: (Note: the belongs_to: declares the association with another Model for categories – ActiveRecord manages this relationship on the fly)


Figure 1 – Recipe Model


class Recipe < ActiveRecord::Base
belongs_to :category
end


Controller


Methods of the comtroller class (RecipeController) become the actions available to the web application. These map directly to URI names. RecipeController#list maps to /recipe/list/…. (again evidence of convention over configuration).

As you can see from the sample Controller below – each method (Action) accesses the Model to invoke the appropriate business logic to obtain the relevent data. Then the appropriate flow control is exercised (do nothing means “render with the corresponding view”, where as redirect_to changes the flow to another Action).


Figure 2 – Recipe Controller


class RecipeController < ApplicationController
layout "standard-layout"
scaffold :recipe

def new
@recipe = Recipe.new
@categories = Category.find_all
end

def index
self.list
render_action "list"
end

def list
@category = @params['category']
@recipes = Recipe.find_all
end

...
end


View


The action name (for a controller) specifies which rhtml template within a view, to pick for the rendering of the output. This can also be further “skinned” by the specification of a layout (an html super set wrapper that the content is inserted into) by the “layout” directive given in the controller (see above).


Figure 3 -list() Action => list view => list.rhtml




<b>Recipe</b>

<b>Category</b>

<b>Date</b></td>
</tr>

<% @recipes.each do |recipe| %>
   <% if (@category == nil) || (@category == recipe.category.name)%>
     <tr>
      <td>
        <%= link_to recipe.title,
                   :action => “show”,
                   :id => recipe.id %>
        <font size=-1>

        <%= link_to “(delete)”,
                    {:action => “delete”, :id => recipe.id},
                    :confirm => “Really delete #{recipe.title}?” %>
        </font>
      </td>
      <td>
        <%= link_to recipe.category.name,
                    :action => “list”,
          :category => “#{recipe.category.name}” %>
      </td>
      <td><%= recipe.date %></td>
     </tr>
   <% end %>
<% end %>

</table>
</pre>
</p>
<p>
Figure 4 – layout







  

Online Cookbook


   *<%= @content_for_layout %>*
   <p>
     <%= link_to “Create new recipe”,
                 :controller => “recipe”,
                 :action => “new” %>
 
   <%= link_to “Show all recipes”,
               :controller => “recipe”,
               :action => “list” %>
    
   <%= link_to “Show all categories”,
               :controller => “category”,
               :action => “list” %>
   </p>
</body>
</html>

</pre>
Note: *@content_for_layout* determines where the body of each rendered template associated with an action is inserted.
</p>
<p>
Further reading and tutorials for Rails can be found at RubyOnRails .  There are several excellent primers including:


The Cookbook part 1 and part 2


The whole reference guide is available at API .
</p>


SAP on Rails


SAP on Rails focuses on providing an alternative type of Model template to the default – ActiveRecord.


This is done via SAP::Rfc which allows RFC calls to SAP from Ruby, with automatic handling of data types, and discovery
of interface definitions for RFCs.  Some of this has been covered in a previous  article , and on SDN .<br/>
The model templating class is SAP4Rails.  It’s job is to automatically build up  connections to R/3, look up the interface definitions for the collection of associated RFCs, and to hold the attribute definitions for the given model.  This, coincidentally, corresponds to the SAP Business Objects view of the world in BAPIs.<br/>
</p>


Currencies and Exchange Rates



The example I have to work through is based on the two BAPI objects – Currency (BUS1090), and ExchangeRate (BUS1093).  These can be found using the transaction BAPI under “Basis Services / Communication Interfaces”.  I have used these objects as they exist in my NW4 test drive system, so they should be available as a lowest common denominator across the board.  The complete example is available at exrates.tgz .  The walk through below is going to centre around the “list” action, of the exrate controller.  This will show how to generate a list of exchange rates out of SAP.  For this we will need to develop the Exrate Model, the ExrateController controller, and the list.rhtml view associated.  Download the entire application to see all the other controller/action functions including listing, and showing details of Currencies, and the list, show, and create of Exchange rates.


Figure 5 – Currency and ExchangeRate objects in the BAPI explorer


!http://www.piersharding.com/download/ruby/bapi1.png|height=40px|width=50px|src=http://www.piersharding.com/download/ruby/bapi1.png! Click to view

Each method of a business object has an associated RFC – these are what get mapped into the Rails data model.


Figure 6 – GetCurrentRates of the ExchangeRate object maps to the RFC BAPI_EXCHRATE_GETCURRENTRATES


!http://www.piersharding.com/download/ruby/bapi2.png|height=40px|width=50px|src=http://www.piersharding.com/download/ruby/bapi2.png! Click to View


Start developing the Rails application


First install SAP::Rfc for Ruby.  It is critical that this module is loadable in the Ruby library path – so check this first with: ruby -r “SAP/Rfc” -e 1 – this will give an error “ruby: No such file to load — SAP/Rfc (LoadError)” if this module cannot be found.  If you have installed it in an unusal way, or location, then you can try setting the environment variable RUBYLIB to the relevent directory.

Next – start the project by building the basic framework – this is done using the Rails supplied tools – execute these commands to start it off:


rails Exrates
cd Exrates
./scripts/generate controller Exrate
./scripts/generate model exrate
./scripts/generate scaffold exrate

The file layout of the application is something like this (below). Some of the files shown we have yet to create/put in place.


Figure 7 – Application layout


./config/routes.rb
./config/sap.yml <== RFC connection configuration
./app/controllers/exrate_controller.rb
./app/controllers/application.rb
./app/helpers/currency_helper.rb
./app/helpers/application_helper.rb
./app/helpers/exrate_helper.rb
./app/models/exrate.rb
./app/views/layouts/standard-layout.rhtml
./app/views/exrate/show.rhtml
./app/views/exrate/new.rhtml
./app/views/exrate/_form.rhtml
./app/views/exrate/list.rhtml
./public/stylesheets/scaffold.css
./lib/saprfc.so - SAP::Rfc files installed here
./lib/SAP/Rfc.rb /
./lib/SAP4Rails.rb <== Data Model template SAP4Rails

Note: I installed SAP::Rfc into the ./lib directory along side SAP4Rails.rb – this is just a matter of preference.

Grab SAP4Rails.rb from here and place it in the

SAP4Rails – the Data Model


When ./scripts/generate model exrate is executed a number of files are created, including ./app/models/exrate.rb.  This contains the basic definition using ActiveRecord:


Figure 8 – Default Exrate code


class Exrate < ActiveRecord::Base
end

This needs to be changed to use SAP4Rails:


Figure 9 – Our Exrate code



require “SAP4Rails”
class Exrate < SAP4Rails

  1. You must define a list of RFCs to preload

  @@funcs = [
       ‘BAPI_EXCHANGERATE_CREATE’,
       ‘BAPI_EXCHRATE_CREATEMULTIPLE’,
       ‘BAPI_EXCHRATE_GETCURRENTRATES’,
       ‘BAPI_EXCHANGERATE_GETDETAIL’,
       ‘BAPI_EXCHANGERATE_GETFACTORS’,
       ‘BAPI_EXCHRATE_GETLISTRATETYPES’,
       ‘BAPI_EXCHANGERATE_SAVEREPLICA’,
       ‘BAPI_TRANSACTION_COMMIT’,
  ]


  1. You must define a list of attribute accessors to preload

  @@params = [ ‘from’,
               ‘extype’,
               ‘to’,
               ‘rate’,
               ‘validfrom’,
  ]
 
 

  1. User defined instance methods here

  attr_accessor :message


   

  1. user defined Class methods

  class << self
    def list
      t = Date.today
      tday = sprintf(“%04d%02d%02d”, t.year.to_i, t.month.to_i, t.day.to_i)
      RAILS_DEFAULT_LOGGER.warn(“[Exrate] date: ” + tday)
      Exrate.BAPI_EXCHRATE_GETCURRENTRATES.date.value = tday
      Exrate.BAPI_EXCHRATE_GETCURRENTRATES.call()
      return Exrate.BAPI_EXCHRATE_GETCURRENTRATES.exch_rate_list.rows()
    end
  end
end
</pre>
The noticeable difference here is the two class attributes, @@funcs, and @@params.  As the comments suggest – these are how we tell SAP4Rails what RFCs need to be preloaded, and what attributes our model is going to have.  Technically speaking, this example does not need the @@params as this is used when building Rails update, and create features.
<br/>
When the Exrate class is defined at run time, these values are processed and as the first method is accessed all of the RFC definitions, and attributes are loaded up.  The full definition can be found here .
<br/>
However – before SAP4Rails can interact with an SAP R/3 system, we need to tell it how to connect to one.  This is done via a YAML based config file – ./config/sap.yml.


Figure 10 – RFC connection configuration

Create the file ./config/sap.yml with your connection settings, like this:


development:
ashost: seahorse.local.net
sysnr: "00"
client: "010"
user: developer
passwd: developer
lang: EN
trace: "1"

Note: these values are repeated for test and production.

SAP4Rails ensures that a separate RFC connection is created for each Model – this allows a separate SAP session context per data Model, which is useful for COMMIT related issues (transactions).


The Controller


When ./scripts/generator controller Exrate is executed, amoung other things, a file ./app/controllers/exrate_controller.rb containing ExrateController, is created.  The outline for this is:


Figure 11 – Default ExrateController code


class ExrateController < ApplicationController
end

We amend this with a directive for a layout to use (standard-layout), and methods index(), and list().


Figure 12 – Our ExrateController code


class ExrateController < ApplicationController
layout "standard-layout"

def index
list
render_action 'list'
end

def list
@exrates = Exrate.list()
RAILS_DEFAULT_LOGGER.warn("[LIST] exchange rates: " + @exrates.length.to_s)
end
...
end

These correspond directly to the Actions index and list for the Controller exrate, which will map to a URI of /exrate/index and /exrate/list.
The Action index() is just like a redirect to list() (the list() action is executed and then rendered). Within list(), we see a call upon the class method of our Model Exrate – Exrate.list(). If we refer back to the code above for class Exrate, we can see the definition for list(). It calls upon a dynamic method BAPI_EXCHRATE_GETCURRENTRATES which gives us access to an object representation of the same-named RFC.


Figure 13 – Code from Exrate#list


t = Date.today
tday = sprintf("%04d%02d%02d", t.year.to_i, t.month.to_i, t.day.to_i)
Exrate.BAPI_EXCHRATE_GETCURRENTRATES.date.value = tday
Exrate.BAPI_EXCHRATE_GETCURRENTRATES.call()
return Exrate.BAPI_EXCHRATE_GETCURRENTRATES.exch_rate_list.rows()

Looking closer at the Exrate.list() call, we see the date parameter of the RFC being set to todays date, and then the call() being made, and finally exch_rate_list.rows() is returned.


Figure 14 – Inteface definition of BAPI_EXCHRATE_GETCURRENTRATES as seen in SE37



FUNCTION bapi_exchrate_getcurrentrates.
*”—-


“Lokale Schnittstelle:
*”  IMPORTING
*”     VALUE(DATE) LIKE  BAPI1093_2-TRANS_DATE
*”     VALUE(DATE_TYPE) LIKE  BAPI1093_2-DATE_TYPE DEFAULT ‘V’
*”     VALUE(RATE_TYPE) LIKE  BAPI1093_1-RATE_TYPE DEFAULT ‘M’
*”     VALUE(SHOW_PROTOCOL) LIKE  BAPI1093_2-SHOW_PROTOCOL OPTIONAL
*”  TABLES
*”      FROM_CURR_RANGE STRUCTURE  BAPI1093_3
*”      TO_CURRNCY_RANGE STRUCTURE  BAPI1093_4
*”      EXCH_RATE_LIST STRUCTURE  BAPI1093_0
*”      RETURN STRUCTURE  BAPIRET1
*”—-




The interface definition for BAPI_EXCHRATE_GETCURRENTRATES (above – via transaction SE37) shows us that exch_rate_list is a table parameter, and the rows() method is returning an Array of table lines. SAP::Rfc takes care of all of this, including carving up the rows based on the table structure definition, making each line a hash of fieldname/value pairs.


Going back to the Controller – at this level, SAP RFC specificness has been abstracted away – the only hint is directly calling error methods (see the Exrate#save method definitition) – this is usually more concealed in ActiveRecord, because of the Database Schema related information being stored in the Model – this is a lot harder to achieve in relation to RFC calls, as the schema relating to an RFC is less definitive, than that of classic Rails database table design – see the Todo list, and Cookbook tutorials to get further details.  SAP4Rails uses the ActiveRecord::Errors class which is bound to an inherited attribute of the Model called @errors.  When the facilities of this class are used then error testing, recording, and then subsequent display is trivial with the inclusion of the error_messages_for directive in a view template (see fragment _form.rhtml via new.rhtml for exrate, and observe how the Exrate#save interacts with it).

Other than that – from here on in it is just plain Rails.


The Views


Now on to rendering the output.  The embedded Ruby code of the list.rhtml template gets executed in the context of the instantiated ExrateController, so it has access to all the attributes of that object.  In the interests of tidiness, I have put the column/field names relating to list() Array results in a Helper module ./app/helpers/exrate_helper.rb.  This is inherited by the controller at run time, so anything defined here is also available in the template.


Figure 15 – ExrateController helper module ExrateHelper



module ExrateHelper
 

  1. Fields for form output

  def formFields
    return    [ ‘FROM_CURR’,
                ‘TO_CURRNCY’,
                ‘RATE_TYPE’,
                ‘TO_FACTOR’,
                ‘EXCH_RATE’,
    ]
  end
end

There is so much going on within the template, but specific to our SAP4Rails example, we can see the code iterating over the attribute Array of @exrates – each element of which, holds a hash of field/value pairs. This is where the field names from formFields() are also iterated over to print out the columns.


Figure 16 – exrate template list.rhtml



Listing Exchange Rates


<%= link_to ‘Currencies’, :controller => ‘currency’, :action => ‘list’ %>
 
<table>
  <tr>
  <!– get fields from ExrateHelper –>
  <% formFields.each {|key| %>
    <th><%= key %></th>
  <% } %>
  </tr>
 
  <% for exrate in @exrates %>
  <tr>
    <% formFields.each {|val| %>
    <td>
      <% if val == “FROM_CURR” or val == “TO_CURRNCY” %>
        <%= link_to exrate[val], :controller => ‘currency’, :action => ‘show’,
                                    :id => exrate[val].strip %>
      <% else %>
        <%=h exrate[val] %>
      <% end %>
      </td>
    <% } %>
    <td>
    <%= link_to ‘Show’, :action => ‘show’, :id => exrate[‘RATE_TYPE’].strip + ‘:’
                   + exrate[‘FROM_CURR’].strip + ‘:’ +
                     exrate[‘TO_CURRNCY’].strip %>
    <%= link_to ‘Edit’, :action => ‘new’, :id => exrate[‘RATE_TYPE’].strip + ‘:’
                   + exrate[‘FROM_CURR’].strip + ‘:’ +
                     exrate[‘TO_CURRNCY’].strip %>
    </td>
  </tr>
  <% end %>
</table>
</pre>
</p>

<p>
And with that – here are the results.
</p>
<p>
Figure 17 – Listing Exchange Rates – rendered list.rhtml




In conclusion


The approach laid out in this article, has enabled a high level of integration with the Rails framework.  The amount of code required to make this possible (SAP4Rails.rb) is less than 130 lines, which I think is testimony to how flexible, and well designed Rails is.  Further more – in the data Models shown, the heavy lifting of wrestling with RFC parameters, and their associated data types has been made trivial with SAP::Rfc and it’s auto-interface-discovery features.  Have a closer look at the resources included (see above) – and you can see why Rails is creating such a storm in the world of Open Source, and making waves in the “Traditional Commercial Web development” Arena.


Now you can get on track with your Web Services development. 🙂


Note: since this was first published, SAP4Rails has moved on, and is now available as a separately installable module which you can get from here.  A modified version of the Exrates example is held within the source package.
</p>

To report this post you need to login first.

34 Comments

You must be Logged on to comment or reply to a post.

  1. DJ Adams
    Hi Piers – great article.

    (Disclaimer: I’m a big fan of Ruby on Rails).

    Ruby on Rails is a great example of a framework where “convention over configuration” affords huge gains in productivity and clarity, in comparison to the turgid complexity that plagues the J2EE platform.

    Furthermore, it’s only a matter of time before the enterprise software industry catches up with where Ruby (as an example) is and starts to realise the power of dynamic languages. (Incidentally, this is why the ‘enlightened ones’ refer to IDEs as “programming crutches” – requiring an IDE like Eclipse to program within should be setting off alarm bells, not championed as progress 🙂

    dj

    (0) 
    1. I cannot agree more with DJ and Piers about Ruby and Rails. I have been a secret lover for some time of this beautiful language and I really hope that it catches up with the others in the enterprise space as well. It has been simply wonderful to work with Ruby on Rails on some private projects.

      Thanks a lot for bringing this on to SDN and SAP space. Pranav

      (0) 
      1. Piers Harding Post author
        🙂

        I remember well, our conversation at the Developer Meet – infact it could be said that “This one is for you- Pranav”.

        Cheers.

        (0) 
          1. Piers Harding Post author
            Hi Pranav,
            Yes – I did see Davids’ post.  He was kind enough to point me in the right direction when I was looking for examples of other data sources for Rails, from ActiveRecord.
            Cheers.
            (0) 
  2. Valery Silaev
    Thanks for great article!

    For some time word combination SAP & PHP sounds for me like oxymoron. And now SAP & Rails! SAP & Flex… Oh Dear! It is becoming unpopular to be Java developer these days 😉

    Btw, have to admit that RoR + SAP RFC code looks far simplier then WebDynpro + Adaptive RFC.

    VS

    (0) 
  3. Community User
    Hi Piers,

    thanks for the great article. At sdn meets labs I briefly spoke with some people about ruby and told them that it is still on my todo-list. Now, some months later I have installed everything I need but still need some time to get fully started 🙂
    As I side note for the testing geeks. I found it nice that ruby will generate all the basic unit tests when you first create a new application. Furthermore ruby comes with his own unit testing tool, cool stuff =)
    Btw if someboy does not want to read a lot about ruby just watch it in action: http://www.rubyonrails.org/media/video/rails_take2_with_sound.mov

    Thomas

    (0) 
  4. Dagfinn Parnas
    First of all; Great work Piers

    Now If SAP would pour some millions into the ruby on rails project(as they’ve done with PHP http://www.theregister.co.uk/2005/08/04/evans_survey/), ) , there might be official support on such an integration, but is it realistic to expect this?

    It’d be interesting to hear the official thoughts(or for that matter unofficial) of SAP on future support for dynamic languages.

    Still I think there will go many many years before dynamic languages are not only used by the “enlightened ones”, but also used for enterprise applications.

    just my two cents though

    (0) 
    1. Piers Harding Post author
      Thanks Dagfinn – Now we’re talking.
      I’ve been trying to garner interest in binding dynamic  languages to R/3  the whole time I’ve been on SDN.
      What I would like to see is an opening up of the interface APIs for RFC (for example, I’ve been trying for over 12 months now to get someone in SAP to tell me how the new complex data types work here) so I can add greater support in Perl, Python, and Ruby, and
      Then I’d like to see SAP create a generic API within ABAP for grafting on other programming languages for communication in the opposite direction.  I’m not pretending that this is a trivial exercise, but I think it is extremely important to SAP in the area of extending its capabilities for integration, and interfacing with other products, and services that are increasingly coming from Open Source stock.
      Cheers.
      (0) 
  5. Gregor Wolf
    Hi Piers,

    I’m trying to get your Example Application running on a Debian Sarge system. I’ve installed SAP::Rfc for Ruby with the WebAS 6.20 RFCSDK. ruby -r “SAP/Rfc” -e 1 does not return an error. My ruby version is “ruby 1.8.2 (2005-04-11) [i386-linux]”, gem versin is: 0.8.11. When I call the application I got this error:

    NoMethodError in Exrate#list
    undefined method `toHash’ for nil:NilClass
    /app/models/exrate.rb:83:in `list’
    /app/controllers/exrate_controller.rb:15:in `list’
    script/server:49

    The R/3 connection works. I’ve looked in the trace file and the BAPI is called sucessfully.

    Hope you can help.

    Regards
    Gregor

    (0) 
      1. Piers Harding Post author
        Hi Gregor (and everybody) – as we discussed – we found that there is a difference in your R/3 version when it comes to defining an RFC parameter with a structure.  I have patched SAP::Rfc according and a new release is on RAA – http://raa.ruby-lang.org/project/saprfc/.
        Thanks for the help with tracking the bug down.
        Cheers,
        Piers Harding.
        (0) 
  6. Vasil Bachvarov
    Hi, Pierce,

    Thank you for the great work you’ve done!
    I think the Ruby module is quite useful and is going
    to be used by many developers.

    Unfortunately I was not able to find any documentation or examples
    on the net. I think it would be useful if you could
    provide a brief description of the basic usage
    of the classes.

    For example I need to discover an RFC function,
    set the import parameters, make the call and
    then get the output parameter.
    Still haven’t made it run, but I know I am close.

    P.S. I am not very experienced in Ruby, but know
    the basic stuff.

    Greetings
    Vasil

    (0) 
    1. Vasil Bachvarov
      P.S. I forgot to write down the conditions and what error I get.

      I am using your module with the following code:

      require ‘rubygems’
      require_gem “saprfc”

      # connect
      rfc = SAP::Rfc.new(. . .)

      # lookup the BW RFC interface
      i = rfc.discover(“…”)

      # Import parameters
      E–>  i.getParm(“PAR1”).value = par1

      # call and test the return
      rfc.call(i)

      # Export parameters
      par2 = i.getParm(“PAR2”).value
      . . .

      And I got error on the line, marked with “E–>”.
      When I debugged the code of Rfc.rb, I located the
      exception in this code area:

      . . .
      # getParm method of Iface class.
      def getParm(parm)
            return @parmsindex.has_key?(parm.upcase) ? @fieldsindex[parm.upcase] : nil
          end
      . . .

      And the error description was:
      C:/Program Files/Ruby/lib/ruby/gems/1.8/gems/saprfc-0.11-mswin32/lib/SAP/Rfc.rb:765:in `getParm’: undefined method `[]’ for nil:NilClass (NoMethodError)
           from C:/SAP_Files/PHP/workspace/Ruby/rfccall.rbx:27

      As long as I see, all other calls before the problematic line were successful and I got also
      the result of the function discovery. I was able to see all the parameters in the Watch window.
      It seems like having this “@fieldsindex” variable set to nil and trying to search in it.

      Maybe I am not using the module properly, but I have no idea how should my call look like.

      Thanks in advance.

      (0) 
      1. Piers Harding Post author
        Hi Vasil,

        There are a number of places you can get examples from:
        http://www.piersharding.com/blog/archives/saprfc/index.html is my collection for Perl, Python, and Ruby
        http://raa.ruby-lang.org/list.rhtml?name=saprfc is the official link for the Ruby SAP::rfc project.  Follow this for downloading the source, and bundled with the source are some basic examples, but more importantly it has the module documentation.

        Cheers,
        Piers Harding.

        (0) 
  7. Fabio Akita
    Hi, I was just trying out your library and I am very amazed to see that it plain works.

    Even though I am quite able to fetch exporting values and tables, I am having trouble with simple exporting structures like the ones like BAPIRETURN. It is a structure not a table like a structure. I tried two different RFCs and both returned this structure as a concatenated long string.

    Are you aware of this problem, am I doing something wrong?

    Another thing: I am very used to the SAP Java Connector and I know that sapjco does connection pooling. I can even configure how many connections I want to maintain opened.

    How does this library works, along with Rails? Does it have something similar, or it open a connection, execute and than close for each request? Or am I reading the architecture the wrong way?

    (0) 
    1. Piers Harding Post author
      Hi Fabio,
      With parameters that have structures, you should be automatically returned  a hash (key/value pairs) of the fields within – please post you sample piece of code so I can see what the problem is.

      Connection pooling is a separate problem.  I feel it should be up to the library user to determine what kind of pooling scheme they want to implement – for example, you may have more than one R/3 system tat you wish to communicate (I do at my current employment), therefore you might need to maintain separate system connections.
      In a ROR specific environment – I’m sure that it would be possible to come up with something a bit more dedicated and friendly – what do you have in mind?
      Cheers,
      Piers Harding.

      (0) 
  8. Kevin McDonald
    Thank you for sharing this topic with the forum. Ruby on Rails has been near the center of my research this past year and you have help further my understanding of how SAP may work under the Rails.

    Cheers,
    Kevin

    (0) 
  9. Bernd Schäufele
    Hi,
    I did it exactly as in the tutorial (for a method called ZFM_ATLAS_TASKS_INIT, that we have).

    So I have an array @@funcs = [

    ‘ZFM_ATLAS_TASKS_INIT’,

    ]

    and this Class Method:

    class << self
    def list
    Unit.ZFM_ATLAS_FE_DETAILS.call()
    end
    end

    When I call Unit.list() from the controller I get the following error:

    NoMethodError in UnitController#view

    You have a nil object when you didn’t expect it!
    The error occurred while evaluating nil.call

    Has anyone experienced a similar error? Obviously the RFC object does not exist. I think the connection to the R/3 system is working, as I managed to get rid of some connection errors before 😀

    Thanks in advance
    Bernd

    (0) 
    1. Piers Harding Post author
      What you need is something like:
      require_gem “sap4rails”
      class MyModel<SAP4Rails::Base
        function_module :FM1,
                        :FM2
      ….
      (0) 
  10. Bernd Schäufele
    Dear Piers,
    thank you very much for this fast answer. Now I could successfully set an RFC call. However, I would like to access a table that is defined as

    ET_FORCE TYPE  /ISDFPS/FORCE_TAB_GIS

    I tried it that way:
    return Unit2.ZFM_ATLAS_SEARCH_FE.et_force.rows()
    just like in the example.
    Unfortunately “et_force” seems to be nil and the trace file says
    ***Discarding unrequested T:ET_FORCE
    How can I make the RFC call to request this table?

    (0) 
    1. Piers Harding Post author
      You should really move this part of the conversation to the forums, as it is not strictly to do with the weblog.
      You need to explain what your function module interface looks like, as I cannot guess from what information you have given?
      Cheers,
      Piers Harding.
      (0) 
  11. Srinadh Karumuri
    It is still useful after 2 years.

    Thought a newbie might wonder.

    I read earlier but didn’t try it out myself. When I tried I realized that there is no sirectory named ‘scripts’. I guess it should be ‘script’.

    Any more work in the same lines => rails+ruby+SAP?

    (0) 

Leave a Reply