earth_tools 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ # Changelog
2
+ Find the changes below for each version.
3
+
4
+ ## 0.1.0
5
+ * Add cache handling
6
+
7
+ ## 0.0.1
8
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,136 @@
1
+ # earth_tools
2
+ [![Gem Version](https://badge.fury.io/rb/earth_tools.png)](http://badge.fury.io/rb/earth_tools) [![Dependency Status](https://gemnasium.com/mckramer/earth_tools.png?travis)](https://gemnasium.com/mckramer/earth_tools) [![Code Climate](https://codeclimate.com/github/mckramer/earth_tools.png)](https://codeclimate.com/github/mckramer/earth_tools) [![Build Status](https://secure.travis-ci.org/mckramer/earth_tools.png?branch=master)](http://travis-ci.org/mckramer/earth_tools)
3
+
4
+ `earth_tools` is a wrapper around the wonderful [earthtools.org webservices](http://www.earthtools.org/webservices.htm), which allows you to determine the sea level height, time zone, and surise/sunset times from a set of coordinates.
5
+
6
+ ## Compatibility
7
+
8
+ * Supports Ruby 1.9.2 & 1.9.3
9
+
10
+ Will be testing on other versions in the future.
11
+
12
+ ## Installation instructions
13
+
14
+ Add to your Gemfile:
15
+
16
+ `gem 'earth_tools'`
17
+
18
+ and then bundle your gemfile:
19
+
20
+ `bundle install`
21
+
22
+ and you are done!
23
+
24
+ ## API
25
+
26
+ The run down of the 3 major functions available
27
+
28
+ ### Time zone
29
+
30
+ # API
31
+ result = EarthTools.time_zone(latitude, longitude)
32
+ # Example
33
+ result = EarthTools.time_zone(40.71417, -74.00639) # New York City
34
+ result.iso_time # => 2012-06-14 12:56:40 -0500
35
+ result.utc_offset # => -5
36
+ result.utc_time # => 2012-06-14 17:56:40 +0000
37
+
38
+ ### Height above/below sea level
39
+
40
+ # API
41
+ result = EarthTools.height(latitude, longitude)
42
+ # Example
43
+ result = EarthTools.height(52.4822, -1.8946) # Birmingham, AL
44
+ result.meters # => 141
45
+ result.feet # => 462.6
46
+ result.height # => 462.6 (when EarthTools::Configuration.units is set to :english units)
47
+
48
+ ### Sunrise/sunset times
49
+
50
+ # API
51
+ result = EarthTools.sunrise_sunset(latitude, longitude, month, day, timezone, dst)
52
+ # Example
53
+ result = EarthTools.sunrise_sunset(40.71417, -74.00639, 12, 4, -5, 0) # New York City, December 4th
54
+ result.sunrise # => 2012-12-04 07:05:50 -0500
55
+ result.sunset # => 2012-12-04 16:26:59 -0500
56
+
57
+ ### Configuration
58
+
59
+ # Configure block (set to defaults)
60
+ EarthTools.configure do |config|
61
+ config.always_raise = [] # Add any errors that you would like to be custom handled, see "Error handling" section below
62
+ config.cache = nil # Cache object (see Caching section for what methods are required)
63
+ config.cache_prefix = "earth_tools:" # Prefix to use for cache keys
64
+ config.timeout = 3 # Timeout in seconds
65
+ config.units = :english # Also, can specify :metric
66
+ end
67
+ # Static call
68
+ EarthTools::Configuration.timeout = 5 # Set timeout to 5 seconds
69
+
70
+ ## Earth Tool API restrictions
71
+
72
+ ### Limits
73
+
74
+ Earth Tools imposes some [usage restrictions](http://www.earthtools.org/webservices.htm#usage) that are duplicated below (these restrictions may not be kept up-to-date, so please check the website):
75
+
76
+ 1. You *must not* make more than 1 (one) request per second to these webservices.
77
+ 2. You *must* cache results if you believe that you will need to make another identical request within any 24-hour period.
78
+ 3. You *must* delete any cached data when you no longer need it and in any case after 14 days. You should then make a new request for the data in line with the previous two rules. If you wish to keep access to data I am able to license the data for use in this way.
79
+
80
+ ### Caching
81
+
82
+ It is recommended to cache retrieved data when relying on an external service. You can configure a cache store:
83
+
84
+ EarthTools::Configuration.cache = Redis.new
85
+ EarthTools::Configuration.cache_prefix = "..." # Provide a custom cache prefix, defaults to 'earth_tools:'
86
+
87
+ The cache store can be any object that supports the following methods:
88
+
89
+ <table>
90
+ <tr>
91
+ <th>Method</th><th>Description</th><th>Examples</th>
92
+ </tr>
93
+ <tr>
94
+ <td><code>#[](key)</code></td><td>Retrieves a value by with the key</td><td></td>
95
+ </tr>
96
+ <tr>
97
+ <td><code>#[]=(key, value)</code></td><td>Stores a value with the key</td><td></td>
98
+ </tr>
99
+ <tr>
100
+ <td><code>#keys</code></td><td>Retrieves all keys</td><td></td>
101
+ </tr>
102
+ <tr>
103
+ <td>
104
+ <div><code>#del</code></div>
105
+ <div>or</div>
106
+ <div><code>#delete</code></div>
107
+ </td>
108
+ <td>Deletes a key</td>
109
+ <td></td>
110
+ </tr>
111
+ </table>
112
+
113
+ If you need to expire cached content:
114
+
115
+ EarthTools.cache.expire("http://...") # Expire cached result for a URL
116
+ EarthTools.cache.expire(:all) # Expire all cached results
117
+
118
+ There is no need to include the prefix when passing a URL to be expired. Expiring `:all` will only expire keys with the configured prefix (won't kill every entry in your key/value store).
119
+
120
+ ## Error handling
121
+
122
+ By default Earth Tools will rescue any exceptions raised by calls to the webservice and return an empty array (using warn() to inform you of the error). You can override this and implement custom error handling for certain exceptions by using the `:always_raise` option:
123
+
124
+ EarthTools::Configuration.always_raise = [SocketError, TimeoutError]
125
+
126
+ ## Issues & contributing
127
+
128
+ No outstanding issues right now. Please post any issues to the [issues queue on github](https://github.com/mckramer/earth_tools/issues).
129
+
130
+ ## Future
131
+
132
+ I would love to see this functionality brought into the `geocoder` gem or similar in the future.
133
+
134
+ # License and attributions
135
+
136
+ This gem's structure and design borrows heavily from `geocoder`, so thanks to its author. Find me on twitter [@maxckramer](https://twitter.com/maxckramer).
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+ require 'bundler'
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ require 'rake/testtask'
7
+
8
+ desc 'Default: run unit tests'
9
+ task :default => :test
10
+
11
+ desc 'Run all tests'
12
+ task :test_all => [:test, :integration_test]
13
+
14
+ desc 'Run unit tests'
15
+ Rake::TestTask.new(:test) do |t|
16
+ t.libs << 'test'
17
+ t.pattern = 'test/*_test.rb'
18
+ t.verbose = true
19
+ end
20
+
21
+ desc 'Run integration tests (require to set proxy in test_helper.rb if needed)'
22
+ Rake::TestTask.new(:integration_test) do |t|
23
+ t.libs << 'test'
24
+ t.pattern = 'test/integration/*_test.rb'
25
+ t.verbose = true
26
+ end
@@ -0,0 +1,80 @@
1
+ module EarthTools
2
+
3
+ ##
4
+ # The Earth Tools cache wrapper.
5
+ #
6
+ # Must respond to:
7
+ # -> [] -- read
8
+ # -> []= -- write
9
+ # -> del -- delete
10
+ # -> keys -- list of keys
11
+ #
12
+ class Cache
13
+
14
+ ##
15
+ # @constructor
16
+ def initialize(store, prefix)
17
+ @store = store
18
+ @prefix = prefix
19
+ end
20
+
21
+ ##
22
+ # Read from the cache.
23
+ # @return the object saved in the cache
24
+ def [](url)
25
+ @store[key_for(url)]
26
+ end
27
+
28
+ ##
29
+ # Write to the cache.
30
+ def []=(url, value)
31
+ @store[key_for(url)] = value
32
+ end
33
+
34
+ ##
35
+ # Delete cache entry for given URL,
36
+ # or pass <tt>:all</tt> to clear all URLs.
37
+ def expire(url)
38
+ if url == :all
39
+ urls.each{ |u| expire(u) }
40
+ else
41
+ @store.send(@store.respond_to?(:del) ? :del : :delete, key_for(url))
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ attr_reader :prefix, :store
48
+
49
+ ##
50
+ # Cache key for a given URL.
51
+ # @return [String] the cache key
52
+ def key_for(url)
53
+ [@prefix, url].join
54
+ end
55
+
56
+ ##
57
+ # Array of keys with the currently configured prefix
58
+ # that have non-nil values.
59
+ # @return [Array] the list of keys
60
+ def keys
61
+ @store.keys.select{ |k| k.match /^#{@prefix}/ and cleave(@store[k]) }
62
+ end
63
+
64
+ ##
65
+ # Array of cached URLs.
66
+ # @return [Array] the list of cached URLs
67
+ def urls
68
+ keys.map{ |k| k[/^#{@prefix}(.*)/, 1] }
69
+ end
70
+
71
+ ##
72
+ # Convert empty string to nil.
73
+ # (Some key/value stores return empty string instead of nil.)
74
+ # @return [Object, nil] the object or nil
75
+ def cleave(value)
76
+ value == "" ? nil : value
77
+ end
78
+
79
+ end
80
+ end
@@ -1,9 +1,10 @@
1
1
  require 'singleton'
2
2
  module EarthTools
3
3
 
4
- ## This method can be used to change some functional aspects, like,
5
- # the geocoding service provider, or the units of calculations.
6
- # Please see {include:Configuration}
4
+ ##
5
+ # This method can be used to change some functional aspects, like
6
+ # the cache client or the units of calculations.
7
+ # See {include:Configuration}.
7
8
  def self.configure(&block)
8
9
  if block_given?
9
10
  block.call(Configuration.instance)
@@ -12,9 +13,12 @@ module EarthTools
12
13
  end
13
14
  end
14
15
 
16
+ ##
17
+ # The singleton that maintains the configuration settings for plugin.
15
18
  class Configuration
16
19
  include Singleton
17
20
 
21
+ # The available options
18
22
  OPTIONS = [
19
23
  :timeout,
20
24
  :proxy,
@@ -29,24 +33,24 @@ module EarthTools
29
33
  def initialize # :nodoc
30
34
  set_defaults
31
35
  end
32
-
33
- # This method will set the configuration options to the default values
36
+
37
+ ##
38
+ # Sets the configuration options to the default values
34
39
  def set_defaults
35
- @timeout = 3 # geocoding service timeout (secs)
40
+ @timeout = 3 # Geocoding service timeout (secs)
36
41
  @proxy = nil # HTTP proxy server (user:pass@host:port)
37
- @cache = nil # cache object (must respond to #[], #[]=, and #keys)
38
- @cache_prefix = "earth_tools:" # prefix (string) to use for all cache keys
39
-
40
- # exceptions that should not be rescued by default
42
+ @cache = nil # Cache object (must respond to #[], #[]=, #keys, and #delete)
43
+ @cache_prefix = "earth_tools:" # Prefix (string) to use for all cache keys
44
+
45
+ # Exceptions that should not be rescued by default
41
46
  # (if you want to implement custom error handling);
42
47
  # supports SocketError and Timeout::Error
43
48
  @always_raise = []
44
-
45
- # calculation options
49
+
50
+ # Calculation options
46
51
  @units = :english # :metric or :english
47
52
  end
48
53
 
49
-
50
54
  # Delegates getters and setters for all configuration settings,
51
55
  # and +set_defaults+ to the singleton instance.
52
56
  instance_eval(OPTIONS.map do |option|
@@ -55,15 +59,15 @@ module EarthTools
55
59
  def #{o}
56
60
  instance.#{o}
57
61
  end
58
-
62
+
59
63
  def #{o}=(value)
60
64
  instance.#{o} = value
61
65
  end
62
66
  EOS
63
67
  end.join("\n\n"))
64
-
68
+
65
69
  class << self
66
- # This method will set the configuration options to the default values
70
+ # Sets the configuration options to the default values
67
71
  def set_defaults
68
72
  instance.set_defaults
69
73
  end
@@ -1,29 +1,27 @@
1
1
  module EarthTools
2
-
2
+
3
+ ##
4
+ # Common error, extended by more specific errors.
3
5
  class Error < StandardError
4
6
  end
5
-
7
+
6
8
  ##
7
- #
8
- #
9
+ # Error thrown when there is an issue setting/getting configuration.
9
10
  class ConfigurationError < Error
10
11
  end
11
-
12
+
12
13
  ##
13
- #
14
- #
14
+ # Error thrown when too many requests have been made to EarthTools service in.
15
15
  class OverQueryLimitError < Error
16
16
  end
17
17
 
18
18
  ##
19
- #
20
- #
19
+ # Error thrown when invalid input is provided to the service when querying.
21
20
  class InvalidInputError < Error
22
21
  end
23
22
 
24
23
  ##
25
- #
26
- #
24
+ # Error thrown when unsupported operation is attempted on the service.
27
25
  class UnsupportedOperationError < Error
28
26
  end
29
27
 
@@ -6,96 +6,97 @@ module EarthTools
6
6
  module Lookup
7
7
 
8
8
  ##
9
- #
9
+ # Base lookup object.
10
10
  #
11
11
  class Base
12
12
 
13
13
  ##
14
14
  # Query the Earth Tools service and return a EarthTools::Result object.
15
- # @return [EarthTools::Result, nil]
15
+ # @return [EarthTools::Result, nil] the results object
16
16
  def search(*options)
17
17
  begin
18
18
  Timeout::timeout(EarthTools::Configuration.timeout) do
19
- raw_results = retrieve(query(options))
20
- parse_results(raw_results, :xml)
19
+ uri = query(options)
20
+ if cache && results = cache[uri]
21
+ # Boom, cached
22
+ else
23
+ # Not cached, so go get the data
24
+ raw_results = retrieve(uri)
25
+ results = parse_xml(raw_results)
26
+ # Save results to cache, if available
27
+ cache(uri, results) if cache && results
28
+ end
29
+ results
21
30
  end
22
31
  rescue Timeout::Error => err
23
32
  raise_error(err) or warn "Earth Tools API took too long to respond. See EarthTools::Configuration to set the timeout time (currently set to #{EarthTools::Configuration.timeout} seconds)."
24
33
  end
25
34
  end
26
-
35
+
27
36
  private
28
37
 
29
38
  ##
30
- # The base URL for the web service endpoint (protocol and server)
39
+ # The base URL for the web service endpoint (protocol and server).
31
40
  # @return [String] the base URL
32
41
  def base_service_url
33
42
  "http://www.earthtools.org"
34
43
  end
35
44
 
36
45
  ##
37
- # URL to use for querying the geocoding engine.
38
- # @return [String]
39
- def query(*options)
40
- base_service_url + query_base + options.join('/')
46
+ # Gets the cache.
47
+ # @return [EarthTools::Cache] the cache
48
+ def cache
49
+ EarthTools::Configuration.cache
41
50
  end
42
51
 
43
52
  ##
44
- # Parse results depending on if xml or json
45
- #
46
- def parse_results(raw_results, type)
47
- case type
48
- when :xml
49
- parse_xml(XmlSimple.xml_in( raw_results, { 'ForceArray' => false } ))
50
- when :json
51
- raise UnsupportedOperationError, "JSON is not supported"
52
- end
53
+ # URL to use for querying the geocoding engine.
54
+ # @return [String] the url
55
+ def query(*options)
56
+ base_service_url + query_base + options.join('/')
57
+ # ([base_service_url, query_base] + options).join('/')
53
58
  end
54
59
 
55
60
  ##
56
- # Handle XML results by validating them
57
- #
58
- def parse_xml(xml)
61
+ # Handle XML results by validating them.
62
+ # @param raw_xml the xml to parse
63
+ # @return [Height, SunriseSunset, TimeZone] the result
64
+ def parse_xml(raw_xml)
65
+ xml = XmlSimple.xml_in( raw_xml, { 'ForceArray' => false } )
59
66
  if xml['location']
60
67
  result_class.new(xml)
61
68
  else
62
69
  warn "Invalid request."
63
- puts xml
64
70
  end
65
71
  end
66
72
 
67
73
  ##
68
- # Handles running query
69
- #
74
+ # Handles running query.
75
+ # @return [xml] the results
70
76
  def retrieve(query)
71
77
  RestClient.proxy = EarthTools::Configuration.proxy if EarthTools::Configuration.proxy
72
- #puts "Trying to connect to endpoint(#{query})"
73
- #puts "Using proxy (#{RestClient.proxy})" if RestClient.proxy
74
78
  RestClient.get query
75
79
  end
76
80
 
77
81
  ##
78
82
  # Raise exception if configuration specifies it should be raised.
79
- # Return false if exception not raised.
80
- #
83
+ # @return [boolean] false, if exception not raised
81
84
  def raise_error(error, message = nil)
82
- if EarthTools::Configuration.always_raise.include?( error.is_a?(Class) ? error : error.class )
83
- raise error, message
84
- else
85
- false
86
- end
85
+ raise error, message if EarthTools::Configuration.always_raise.include?( error.is_a?(Class) ? error : error.class )
86
+ false
87
87
  end
88
88
 
89
89
  ##
90
- #
91
- #
90
+ # The base of the query for the function.
91
+ # @return [String] the base of the query
92
+ # @throws NotImplementedError when child class does not implement method
92
93
  def query_base
93
94
  raise NotImplementedError
94
95
  end
95
96
 
96
97
  ##
97
- #
98
- #
98
+ # The class for the result.
99
+ # @return [EarthTools::Result::Height, EarthTools::Result::SunriseSunset, EarthTools::Result::TimeZone] the result class
99
100
  def result_class
100
101
  EarthTools::Result.const_get(self.class.to_s.split(":").last)
101
102
  end
@@ -4,12 +4,12 @@ require 'earth_tools/result/height'
4
4
  module EarthTools::Lookup
5
5
 
6
6
  ##
7
- #
7
+ # The height lookup.
8
8
  #
9
9
  class Height < Base
10
10
 
11
11
  private
12
-
12
+
13
13
  def query_base
14
14
  "/height/"
15
15
  end
@@ -2,10 +2,13 @@ require 'earth_tools/lookup/base'
2
2
  require 'earth_tools/result/sunrise_sunset'
3
3
 
4
4
  module EarthTools::Lookup
5
+
6
+ ##
7
+ # The Sunrise/Sunset lookup.
5
8
  class SunriseSunset < Base
6
9
 
7
10
  private
8
-
11
+
9
12
  def query_base
10
13
  "/sun/"
11
14
  end
@@ -2,10 +2,14 @@ require 'earth_tools/lookup/base'
2
2
  require 'earth_tools/result/time_zone'
3
3
 
4
4
  module EarthTools::Lookup
5
+
6
+ ##
7
+ # The Time Zone lookup.
8
+ #
5
9
  class TimeZone < Base
6
10
 
7
11
  private
8
-
12
+
9
13
  def query_base
10
14
  "/timezone/"
11
15
  end
@@ -2,48 +2,50 @@ module EarthTools
2
2
  module Result
3
3
 
4
4
  ##
5
- #
5
+ # The base result object.
6
+ #
7
+ # Contains shared domain fields. Extended by different results.
6
8
  #
7
9
  class Base
8
10
  attr_accessor :data
9
-
11
+
10
12
  ##
11
13
  # Takes a hash of result data from a parsed Google result document.
12
- #
14
+ # @param [Object] the
13
15
  def initialize(data)
14
16
  @data = data
15
17
  end
16
-
18
+
17
19
  ##
18
20
  # Get the geographical location
19
- # @returns [Array] a two-element array: [latitude, longitude]
21
+ # @return [Array] a two-element array: [latitude, longitude]
20
22
  def location
21
23
  [latitude, longitude]
22
24
  end
23
-
25
+
24
26
  ##
25
27
  # Get the latitude
26
28
  # See {http://en.wikipedia.org/wiki/Latitude}.
27
- # @returns [Float] the latitude
29
+ # @return [Float] the latitude
28
30
  def latitude
29
31
  @data['latitude'].to_f
30
32
  end
31
-
33
+
32
34
  ##
33
35
  # Get the longitude
34
36
  # See {http://en.wikipedia.org/wiki/Longitude}.
35
- # @returns the longitude
37
+ # @return the longitude
36
38
  def longitude
37
39
  @data['longitude'].to_f
38
40
  end
39
41
 
40
42
  ##
41
43
  # The version of the response format
42
- # @returns [Float] the version
44
+ # @return [Float] the version
43
45
  def version
44
46
  @data['version'].to_f
45
47
  end
46
-
48
+
47
49
  end
48
50
  end
49
51
  end
@@ -4,10 +4,9 @@ require 'earth_tools/configuration'
4
4
  module EarthTools::Result
5
5
 
6
6
  ##
7
- #
8
- #
7
+ # The height result.
9
8
  class Height < Base
10
-
9
+
11
10
  ##
12
11
  # Returns height based on unit requested in configuration
13
12
  # @return [float]
@@ -3,17 +3,16 @@ require 'earth_tools/result/base'
3
3
  module EarthTools::Result
4
4
 
5
5
  ##
6
- # The sunrise/sunset result object
7
- #
6
+ # The sunrise/sunset result.
8
7
  class SunriseSunset < Base
9
-
8
+
10
9
  ##
11
10
  # The date of the sunrise/sunset data as a hash
12
11
  # @return [Hash] Hash containing year, month, and day as integers
13
12
  def date
14
13
  { :year => Time.now.year, :month => @data['date']['month'].to_i, :day => @data['date']['day'].to_i }
15
14
  end
16
-
15
+
17
16
  ##
18
17
  # The sunrise time
19
18
  # @return [Time] the sunrise time
@@ -3,10 +3,11 @@ require 'earth_tools/result/base'
3
3
  module EarthTools::Result
4
4
 
5
5
  ##
6
+ # The Time Zone result.
6
7
  #
7
- #
8
+ # @see http://www.earthtools.org/webservices.htm#timezone
8
9
  class TimeZone < Base
9
-
10
+
10
11
  ##
11
12
  # Whether or not the {#local_time} and {#iso_time} is currently in DST. If they do, the value of this element will be 'True'. If they do not, the value will be 'False'. If it can't be determined whether or not daylight saving time should be used, the value will be 'Unknown'.
12
13
  # @return [String] 'True' || 'False' || 'Unknown'
@@ -42,7 +43,7 @@ module EarthTools::Result
42
43
  def local_time
43
44
  iso_time
44
45
  end
45
-
46
+
46
47
  ##
47
48
  # The number of hours offset from UTC disregarding any correction for daylight saving time
48
49
  # See {http://en.wikipedia.org/wiki/UTC_offset}.
@@ -50,7 +51,7 @@ module EarthTools::Result
50
51
  def utc_offset
51
52
  @data['offset'].to_i
52
53
  end
53
-
54
+
54
55
  ##
55
56
  # The nautical suffix for the time zone
56
57
  # See {http://en.wikipedia.org/wiki/Nautical_time}
@@ -1,4 +1,4 @@
1
1
  module EarthTools
2
2
  # The gem version
3
- VERSION = "0.0.1"
3
+ VERSION = "0.1.0"
4
4
  end
data/lib/earth_tools.rb CHANGED
@@ -4,30 +4,24 @@
4
4
  #
5
5
  module EarthTools
6
6
  extend self
7
-
7
+
8
8
  ##
9
9
  # Retrieve for time zone based on latitude and longitude.
10
- #
11
- # @returns [EarthTools::Result::TimeZone]
12
- #
10
+ # @returns [EarthTools::Result::TimeZone] the time zone result
13
11
  def time_zone(latitude, longitude)
14
12
  get_lookup(:time_zone).search(latitude, longitude) if valid_input?(latitude, longitude)
15
13
  end
16
14
 
17
15
  ##
18
- # Retrieve the sunrise & sunset values
19
- #
20
- # @returns [EarthTools::Result::SunriseSunset]
21
- #
16
+ # Retrieve the sunrise & sunset values.
17
+ # @return [EarthTools::Result::SunriseSunset] the sunrise/sunset result
22
18
  def sunrise_sunset(latitude, longitude, month, day, timezone = 99, dst = false)
23
19
  get_lookup(:sunrise_sunset).search(latitude, longitude, day, month, timezone, dst ? 1 : 0)
24
20
  end
25
21
 
26
22
  ##
27
- # Retrieve the land height for a given latitude and longitude
28
- #
29
- # @returns [EarthTools::Result::Height]
30
- #
23
+ # Retrieve the land height for a given latitude and longitude.
24
+ # @return [EarthTools::Result::Height] the height result
31
25
  def height(latitude, longitude)
32
26
  get_lookup(:height).search(latitude, longitude)
33
27
  end
@@ -36,7 +30,7 @@ module EarthTools
36
30
 
37
31
  ##
38
32
  # Retrieve a lookup object from the store.
39
- #
33
+ # @return [? extends EarthTools::Lookup::Base]
40
34
  def get_lookup(name)
41
35
  @lookups = {} unless defined?(@lookups)
42
36
  @lookups[name] = spawn_lookup(name) unless @lookups.include?(name)
@@ -45,7 +39,7 @@ module EarthTools
45
39
 
46
40
  ##
47
41
  # Spawn a lookup of the given name.
48
- #
42
+ # @return [? extends EarthTools::Lookup::Base] new lookup helper
49
43
  def spawn_lookup(name)
50
44
  name = name.to_s
51
45
  require "earth_tools/lookup/#{name}"
@@ -54,36 +48,36 @@ module EarthTools
54
48
  end
55
49
 
56
50
  ##
57
- # Validates input
58
- #
51
+ # Validates input.
52
+ # @return [Boolean] true, if coordinates are valid
59
53
  def valid_input?(latitude, longitude)
60
54
  coordinates?(latitude, longitude)
61
55
  end
62
56
 
63
57
  ##
64
- # Validates input
65
- #
58
+ # Validates input.
59
+ # @return [Boolean] true, if all values are valid
66
60
  def valid_full_input?(latitude, longitude, day, month, timezone, dst)
67
61
  coordinates?(latitude, longitude) && !blank?(day) && !blank(month) && !blank?(timezone) && !blank?(dst)
68
62
  end
69
63
 
70
64
  ##
71
- # Validates a pair of coordinates
72
- #
65
+ # Validates a pair of coordinates.
66
+ # @return [Boolean] true, if latitute and longitude are (sort of) valid coordinates
73
67
  def coordinates?(latitude, longitude)
74
68
  coordinate?(latitude) && coordinate?(longitude)
75
69
  end
76
70
 
77
71
  ##
78
- # Determine if given value is a coordinate
79
- #
72
+ # Determine if given value is a coordinate.
73
+ # @return [Boolean] true, if given value is a coordinate
80
74
  def coordinate?(value)
81
75
  !! value.to_f
82
76
  end
83
77
 
84
78
  ##
85
- # Determine if given value is blank
86
- #
79
+ # Determine if given value is blank.
80
+ # @return [Boolean] true, if value is nil or empty
87
81
  def blank?(value)
88
82
  value.nil? || value.to_s.empty?
89
83
  end
@@ -0,0 +1,47 @@
1
+ # encoding: utf-8
2
+
3
+ require 'test_helper'
4
+ require 'earth_tools'
5
+ require 'earth_tools/cache'
6
+
7
+ ##
8
+ # Tests for the Cache.
9
+ class CacheTest < MiniTest::Unit::TestCase
10
+
11
+ def setup
12
+ @raw_cache = {}
13
+ @cache = EarthTools::Cache.new(@raw_cache, 'earth_tools:')
14
+ end
15
+
16
+ def test_store_and_retrieve_from_cache
17
+ @cache['test/1'] = :data
18
+
19
+ assert_equal :data, @cache['test/1'], 'The cache was not stored properly.'
20
+ end
21
+
22
+ def test_remove_single_url
23
+ @cache['test/1'] = :data
24
+ @cache['test/2'] = :data
25
+
26
+ @cache.expire('test/1')
27
+
28
+ assert_nil @cache['test/1'], 'The cache should have deleted entry.'
29
+ assert_equal :data, @cache['test/2'], 'The cache should not have deleted entry.'
30
+ end
31
+
32
+ def test_remove_all_prefixed_urls
33
+ @raw_cache['test'] = :data
34
+ @raw_cache['other:test'] = :data
35
+ @cache['test/1'] = :data
36
+ @cache['test/2'] = :data
37
+ @cache['test/3'] = :data
38
+
39
+ @cache.expire(:all)
40
+ assert_equal :data, @raw_cache['test'], 'The cache should not affect non-prefixed entries.'
41
+ assert_equal :data, @raw_cache['other:test'], 'The cache should not affect non-prefixed entries.'
42
+ assert_nil @cache['test/1'], 'The cache should be empty of prefixed entries.'
43
+ assert_nil @cache['test/2'], 'The cache should be empty of prefixed entries.'
44
+ assert_nil @cache['test/3'], 'The cache should be empty of prefixed entries.'
45
+ end
46
+
47
+ end
@@ -6,7 +6,7 @@ class ConfigurationTest < MiniTest::Unit::TestCase
6
6
  def setup
7
7
  EarthTools::Configuration.set_defaults
8
8
  end
9
-
9
+
10
10
  # --- class method configuration ---
11
11
  def test_configurated_by_class_method
12
12
  EarthTools::Configuration.units = :metric
@@ -18,7 +18,7 @@ class ConfigurationTest < MiniTest::Unit::TestCase
18
18
  refute_equal result.height, result.feet
19
19
  end
20
20
  end
21
-
21
+
22
22
  # --- EarthTools#configure distances configuration ---
23
23
  def test_configuration
24
24
 
@@ -26,7 +26,7 @@ class ConfigurationTest < MiniTest::Unit::TestCase
26
26
  EarthTools.configure do |config|
27
27
  config.units = :metric
28
28
  end
29
-
29
+
30
30
  assert_equal EarthTools::Configuration.units, :metric
31
31
  result = EarthTools.height(52.4822, -1.8946)
32
32
  if result.height == 0
@@ -34,10 +34,10 @@ class ConfigurationTest < MiniTest::Unit::TestCase
34
34
  else
35
35
  refute_equal result.height, result.feet
36
36
  end
37
-
37
+
38
38
  # Direct
39
39
  EarthTools.configure.units = :metric
40
-
40
+
41
41
  assert_equal EarthTools::Configuration.units, :metric
42
42
  result = EarthTools.height(52.4822, -1.8946)
43
43
  assert_equal result.height, result.meters
@@ -7,6 +7,8 @@ require 'earth_tools/result/sunrise_sunset'
7
7
  require 'earth_tools/result/time_zone'
8
8
  require 'mock_lookup'
9
9
 
10
+ ##
11
+ # Tests for module static methods.
10
12
  class EarthToolsTest < MiniTest::Unit::TestCase
11
13
 
12
14
  def test_time_zone_method_returns_result_object
data/test/height_test.rb CHANGED
@@ -6,8 +6,7 @@ require 'earth_tools/result/height'
6
6
  require 'mock_lookup'
7
7
 
8
8
  ##
9
- #
10
- #
9
+ # Tests for height lookups.
11
10
  class HeightTest < MiniTest::Unit::TestCase
12
11
 
13
12
  def setup
data/test/mock_lookup.rb CHANGED
@@ -1,6 +1,10 @@
1
1
  require 'earth_tools/lookup/base'
2
- class EarthTools::Lookup::Base
3
2
 
3
+ ##
4
+ # Mock Lookup class.
5
+ # Overrides normal lookup base for testing.
6
+ class EarthTools::Lookup::Base
7
+
4
8
  private
5
9
 
6
10
  def read_fixture(file)
@@ -14,5 +18,5 @@ class EarthTools::Lookup::Base
14
18
  query = query.split('/')
15
19
  read_fixture "#{ query[3] }_(#{ query[4, query.size-1].join(',') }).xml"
16
20
  end
17
-
21
+
18
22
  end
@@ -5,8 +5,10 @@ require 'earth_tools'
5
5
  require 'earth_tools/result/sunrise_sunset'
6
6
  require 'mock_lookup'
7
7
 
8
+ ##
9
+ # Tests for Sunrise/Sunset lookups.
8
10
  class SunriseSunsetTest < MiniTest::Unit::TestCase
9
-
11
+
10
12
  def setup
11
13
  @result = EarthTools.sunrise_sunset(40.71417, -74.00639, 12, 4)
12
14
  end
@@ -20,7 +22,7 @@ class SunriseSunsetTest < MiniTest::Unit::TestCase
20
22
  end
21
23
 
22
24
  def test_sunrise_parsed_correctly
23
- assert_equal Time.new(2012, 12, 4, 7, 5, 50, '-05:00'), @result.sunrise, 'Sunrise was not parsed correctly'
25
+ assert_equal Time.new(Time.now.year, 12, 4, 7, 5, 50, '-05:00'), @result.sunrise, 'Sunrise was not parsed correctly'
24
26
  end
25
27
 
26
28
  # ---------------------------------------------------------------------------
@@ -32,7 +34,7 @@ class SunriseSunsetTest < MiniTest::Unit::TestCase
32
34
  end
33
35
 
34
36
  def test_sunset_parsed_correctly
35
- assert_equal Time.new(2012, 12, 4, 16, 26, 59, '-05:00'), @result.sunset, 'Sunset was not parsed correctly'
37
+ assert_equal Time.new(Time.now.year, 12, 4, 16, 26, 59, '-05:00'), @result.sunset, 'Sunset was not parsed correctly'
36
38
  end
37
39
 
38
40
  # ---------------------------------------------------------------------------
@@ -49,12 +51,13 @@ class SunriseSunsetTest < MiniTest::Unit::TestCase
49
51
  end
50
52
 
51
53
  def test_twilight_parsed_correctly
52
- assert_equal Time.new(2012, 12, 4, 5, 27, 39, '-05:00'), @result.twilight(:morning, :astronomical), 'Twilight was not parsed correctly'
53
- assert_equal Time.new(2012, 12, 4, 6, 35, 6, '-05:00'), @result.twilight(:morning, :civil), 'Twilight was not parsed correctly'
54
- assert_equal Time.new(2012, 12, 4, 6, 0, 50, '-05:00'), @result.twilight(:morning, :nautical), 'Twilight was not parsed correctly'
55
- assert_equal Time.new(2012, 12, 4, 18, 5, 10, '-05:00'), @result.twilight(:evening, :astronomical), 'Twilight was not parsed correctly'
56
- assert_equal Time.new(2012, 12, 4, 16, 57, 43, '-05:00'), @result.twilight(:evening, :civil), 'Twilight was not parsed correctly'
57
- assert_equal Time.new(2012, 12, 4, 17, 31, 59, '-05:00'), @result.twilight(:evening, :nautical), 'Twilight was not parsed correctly'
54
+ year = Time.now.year
55
+ assert_equal Time.new(year, 12, 4, 5, 27, 39, '-05:00'), @result.twilight(:morning, :astronomical), 'Twilight was not parsed correctly'
56
+ assert_equal Time.new(year, 12, 4, 6, 35, 6, '-05:00'), @result.twilight(:morning, :civil), 'Twilight was not parsed correctly'
57
+ assert_equal Time.new(year, 12, 4, 6, 0, 50, '-05:00'), @result.twilight(:morning, :nautical), 'Twilight was not parsed correctly'
58
+ assert_equal Time.new(year, 12, 4, 18, 5, 10, '-05:00'), @result.twilight(:evening, :astronomical), 'Twilight was not parsed correctly'
59
+ assert_equal Time.new(year, 12, 4, 16, 57, 43, '-05:00'), @result.twilight(:evening, :civil), 'Twilight was not parsed correctly'
60
+ assert_equal Time.new(year, 12, 4, 17, 31, 59, '-05:00'), @result.twilight(:evening, :nautical), 'Twilight was not parsed correctly'
58
61
  end
59
62
 
60
63
  # ---------------------------------------------------------------------------
@@ -73,8 +76,8 @@ class SunriseSunsetTest < MiniTest::Unit::TestCase
73
76
  assert @result.morning_astronomical_twilight.is_a?(Time), 'Morning astronomical twilight should be a time'
74
77
  end
75
78
 
76
- def test_twilight_parsed_correctly
77
- assert_equal Time.new(2012, 12, 4, 5, 27, 39, '-05:00'), @result.morning_astronomical_twilight, 'Twilight was not parsed correctly'
79
+ def test_morning_astronomical_twilight_parsed_correctly
80
+ assert_equal Time.new(Time.now.year, 12, 4, 5, 27, 39, '-05:00'), @result.morning_astronomical_twilight, 'Twilight was not parsed correctly'
78
81
  end
79
82
 
80
83
  # ---------------------------------------------------------------------------
@@ -82,7 +85,7 @@ class SunriseSunsetTest < MiniTest::Unit::TestCase
82
85
  # ---------------------------------------------------------------------------
83
86
 
84
87
  def test_utc_offset_is_integer
85
- assert @result.utc_offset.is_a?(Integer), 'UTC offset should be an integer'
88
+ assert @result.utc_offset.is_a?(Integer), 'UTC offset should be an integer'
86
89
  end
87
90
 
88
91
  def test_utc_offset_parsed_correctly
@@ -5,8 +5,10 @@ require 'earth_tools'
5
5
  require 'earth_tools/result/time_zone'
6
6
  require 'mock_lookup'
7
7
 
8
+ ##
9
+ # Tests for Time Zone lookups.
8
10
  class TimeZoneTest < MiniTest::Unit::TestCase
9
-
11
+
10
12
  def setup
11
13
  @result = EarthTools.time_zone(40.71417, -74.00639)
12
14
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: earth_tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-09 00:00:00.000000000Z
12
+ date: 2013-12-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rest-client
16
- requirement: &26402964 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: 1.6.1
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *26402964
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 1.6.1
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: xml-simple
27
- requirement: &26402628 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ~>
@@ -32,13 +37,27 @@ dependencies:
32
37
  version: 1.1.1
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *26402628
36
- description: Client library to query the earthtools.org web services
37
- email: max@maxkramer.me
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 1.1.1
46
+ description: ! " \n The earth_tools gem is a client library to query the earthtools.org
47
+ web services.\n Available features include determining time zone, sunset/sunrise
48
+ times, and height\n above sea level for a given longitute/latitude pair. See
49
+ the README for more\n information. Also, please follow the web service restrictions
50
+ for use described \n in the README.\n \n"
51
+ email: max@maxckramer.com
38
52
  executables: []
39
53
  extensions: []
40
54
  extra_rdoc_files: []
41
55
  files:
56
+ - README.md
57
+ - CHANGELOG.md
58
+ - Gemfile
59
+ - Rakefile
60
+ - lib/earth_tools/cache.rb
42
61
  - lib/earth_tools/configuration.rb
43
62
  - lib/earth_tools/exceptions.rb
44
63
  - lib/earth_tools/lookup/base.rb
@@ -51,6 +70,7 @@ files:
51
70
  - lib/earth_tools/result/time_zone.rb
52
71
  - lib/earth_tools/version.rb
53
72
  - lib/earth_tools.rb
73
+ - test/cache_test.rb
54
74
  - test/configuration_test.rb
55
75
  - test/earth_tools_test.rb
56
76
  - test/fixtures/height_(52.4822,-1.8946).xml
@@ -85,9 +105,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
85
105
  version: '0'
86
106
  requirements: []
87
107
  rubyforge_project:
88
- rubygems_version: 1.7.2
108
+ rubygems_version: 1.8.23
89
109
  signing_key:
90
110
  specification_version: 3
91
- summary: Client library to query the earthtools.org web services
111
+ summary: Client library to query the earthtools.org web services.
92
112
  test_files: []
93
- has_rdoc: