[QUIZ] Current Temperature (#68)

This is also my first Ruby Quiz submission.

I was going to neglect this one as well, but I got to thinking how nicely lazy.rb might work with some web services. Once someone actually came across a working SOAP service (xmethods lists quite a few that are iffy),
I decided to give it a go.

Thanks =)

Jeff

#!/usr/bin/env ruby

require 'lazy'
require 'soap/wsdlDriver'
require 'rexml/document'
$-w = nil

$wsdl_loc = "http://www.webservicex.net/globalweather.asmx?WSDL"
class WeatherState
   def initialize(city, country)
     stub = SOAP::WSDLDriverFactory.new($wsdl_loc).create_rpc_driver

     @keep_me = promise do
       conditions = stub.getWeather(:CityName =>city, :CountryName=>country)
       data = REXML::Document.new(conditions.getWeatherResult.gsub(/<\?.*?>\n/, ''))
       { :temp => data.elements["//Temperature"].text, loc => data.elements["//Location"].text }
       end
     end

     def temp
       demand(@keep_me)[:temp]
     end

     def loc
       demand(@keep_me)[:loc]
     end
end

if ARGV.length != 2
   abort("Usage: weather.rb city country")
end

# Create Weather Object
weatherProxy = WeatherState.new(ARGV[0], ARGV[1])
puts "Location: " + weatherProxy.loc
puts "Current Temp: " + weatherProxy.temp.strip

Hal Fulton <hal9000@hypermetrics.com> writes:

But what is this "Outside" you speak of? I don't think I have
that installed...

You need to "require 'pants'" first.

I've been lurking for a bit over 2 months as I've been reading
here and there about Ruby.

Anyway my first quiz submission (which is also my second Ruby script):

Let me be one of the first to welcome you then! Script looks great
for the second on, by the way.

Thanks! It's lacking a bunch of error checking, input validation and the
like, but it suffices for now. And I can look at some of the other entries
to get some of those details.

The quiz is a great idea.

Regards,
Harley Pebley

Cool. I'd tried to do something like that, but couldn't quite get it to
work (because of the yahoo redirect). Looking at your code helped me
figure it out. I looked at net/http and then more at what open-uri
provides. Lo and behold it provides some meta-data that helps with the
redirect problem. Anyways thanks gordon! I added my now fixed function
below.

-----Jay Anderson

require 'rexml/document'
require 'open-uri'

LOC_MATCH = /\/forecast\/([^.]+)\.html/

#Searches Yahoo and returns an array of location ids
def yahoo_loc_search(loc)
    return [loc] if loc =~ /\d/ #places usually don't have numbers in
their names
    locs =

open("Fremont, United States - Weather Forecasts | Maps | News - Yahoo Weather)
do |http|
        return [$1] if http.base_uri.to_s =~ LOC_MATCH
        http.each {|line| locs << $1 if line =~ LOC_MATCH }
    end
    locs
end

#Returns a hash containing the location and temperature information
#Accepts US zip codes or Yahoo location id's
def yahoo_weather_query(loc_ids, units)
    weather =
    loc_ids.each do |l|
        h = {}

open("http://xml.weather.yahoo.com/forecastrss?p=#{l}&u=#{units\}&quot;\) do

http>

            response = http.read
            doc = REXML::Document.new(response)
            channel = doc.root.elements['channel']
            title = channel.elements['title'].text
            if title !~ /Error/ then
                location = channel.elements['yweather:location']
                h[:city] = location.attributes["city"]
                h[:region] = location.attributes["region"]
                h[:country] = location.attributes["country"]
                h[:temp] =
channel.elements["item"].elements["yweather:condition"].attributes["temp"]
                weather << h
            end
        end
    end
    weather
end

if ARGV.length < 1 then
    puts "usage: #$0 <location> [f|c]"
    exit
end
loc_id = ARGV[0]
units = (ARGV[1] || 'f').downcase
units = (units =~ /^(f|c)$/) ? units : 'f'

loc_ids = yahoo_loc_search(loc_id)
weather_info = yahoo_weather_query(loc_ids, units)

puts "No matches found" if weather_info.size == 0

weather_info.each do |w|
    city = w[:city]
    region = w[:region]
    country = w[:country]
    temp = w[:temp]

    final_loc = "#{city}, #{region}#{', ' if region!="" and
country!=""}#{country}"
    puts "The temperature in #{final_loc} is #{temp} degrees
#{units.upcase}"
end

George Ogata <g_ogata@optushome.com.au> writes:

Hal Fulton <hal9000@hypermetrics.com> writes:

But what is this "Outside" you speak of? I don't think I have
that installed...

You need to "require 'pants'" first.

Alternatively, require 'rubypants' :wink:

···

--
Christian Neukirchen <chneukirchen@gmail.com> http://chneukirchen.org