Skip to content

Commit

Permalink
add raw_data (XML) method
Browse files Browse the repository at this point in the history
  • Loading branch information
mateu committed Dec 29, 2010
1 parent 5277c9a commit f374e61
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 19 deletions.
5 changes: 5 additions & 0 deletions Changes
@@ -1,4 +1,9 @@
{{$NEXT}} {{$NEXT}}
Improvements;
- Add raw_data attribute that has the raw XML
- Validate XML before using just in case.
- improve Synopsis



0.01 2010-12-29 09:04:55 America/Denver 0.01 2010-12-29 09:04:55 America/Denver
- Initial Release - Initial Release
56 changes: 40 additions & 16 deletions lib/Weather/Underground/Forecast.pm
Expand Up @@ -3,10 +3,11 @@ use Moose;
use namespace::autoclean; use namespace::autoclean;
use LWP::Simple; use LWP::Simple;
use XML::Simple; use XML::Simple;
use XML::Validate;


use Data::Dumper::Concise; use Data::Dumper::Concise;


our $VERSION = '0.01'; our $VERSION = '0.02';


=head1 Name =head1 Name
Expand All @@ -22,9 +23,9 @@ Weather::Underground::Forecast - Simple API to Weather Underground Forecast Data
); );
Where the $location can be: Where the $location can be:
* city,state (Bloomington,IN) * 'city,state' Example: location => 'Bloomington,IN'
* zip code (47401) * zip_code Example: location => 47401
* latitude,longitude (46,-113) * 'latitude,longitude' Example: location => '46,-113'
my ($highs, $lows) = $forecast->temperatures; my ($highs, $lows) = $forecast->temperatures;
Expand All @@ -49,6 +50,11 @@ has 'data' => (
isa => 'ArrayRef[HashRef]', isa => 'ArrayRef[HashRef]',
lazy_build => 1, lazy_build => 1,
); );
has 'raw_data' => (
is => 'rw',
isa => 'Str',
lazy_build => 1,
);
has 'source_URL' => ( has 'source_URL' => (
is => 'ro', is => 'ro',
isa => 'Any', isa => 'Any',
Expand All @@ -70,7 +76,7 @@ after 'set_location' => sub {
Get the high and low temperatures for the number of days specified. Get the high and low temperatures for the number of days specified.
Returns: Array of two ArrayRefs being the high and low temperatures Returns: Array of two ArrayRefs being the high and low temperatures
Example: my ($highs, $lows) = $wunder->forecast_temperaures; Example: my ($highs, $lows) = $wunder->temperaures;
=cut =cut


Expand All @@ -90,7 +96,7 @@ sub highs {


my $key1 = 'high'; my $key1 = 'high';
my $key2 = $self->temperature_units; my $key2 = $self->temperature_units;
return $self->get_forecast_data_by_two_keys( $key1, $key2 ); return $self->_get_forecast_data_by_two_keys( $key1, $key2 );
} }


=head2 lows =head2 lows
Expand All @@ -104,22 +110,24 @@ sub lows {


my $key1 = 'low'; my $key1 = 'low';
my $key2 = $self->temperature_units; my $key2 = $self->temperature_units;
return $self->get_forecast_data_by_two_keys( $key1, $key2 ); return $self->_get_forecast_data_by_two_keys( $key1, $key2 );
} }


=head2 precipitation =head2 precipitation
Get an ArrayRef[Int] of the forecasted chance of precipitation. Get an ArrayRef[Int] of the forecasted chance of precipitation.
Example: my $chance_of_precip = $wunder->precipitation;
=cut =cut


sub precipitation { sub precipitation {
my $self = shift; my $self = shift;


return $self->get_forecast_data_by_one_key('pop'); return $self->_get_forecast_data_by_one_key('pop');
} }


=head2 get_forecast_data_by_one_key =head2 _get_forecast_data_by_one_key
Get the values for a single forecast metric that is Get the values for a single forecast metric that is
only one key deep. An examples is: 'pop' (prob. of precip.) only one key deep. An examples is: 'pop' (prob. of precip.)
Expand All @@ -129,20 +137,20 @@ the exact data structure and keys available.
=cut =cut


sub get_forecast_data_by_one_key { sub _get_forecast_data_by_one_key {
my ( $self, $key ) = @_; my ( $self, $key ) = @_;


return [ map { $_->{$key} } @{ $self->data } ]; return [ map { $_->{$key} } @{ $self->data } ];
} }


=head2 get_forecast_data_by_two_keys =head2 _get_forecast_data_by_two_keys
Like the one_key method above but for values that are Like the one_key method above but for values that are
two keys deep in the data structure. two keys deep in the data structure.
=cut =cut


sub get_forecast_data_by_two_keys { sub _get_forecast_data_by_two_keys {
my ( $self, $key1, $key2 ) = @_; my ( $self, $key1, $key2 ) = @_;


return [ map { $_->{$key1}->{$key2} } @{ $self->data } ]; return [ map { $_->{$key1}->{$key2} } @{ $self->data } ];
Expand All @@ -158,16 +166,32 @@ sub _query_URL {
sub _build_data { sub _build_data {
my $self = shift; my $self = shift;


my $content = get( $self->_query_URL );
die "Couldn't get URL: ", $self->_query_URL unless defined $content;

my $xml = XML::Simple->new; my $xml = XML::Simple->new;
my $data_ref = $xml->XMLin($content); my $data_ref = $xml->XMLin( $self->raw_data );
my $forecasts = $data_ref->{simpleforecast}->{forecastday}; my $forecasts = $data_ref->{simpleforecast}->{forecastday};


return $forecasts; return $forecasts;
} }


sub _build_raw_data {
my $self = shift;

my $content = get( $self->_query_URL );
die "Couldn't get URL: ", $self->_query_URL unless defined $content;

my $xml_validator = new XML::Validate( Type => 'LibXML' );
if ( !$xml_validator->validate($content) ) {
my $intro = "Document is invalid\n";
my $message = $xml_validator->last_error()->{message};
my $line = $xml_validator->last_error()->{line};
my $column = $xml_validator->last_error()->{column};
die "Error: $intro $message at line $line, column $column";
}

# return and set attribute to raw xml when we make it this far.
return $content;
}

sub _build_source_URL { sub _build_source_URL {
my $self = shift; my $self = shift;
return return
Expand Down
6 changes: 3 additions & 3 deletions t/basic.t
Expand Up @@ -6,7 +6,7 @@ use LWP::Simple;
use Data::Dumper::Concise; use Data::Dumper::Concise;


my $wunder_forecast = Weather::Underground::Forecast->new( my $wunder_forecast = Weather::Underground::Forecast->new(
location => 'Missoula,MT', location => '59802',
temperature_units => 'fahrenheit', # or 'celsius' temperature_units => 'fahrenheit', # or 'celsius'
); );


Expand All @@ -18,8 +18,8 @@ SKIP:


# Test internet connection # Test internet connection
my $source_URL = $wunder_forecast->_query_URL; my $source_URL = $wunder_forecast->_query_URL;
my $content = get($source_URL); my $head = head($source_URL);
skip( 'Skipping live test using Internet', 3 ) if !$content; skip( 'Skipping live test using Internet', 3 ) if !$head;


my ( $highs, $lows ) = $wunder_forecast->temperatures; my ( $highs, $lows ) = $wunder_forecast->temperatures;
my $chance_of_precip = $wunder_forecast->precipitation; my $chance_of_precip = $wunder_forecast->precipitation;
Expand Down

0 comments on commit f374e61

Please sign in to comment.