0

I'm trying to use this Ruby wrapper https://github.com/mattetti/Pvwatts but I have an issue with my controller app/controllers/projects_controller.rb (relevant excerpts)

require 'rubygems'
require 'savon'

class ProjectsController < ApplicationController
    <snip>
    def annual_production
        <snip>
        client = Savon::Client.new("http://pvwatts.nrel.gov/PVWATTS.asmx?WSDL")
        production_data = Pvwatts.new("<key>").yearly_production(:locationId => @locationId, :dc_rating => @dc_rating, :tilt => @tilt, :azimuth => @azimuth, :derate => @derate, :cost => @cost, :array_type => @array_type)
        <snip>
        respond_to do |format|
            if @project.update_attributes(params[:project])
                format.js
                format.html
            else
                format.html { render :action => "update" }
                format.json { render :json => @project.errors, :status => :unprocessable_entity }
            end
        end
    end
end

class Pvwatts
    Savon::Request.log = false
    <snip>
    def yearly_production(opts={})
        <snip>
        client = Savon::Client.new("http://pvwatts.nrel.gov/PVWATTS.asmx?WSDL")
        <snip>
        req = prep_request(@locationId, @dc_rating, @tilt, @azimuth, @derate, @array_type, @cost)
        response = client.get_pvwatts{|soap| soap.input = "GetPVWATTS"; soap.body = req }
        <snip>
    end
end

This is the definition of the button that triggers the SOAP request

<input type=button id='pvwatt_update_button_id' value="Update from PVWatts" class='pvwatt_update_button_class'>

When that button is clicked, I get this "500 Internal Server Error"

Started GET "/projects/annual_production?id=4&keys=8<key>&reference_state=California&reference_city=San+Francisco&locationId=23234&dc_rating=1&tilt=20&azimuth=180&derate=80&cost=0.1&array_type=0" for <server_ip_address> at Tue Nov 20 20:07:18 -0800 2012
Processing by ProjectsController#annual_production as */*
Parameters: {"array_type"=>"0", "azimuth"=>"180", "locationId"=>"23234", "dc_rating"=>"1", "reference_city"=>"San Francisco", "keys"=>"<key>", "id"=>"4", "derate"=>"80", "reference_state"=>"California", "cost"=>"0.1", "tilt"=>"20"}
Project Load (0.2ms)  SELECT "projects".* FROM "projects" WHERE "projects"."id" = ? LIMIT 1  [["id", "4"]]
Completed 500 Internal Server Error in 282ms

NameError (uninitialized constant Savon::Request):
app/controllers/projects_controller.rb:1697
app/controllers/projects_controller.rb:1628:in `annual_production'

Rendered /var/lib/gems/1.8/gems/actionpack-3.2.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.6ms)
Rendered /var/lib/gems/1.8/gems/actionpack-3.2.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (1.2ms)
Rendered /var/lib/gems/1.8/gems/actionpack-3.2.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (10.0ms)

Anyone knows what am I doing wrong?

Here is my installed gems list

root@sv-001:/home/user/myapp# gem list

*** LOCAL GEMS ***

actionmailer (3.2.9)
actionpack (3.2.9)
activemodel (3.2.9)
activerecord (3.2.9)
activeresource (3.2.9)
activesupport (3.2.9)
akami (1.2.0)
arel (3.0.2)
builder (3.0.4)
bundler (1.2.2, 1.2.1)
coffee-rails (3.2.2)
coffee-script (2.2.0)
coffee-script-source (1.4.0)
erubis (2.7.0)
execjs (1.4.0)
git (1.2.5)
gyoku (0.4.6)
hike (1.2.1)
httpi (1.1.1)
i18n (0.6.1)
jeweler (1.8.4)
journey (1.0.4)
jquery-rails (2.1.3)
json (1.7.5)
libv8 (3.3.10.4 x86-linux)
mail (2.4.4)
mime-types (1.19)
multi_json (1.3.7)
nokogiri (1.5.5)
nori (1.1.3)
polyglot (0.3.3)
rack (1.4.1)
rack-cache (1.2)
rack-ssl (1.3.2)
rack-test (0.6.2)
rails (3.2.9)
railties (3.2.9)
rake (10.0.2, 10.0.1)
rdoc (3.12)
sass (3.2.3)
sass-rails (3.2.5)
savon (1.2.0)
sprockets (2.2.1)
sqlite3 (1.3.6)
therubyracer (0.10.2)
thor (0.16.0)
tilt (1.3.3)
treetop (1.4.12)
tzinfo (0.3.35)
uglifier (1.3.0)
wasabi (2.5.1)

and here are my ruby and rails versions

root@sv-001:/home/user/myapp# gem -v
1.8.15
root@sv-001:/home/user/myapp# ruby -v
ruby 1.8.7 (2011-06-30 patchlevel 352) [i686-linux]
root@sv-001:/home/user/myapp# rails -v
Rails 3.2.9
root@sv-001:/home/user/myapp# 

Update 1

NoMethodError (undefined method `debug' for :logger:Symbol):
app/controllers/projects_controller.rb:1757:in `yearly_production'
app/controllers/projects_controller.rb:1638:in `annual_production'

Update 2

NoMethodError (undefined method `get_pvwatts' for #<Savon::Client:0xb275c15c>):
app/controllers/projects_controller.rb:1737:in `yearly_production'
app/controllers/projects_controller.rb:1628:in `annual_production'

Update 3

The code that worked for me is the following:

Savon.configure do |c|
   c.log = false
   c.logger = Rails.logger
end

client = Savon::Client.new do
    wsdl.document = "http://pvwatts.nrel.gov/PVWATTS.asmx?WSDL"
end

response = client.request :wsdl, "get_pvwatts" do
  soap.body = req
end

rdata = response.to_hash
rh4games
  • 962
  • 2
  • 15
  • 38

2 Answers2

2

The syntax for Savon has changed since it crossed the 1.x version. You've got the latest version installed.

I investigated the webservice in question using a tool called SoapUI. I highly recommend it while developing SOAP clients. You can create calls out of the tool and can tinker around on the SOAP level before you write your actual source code. For this giving (legacy?) webservice you need to set the SOAPAction explicitely.

I put all of this in a working Ruby script. I didn't use the WSDL. Savon's WSDL support is not complete. The author is working on an improved version. I 'hardcoded' the namespace and the endpoint.

#!ruby

require 'savon'
require 'pp'

Savon.configure do |c|
  c.log = true
  c.pretty_print_xml = true
end

client = Savon::Client.new do
  # wsdl.document = "http://pvwatts.nrel.gov/PVWATTS.asmx?WSDL"
  wsdl.endpoint = "http://pvwatts.nrel.gov/PVWATTS.asmx"
  wsdl.namespace = "http://pvwatts.nrel.gov"
end

begin
  response  = client.request :pvw, "GetPVWATTS" do
    http.headers['SOAPAction'] = '"http://pvwatts.nrel.gov/GetPVWATTS"'
    soap.body = { 'pvw:key' => 'your_secret',
                  'pvw:latitude' => 43,
                  'pvw:longitude' => 280 }
  end
  pp response.to_hash
rescue Savon::SOAP::Fault => error
  print error
end

It doesn't return a valid result on my machine because I'm lacking the authorization code. Let us know whether that helped you to make your next step.

Steffen Roller
  • 3,464
  • 25
  • 43
  • Thanks Steffen for your response. I implemented the changes you suggested and I'm now getting the error reported in Update 1 above. Any idea what's still wrong? Thanks – rh4games Nov 23 '12 at 05:43
  • I think I was too fast to write the logger line. If you haven't implemented a logger method just comment out the line or point to the `Rails.logger` in case you run under Rails. I would generally try to get a small code snippet running before I would integrate it in a Rails application. – Steffen Roller Nov 24 '12 at 23:32
  • Thanks Steffen for your follow up. I re-edited my question and added Update 3 with the code that worked for me. Thanks a lot for your help. – rh4games Nov 25 '12 at 02:27
0

That library is quite old, and it looks like Savon has changed in the past two years. The class in question now appears to be called Savon::SOAP::Request, and it no longer has a log= method. Just from eyeballing the code, I think you can simply delete all references to Savon::Request and you should be fine.

Chuck
  • 234,037
  • 30
  • 302
  • 389
  • Thanks Chuck for your response. I removed all reference to Savon::Request and I'm now getting the error reported in Update 2 above. Any idea what's still wrong? Thanks – rh4games Nov 23 '12 at 05:39