Need help using Savon gem! (SOAP)

I'm trying to use this "Sendfax" method defined here:
https://ws.interfax.net/dfs.asmx?WSDL. I can't seem to a set a
properly format the request however. Previously I was using
SOAP::WSDLDriverFactory and was succesfully using the service, but
inside a rails application it could not find the "SOAP" module. A
fair bit of time was spent with no resolution.

I read good things about SAVON (http://github.com/rubiii/savon) but I
can't seem to get it to work in a test or in a project. If anyone is
familiar with Savon, I'd -really- appreciate some help as I am stumped
as to why this isn't working.

I have some straight-forward code:

def client
      @client ||= Savon::Client.new "https://ws.interfax.net/dfs.asmx?
WSDL"
end

def send_fax(username="foo", password="bar", fax_number=nil, data=nil)

      @response = client.sendfax do |soap|
         soap.body = {:Username => username,
                      :Password => password,
                      :FaxNumber => fax_number,
                      :FileData => data,
                      :FileType => "HTML"}
      end
end

ghettoiam wrote:

Previously I was using
SOAP::WSDLDriverFactory and was succesfully using the service, but
inside a rails application it could not find the "SOAP" module.

What was the exact error and the line which caused it? I would expect
the solution to be just something like

  require 'soap4r'

at the top of your controller.

If you have code which is happily running outside rails, then IMO your
best bet is to get it to work inside rails, rather than switching to a
completely different library (which probably will suffer the same
problem)

At very worst you could set up a DRb service which does the SOAP work,
and call it from your Rails app. But I don't think that will be
necessary.

···

--
Posted via http://www.ruby-forum.com/\.

Brian Candler wrote:

What was the exact error and the line which caused it? I would expect
the solution to be just something like

Thanks for the advice!

Here is a link to the stack trace, code and test of the error:

http://pastie.org/949549

As I mentioned, the test passes. In RubyMine (IDE) I can even click
through SOAP::WSDLDriverFactory to the underlying SOAP module.

I'm hoping a require can fix it but I'm not having any luck. I don't
understand why I'd need to require something inside of rails that I
don't in my test.

Thanks again for any help!

···

--
Posted via http://www.ruby-forum.com/\.

Dan Cruickshank wrote:

Thanks again for any help!

For whatever its wroth in the IRB I get this

require "soap/wsdlDriver"

=>

In my test I seem to get

found = require "soap/wsdlDriver"
- where found is nil

···

--
Posted via http://www.ruby-forum.com/\.

Dan Cruickshank wrote:

I'm hoping a require can fix it but I'm not having any luck. I don't
understand why I'd need to require something inside of rails that I
don't in my test.

Do you have the soap4r gem installed? There's an old and now rather
broken soap4r in the ruby standard library. Perhaps you're using the gem
in one environment and not the other. Worse, perhaps you have loaded
part of the old soap4r before gems are activated, and another part
afterwards.

At the line before the error in fax_api.rb you could break into debugger
and poke around, or add debugging statements like
  STDERR.puts $LOAD_PATH.inspect
  STDERR.puts ::SOAP.constants.inspect

Also: take your working test code and run it using
  script/runner whatever.rb
which will first boot up the rails environment, then run the script you
provide. Does it now fail?

What about using script/console instead of irb?

If you can make a standalone test case which is just a couple of lines
that you run from script/runner or script/console, that would be an
ideal way to get the problem resolved quickly.

FaxApi - Throws an "uninitialized constant FaxApi::WSDLDriverFactory"
error when called from the controller

Are you sure that's the error it gives? Not FaxAPI::SOAP ?

Now, I agree you don't need to require soap if you have done this in
your fax_api.rb file. But you could try this at the top of fax_api.rb:

gem 'soap4r'
require 'soap/wsdlDriver'

and/or declare the soap4r gem dependency in config/environment.rb

And for extra belt-and-braces use ::SOAP instead of SOAP, i.e. change

    def wsdl
      @soap ||=
SOAP::WSDLDriverFactory.new("InterFax Web Service)
    end

to

    def wsdl
      @soap ||=
::soap::WSDLDriverFactory.new("InterFax Web Service)
    end

I wouldn't worry about the return value from 'require', since Rails
mucks around with the internals of require (as well as const_missing
stuff). But if none of the above helps, check what version of rubygems
you have installed. If it's not the latest, try upgrading it.

HTH,

Brian.

···

--
Posted via http://www.ruby-forum.com/\.

Brian Candler wrote:

Dan Cruickshank wrote:

Do you have the soap4r gem installed?

yes. 1.5.8

Worse, perhaps you have loaded
part of the old soap4r before gems are activated, and another part
afterwards.

Might be (more on that below)

At the line before the error in fax_api.rb you could break into debugger
and poke around, or add debugging statements like
  STDERR.puts $LOAD_PATH.inspect

Done (below)

Also: take your working test code and run it using
  script/runner whatever.rb
which will first boot up the rails environment, then run the script you
provide. Does it now fail?

script/runner lib/fax_api.rb RUNS and submits the fax

these two lines will also connect to it
- script/console
- >> require "lib/fax_api"

I've added (api = FaxAPi.new; api.send(...) to the bottom of my class)

What about using script/console instead of irb?

If you can make a standalone test case which is just a couple of lines
that you run from script/runner or script/console, that would be an
ideal way to get the problem resolved quickly.

Does anything above help us solve this quicker? I've created a new bare
bones rails application and it fails as well with called in a
controller.

::soap::WSDLDriverFactory.new("InterFax Web Service)
-> uninitialized constant SOAP error

Now, the last thing I found was this ticket that implies many problems
between rails and SOAP4R. I didn't realize originally that I was using
SOAP4R underneath all this, but I guess I am.

http://dev.ctor.org/soap4r/ticket/433

They imply that there is a problem between rails and soap4r and the
order of things. I think they say I should be able to put "gem
'soap4r'" at the top of my environment.rb or somewhere in my boot.rb,
but I haven't had any luck with that yet. This sounds like the most
promising avenue however.

···

--
Posted via http://www.ruby-forum.com/\.

Dan Cruickshank wrote:

Does anything above help us solve this quicker? I've created a new bare
bones rails application and it fails as well with called in a
controller.

I created a bare-bones rails-2.3.4 application, with one controller:
script/generate controller hello

and it works fine with
[app/controllers/hello_controller.rb]
require 'soap/wsdlDriver'
class HelloController < ApplicationController
  def world
    soap =
::soap::WSDLDriverFactory.new("InterFax Web Service)
    render :text => "Hello!"
  end
end

And so does the following:
[app/controllers/hello_controller.rb]
require 'soaptest'
class HelloController < ApplicationController
  def world
    Soaptest.get_soap
    render :text => "Hello!"
  end
end

[lib/soaptest.rb]
module Soaptest
  def self.get_soap
    ::soap::WSDLDriverFactory.new("InterFax Web Service)
  end
end

···

--
Posted via http://www.ruby-forum.com/\.

I wish I had such luck. That doesn't work me. There must something
else a foot on my machine.

Following some other old threads looking at issues with soap4r, I put
this a the top of my environment.rb and it worked (!!!!!) :

require "rubygems"
gem "soap4r"
require "soap/soap"
require "soap/wsdlDriver"

The - require "soap/soap" - line seems key.

Thank you so much for all of your help!

Brian Candler wrote:

···

Dan Cruickshank wrote:

Does anything above help us solve this quicker? I've created a new bare
bones rails application and it fails as well with called in a
controller.

I created a bare-bones rails-2.3.4 application, with one controller:
script/generate controller hello

and it works fine with
[app/controllers/hello_controller.rb]
require 'soap/wsdlDriver'
class HelloController < ApplicationController
  def world
    soap =
::soap::WSDLDriverFactory.new("InterFax Web Service)
    render :text => "Hello!"
  end
end

And so does the following:
[app/controllers/hello_controller.rb]
require 'soaptest'
class HelloController < ApplicationController
  def world
    Soaptest.get_soap
    render :text => "Hello!"
  end
end

[lib/soaptest.rb]
module Soaptest
  def self.get_soap
    ::soap::WSDLDriverFactory.new("InterFax Web Service)
  end
end

--
Posted via http://www.ruby-forum.com/\.