reittiopas 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ === 0.0.1 2010-03-29
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
@@ -0,0 +1,21 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.rdoc
4
+ Rakefile
5
+ deps.rip
6
+ lib/reittiopas.rb
7
+ lib/reittiopas/coordinates.rb
8
+ lib/reittiopas/geocoding.rb
9
+ lib/reittiopas/http.rb
10
+ lib/reittiopas/location.rb
11
+ lib/reittiopas/reittiopas.rb
12
+ lib/reittiopas/utils.rb
13
+ script/console
14
+ script/destroy
15
+ script/generate
16
+ spec/fixtures/key.xml
17
+ spec/fixtures/reverse_geocoding.xml
18
+ spec/reittiopas_spec.rb
19
+ spec/spec.opts
20
+ spec/spec_helper.rb
21
+ tasks/rspec.rake
@@ -0,0 +1,58 @@
1
+ = Reittiopas
2
+
3
+ * {Documentation at Github}[http://raneksi.github.com/reittiopas/]
4
+
5
+ == DESCRIPTION:
6
+
7
+ Reittiopas is a Ruby library for accessing the {Reittiopas Developer API}[http://developer.reittiopas.fi/pages/fi/reittiopas-api.php].
8
+
9
+ Requires an account to the service that can be requested through {the account request page}[http://developer.reittiopas.fi/pages/fi/accountrequest.php].
10
+
11
+ == SYNOPSIS:
12
+ require 'reittiopas'
13
+ reittiopas = Reittiopas.new(:username => 'myuser', :password => 'lolcats')
14
+
15
+ === Geocoding
16
+ Search for location by keyword _tee_.
17
+ location = reittiopas.location('tee').first
18
+ puts "#{location}, #{location.city}"
19
+ puts "http://maps.google.com/maps?q=#{URI.escape location.coordinates[:wgs]}"
20
+ Teeripuisto, Helsinki
21
+
22
+ http://maps.google.com/maps?q=60.2528,%2025.02051
23
+
24
+ === Reverse geocoding
25
+ Search for a location by KKJ[http://fi.wikipedia.org/wiki/Kartastokoordinaattij%C3%A4rjestelm%C3%A4] coordinates.
26
+ location = reittiopas.location(:x => 2546445, :y => 6675512).first
27
+ puts "#{location}, #{location.city}"
28
+ Otakaari 9, Espoo
29
+
30
+ == REQUIREMENTS:
31
+
32
+ * Nokogiri[http://nokogiri.org/]
33
+ * Addressable[http://github.com/sporkmonger/addressable]
34
+
35
+ == LICENSE:
36
+
37
+ (The MIT License)
38
+
39
+ Copyright (c) 2010 Raine Virta
40
+
41
+ Permission is hereby granted, free of charge, to any person obtaining
42
+ a copy of this software and associated documentation files (the
43
+ 'Software'), to deal in the Software without restriction, including
44
+ without limitation the rights to use, copy, modify, merge, publish,
45
+ distribute, sublicense, and/or sell copies of the Software, and to
46
+ permit persons to whom the Software is furnished to do so, subject to
47
+ the following conditions:
48
+
49
+ The above copyright notice and this permission notice shall be
50
+ included in all copies or substantial portions of the Software.
51
+
52
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
53
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
54
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
55
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
56
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
57
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
58
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,34 @@
1
+ require 'rubygems'
2
+ gem 'hoe', '>= 2.1.0'
3
+ require 'hoe'
4
+ require 'fileutils'
5
+ require './lib/reittiopas'
6
+
7
+ Hoe.plugin :newgem
8
+
9
+ $hoe = Hoe.spec 'reittiopas' do
10
+ developer 'Raine Virta', 'raine.virta@gmail.com'
11
+ self.rubyforge_name = self.name
12
+
13
+ %w{ addressable nokogiri }.each do |dep|
14
+ self.extra_dev_deps << [dep, '>= 0']
15
+ end
16
+
17
+ self.url = "http://github.com/raneksi/reittiopas"
18
+ self.extra_dev_deps = [['webmock', ">= 0"]]
19
+ self.readme_file = "README.rdoc"
20
+ self.extra_rdoc_files = FileList['*.rdoc']
21
+ end
22
+
23
+ require 'newgem/tasks'
24
+ Dir['tasks/**/*.rake'].each { |t| load t }
25
+
26
+ # remove_task :default
27
+ # task :default => [:spec, :features]
28
+
29
+ require 'gokdok'
30
+ Gokdok::Dokker.new do |gd|
31
+ gd.repo_url = "git@github.com:raneksi/reittiopas.git"
32
+ gd.rdoc_task = :docs
33
+ gd.doc_home = 'doc'
34
+ end
@@ -0,0 +1 @@
1
+ http://github.com/sporkmonger/addressable.git
@@ -0,0 +1,28 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'rubygems'
5
+ require 'uri'
6
+ require 'cgi'
7
+ require 'net/http'
8
+ require 'nokogiri'
9
+ require 'addressable/uri'
10
+
11
+ require 'reittiopas/utils'
12
+ require 'reittiopas/coordinates'
13
+ require 'reittiopas/location'
14
+ require 'reittiopas/geocoding'
15
+ require 'reittiopas/reittiopas'
16
+ require 'reittiopas/http'
17
+
18
+ class Reittiopas
19
+ # The version of Reittiopas you are using.
20
+ VERSION = "0.0.1"
21
+ end
22
+
23
+ # Shorter way for Reittiopas instance creation.
24
+ # In actuality, this doesn't make much sense since it just hides
25
+ # the +new+ method. FIXME
26
+ def Reittiopas(account)
27
+ return Reittiopas.new(account)
28
+ end
@@ -0,0 +1,25 @@
1
+ class Reittiopas
2
+ class Location
3
+ module Coordinates # :nodoc:
4
+ class WGS
5
+ attr_accessor :latitude, :longitude
6
+ def initialize(opts)
7
+ @latitude = opts[:lat].to_f
8
+ @longitude = opts[:lon].to_f
9
+ end
10
+
11
+ def to_s
12
+ [@latitude, @longitude].join(', ')
13
+ end
14
+ end
15
+
16
+ class KKJ
17
+ attr_accessor :x, :y
18
+ def initialize(opts)
19
+ @x = opts[:x].to_i
20
+ @y = opts[:y].to_i
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,53 @@
1
+ class Reittiopas
2
+
3
+ # Module implementing the geocoding features of the Reittiopas API
4
+ # documented at http://developer.reittiopas.fi/pages/fi/http-get-interface.php
5
+ module Geocoding
6
+
7
+ # Send a geocode location query to the API.
8
+ # Both geocoding, and reverse geocoding data is accessed through this method.
9
+ #
10
+ # Returns results as an array containing Reittiopas::Location objects.
11
+ #
12
+ # === Examples:
13
+ # * Search for location by keyword _tee_.
14
+ # reittiopas.location('tee')
15
+ #
16
+ # * Search for location by KKJ coordinates x: _2546445_, y: _6675512_.
17
+ # reittiopas.location(:x => 2546445, :y => 6675512)
18
+ #
19
+ def location(opts)
20
+ params = if opts.is_a? String
21
+ {:key => opts}
22
+ elsif opts.is_a? Hash
23
+ opts
24
+ end
25
+
26
+ parse @http.get(params), opts
27
+ end
28
+
29
+ private
30
+ # Parse XML received from a geocoding API query.
31
+ def parse(xml, opts)
32
+ doc = Nokogiri::XML(xml)
33
+
34
+ locations = doc.search('LOC').map do |loc|
35
+ Reittiopas::Location.parse(loc)
36
+ end
37
+
38
+ # Add KKJ coordinates from REVERSE tag to each Location returned
39
+ # in case it was a reverse geocoding query
40
+ if opts.is_a? Hash
41
+ reverse = doc.search('REVERSE').last
42
+ x = reverse.get_attr_value('x').to_i
43
+ y = reverse.get_attr_value('y').to_i
44
+
45
+ locations.each do |loc|
46
+ loc.coordinates = { :kkj => Reittiopas::Location::Coordinates::KKJ.new(:x => x, :y => y) }
47
+ end
48
+ end
49
+
50
+ return locations
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,40 @@
1
+ class Reittiopas
2
+
3
+ # Reittiopas::HTTP is initialized with account details upon initialization
4
+ # of a Reittiopas object.
5
+ #
6
+ # Since Reittiopas API is to be queried using
7
+ # GET requests with appropriate query parameters, Reittiopas::HTTP exists
8
+ # to simplify the process by offering a +get+ method that accepts a hash
9
+ # containing the query parameters as an argument.
10
+ #
11
+ class HTTP
12
+ # Base URI for the Reittiopas API service.
13
+ API_BASE_URI = "http://api.reittiopas.fi/public-ytv/fi/api/"
14
+
15
+ # Addressable::URI instance of the API URI with account details set as
16
+ # query parameters.
17
+ attr_reader :api_uri
18
+
19
+ # Create a new Reittiopas::HTTP object.
20
+ #
21
+ # +account+ should be a hash containing +:username+ and +:password+.
22
+ def initialize(account)
23
+ @api_uri = Addressable::URI.parse(API_BASE_URI)
24
+ @api_uri.query_values = {:user => account[:username], :pass => account[:password]}
25
+ end
26
+
27
+ # Send a GET request to the API with account details and +opts+ as query
28
+ # parameters.
29
+ #
30
+ # * +opts+ — A hash containing query parameters. Values are automatically
31
+ # encoded by Addressable::URI.
32
+ def get(opts)
33
+ raise ArgumentError if opts.empty?
34
+ uri = @api_uri.dup
35
+ opts.merge!(opts){ |k,ov| ov.to_s } # Coordinates to string
36
+ uri.query_values = uri.query_values.merge(opts)
37
+ return Net::HTTP.get(uri)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,87 @@
1
+ class Reittiopas
2
+
3
+ # This class represents a Location.
4
+ class Location
5
+
6
+ # Get the name of the location.
7
+ attr_accessor :name
8
+
9
+ # Get the city of the location.
10
+ attr_accessor :city
11
+
12
+ # Get the type of the location.
13
+ attr_accessor :type
14
+
15
+ # Get coordinates of the location as a Hash containing Coordinates objects.
16
+ attr_accessor :coordinates
17
+
18
+ # Get the street number of the location.
19
+ attr_accessor :number
20
+
21
+ # Create a Location object from Nokogiri::XML::Element object containing
22
+ # location data.
23
+ def self.parse(xml)
24
+ attr = xml.attributes
25
+
26
+ category = xml.get_attr_value('category')
27
+
28
+ loc = case category
29
+ when "street" then Street.new
30
+ when "stop" then Stop.new
31
+ when "poi" then PointOfInterest.new
32
+ else Location.new
33
+ end
34
+
35
+ loc.name = xml.get_attr_value 'name1'
36
+ loc.city = xml.get_attr_value 'city'
37
+ type = xml.get_attr_value 'type'
38
+ code = xml.get_attr_value 'code'
39
+ number = xml.get_attr_value 'number'
40
+ address = xml.get_attr_value 'address'
41
+
42
+ loc.type = type.to_i if type
43
+ loc.code = code.to_i if code
44
+ loc.number = number.to_i if number
45
+ loc.address = address if address
46
+
47
+ coordinates = {}
48
+
49
+ if attr["x"] && attr["y"]
50
+ coordinates[:kkj] = Coordinates::KKJ.new(Hash[*%w(x y).map { |e| [e.to_sym, attr[e].value.to_i] }.flatten])
51
+ end
52
+
53
+ if attr["lat"] && attr["lon"]
54
+ coordinates[:wgs] = Coordinates::WGS.new(Hash[*%w(lat lon).map { |e| [e.to_sym, attr[e].value.to_f] }.flatten])
55
+ end
56
+
57
+ loc.coordinates = coordinates unless coordinates.empty?
58
+
59
+ return loc
60
+ end
61
+
62
+ # Get the name and street number (if applicable) of the location.
63
+ def to_s
64
+ "#{name} #{number}".strip
65
+ end
66
+
67
+ class PointOfInterest < Location
68
+ # Get the code of the point of interest location.
69
+ attr_accessor :code
70
+ end
71
+
72
+ class Stop < Location
73
+ # Get the address of the bus stop.
74
+ #
75
+ # To follow the API's response format, only bus stops have an address. FIXME?
76
+ attr_accessor :address
77
+
78
+ # Get the code of the bus stop.
79
+ attr_accessor :code
80
+ end
81
+
82
+ class Street < Location
83
+ # Get the street number of the location.
84
+ attr_accessor :number
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,15 @@
1
+ # Reittiopas is a Ruby library for accessing the
2
+ # {Reittiopas Developer API}[http://developer.reittiopas.fi/pages/fi/reittiopas-api.php].
3
+ #
4
+ class Reittiopas
5
+ include Geocoding
6
+
7
+ # Instantiate a Reittiopas object.
8
+ #
9
+ # +account+ should be a hash containing +:username+ and +:password+.
10
+ #
11
+ # Reittiopas.new(:username => 'exampleuser', :password => 'lolcat')
12
+ def initialize(account)
13
+ @http = Reittiopas::HTTP.new(account)
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ # Ugly, get rid of
2
+ module Nokogiri #:nodoc: all
3
+ module XML
4
+ class Element
5
+ def get_attr_value(attr)
6
+ # Might be better to just discard empty attributes
7
+ (a = attribute(attr); a && !a.value.empty? ? a.value : nil)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/reittiopas.rb'}"
9
+ puts "Loading reittiopas gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,22 @@
1
+ <?xml version="1.0" encoding="ISO-8859-1" ?><MTRXML version="1.0">
2
+ <GEOCODE key="tee">
3
+ <LOC name1="Teeripuisto" number="" city="Helsinki" code="1700" address="" type="3" category="poi" x="2556686" y="6682815" lon="25.02051" lat="60.2528" />
4
+ <LOC name1="Teemuntie" number="" city="Helsinki" code="" address="" type="900" category="street" x="2558052" y="6685202" lon="25.04586" lat="60.27403" />
5
+ <LOC name1="Teerenpelinpolku" number="" city="Helsinki" code="" address="" type="900" category="street" x="2556598" y="6682627" lon="25.01887" lat="60.25113" />
6
+ <LOC name1="Teerentie" number="" city="Kirkkonummi" code="" address="" type="900" category="street" x="2524975" y="6686648" lon="24.44833" lat="60.29037" />
7
+ <LOC name1="Teerikuja" number="" city="Vantaa" code="" address="" type="900" category="street" x="2559103" y="6693697" lon="25.06733" lat="60.35011" />
8
+ <LOC name1="Teerikukonkuja" number="" city="Helsinki" code="" address="" type="900" category="street" x="2556898" y="6683026" lon="25.0244" lat="60.25466" />
9
+ <LOC name1="Teerikukontie" number="" city="Helsinki" code="" address="" type="900" category="street" x="2556907" y="6682892" lon="25.02453" lat="60.25346" />
10
+ <LOC name1="Teerimäentie" number="" city="Kerava" code="" address="" type="900" category="street" x="2560257" y="6698983" lon="25.08981" lat="60.39737" />
11
+ <LOC name1="Teerimäentie" number="" city="Vantaa" code="" address="" type="900" category="street" x="2562514" y="6686983" lon="25.12703" lat="60.28935" />
12
+ <LOC name1="Teeripolku" number="" city="Vantaa" code="" address="" type="900" category="street" x="2559133" y="6693811" lon="25.06791" lat="60.35113" />
13
+ <LOC name1="Teeririnne" number="" city="Vantaa" code="" address="" type="900" category="street" x="2559169" y="6693364" lon="25.06843" lat="60.34711" />
14
+ <LOC name1="Teerisuonkuja" number="" city="Helsinki" code="" address="" type="900" category="street" x="2556995" y="6682667" lon="25.02605" lat="60.25143" />
15
+ <LOC name1="Teerisuontie" number="" city="Helsinki" code="" address="" type="900" category="street" x="2557034" y="6682586" lon="25.02673" lat="60.2507" />
16
+ <LOC name1="Teeritie" number="" city="Vantaa" code="" address="" type="900" category="street" x="2559070" y="6693600" lon="25.06671" lat="60.34924" />
17
+ <LOC name1="Teekkarikylä" number="" city="Espoo" code="2222208" address="Otakaari" type="10" category="stop" x="2546445" y="6675512" lon="24.83393" lat="60.18855" />
18
+ <LOC name1="Teerisuonkuja" number="" city="Helsinki" code="1382186" address="Teerisuontie" type="10" category="stop" x="2556964" y="6682609" lon="25.02547" lat="60.25091" />
19
+ <LOC name1="Teerisuontie" number="" city="Helsinki" code="1382141" address="Teerisuontie" type="10" category="stop" x="2556740" y="6682861" lon="25.0215" lat="60.25321" />
20
+ <LOC name1="Teeritie" number="" city="Vantaa" code="4810204" address="Korsontie" type="10" category="stop" x="2559002" y="6694007" lon="25.06559" lat="60.35291" />
21
+ </GEOCODE>
22
+ </MTRXML>
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0" encoding="ISO-8859-1" ?><MTRXML version="1.0">
2
+ <REVERSE x="2546445" y="6675512">
3
+ <LOC name1="Otakaari" number="9" city="Espoo" />
4
+ </REVERSE>
5
+ </MTRXML>
@@ -0,0 +1,245 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe "Reittiopas()" do
4
+ before { @account = {:username => 'foo', :password => 'bar'} }
5
+
6
+ context "when called with an account hash as argument" do
7
+ subject { Reittiopas(@account) }
8
+
9
+ it "should return a Reittiopas object" do
10
+ should be_a_kind_of(Reittiopas)
11
+ end
12
+ end
13
+ end
14
+
15
+ describe Reittiopas do
16
+ before { @account = {:username => 'foo', :password => 'bar'} }
17
+
18
+ context "when initialized with an account" do
19
+ subject { Reittiopas.new(@account) }
20
+
21
+ it { should respond_to(:location) }
22
+ end
23
+
24
+ describe "#location" do
25
+ before { @reittiopas = Reittiopas.new(@account) }
26
+
27
+ context "when given key 'tee' that returns 18 locations from API" do
28
+ before do
29
+ response = File.read(File.dirname(__FILE__) + '/fixtures/key.xml')
30
+ stub_request(:any, /.*key=tee.*/).to_return(:body => response, :status => 200)
31
+ end
32
+
33
+ subject { @reittiopas.location('tee') }
34
+
35
+ it "should return 18 locations in an array" do
36
+ should have(18).items
37
+
38
+ subject.each do |obj|
39
+ obj.should be_a Reittiopas::Location
40
+ end
41
+ end
42
+ end
43
+
44
+ context "when given KKJ coordinates that return one location from API" do
45
+ before do
46
+ response = File.read(File.dirname(__FILE__) + '/fixtures/reverse_geocoding.xml')
47
+ stub_request(:any, /(?:x|y)=\d+&(?:x|y)=\d+/).to_return(:body => response, :status => 200)
48
+ end
49
+
50
+ subject { @reittiopas.location(:x => 2546445, :y => 6675512) }
51
+
52
+ it "should return one result" do
53
+ should have(1).item
54
+ end
55
+
56
+ it "should return a location" do
57
+ subject.first.should be_a Reittiopas::Location
58
+ end
59
+
60
+ it "should return a location with KKJ coordinates" do
61
+ subject.last.coordinates[:kkj].x.should eql 2546445
62
+ subject.last.coordinates[:kkj].y.should eql 6675512
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ describe Reittiopas::HTTP do
69
+ it "should have the proper base API URI" do
70
+ Reittiopas::HTTP::API_BASE_URI.should eql(BASE_URI)
71
+ end
72
+
73
+ before do
74
+ @account = {:username => 'foo', :password => 'bar'}
75
+ @http = Reittiopas::HTTP.new(@account)
76
+ end
77
+
78
+ context "when initialized with an account" do
79
+ subject { Reittiopas::HTTP.new(@account) }
80
+ it { should respond_to(:get) }
81
+
82
+ it "should create an API URI with account details" do
83
+ subject.api_uri.query_values.
84
+ should eql('user' => @account[:username], 'pass' => @account[:password])
85
+ end
86
+ end
87
+
88
+ describe "#get" do
89
+ context "with empty hash as argument" do
90
+ it { lambda { @http.get({}) }.should raise_error(ArgumentError) }
91
+ end
92
+
93
+ context "with proper hash as argument" do
94
+ before do
95
+ @opts = {'key' => 'Keihäänheittäjänkuja 12'}
96
+ @uri = @http.api_uri
97
+ @uri.query_values = @uri.query_values.merge(@opts)
98
+ end
99
+
100
+ it "should create a request" do
101
+ stub_request(:get, Regexp.new(BASE_URI))
102
+ @http.get(@opts)
103
+ request(:get, @uri.to_s).should have_been_made
104
+ end
105
+
106
+ it "should return response body on successful request" do
107
+ stub_request(:get, @uri.to_s).to_return(:body => 'hello', :status => 200)
108
+ @http.get(@opts).should eql('hello')
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ describe Reittiopas::Location do
115
+ it { should respond_to :name }
116
+ it { should respond_to :city }
117
+ it { should respond_to :type }
118
+
119
+ describe "#parse" do
120
+ context "when given LOC" do
121
+ context "example 1" do
122
+ xml = parse_elem '<LOC name1="Sello" number="" city="Espoo" code="2112201" address="Ratsukuja" type="10" category="stop" x="2545011" y="6678850" lon="24.80882" lat="60.21867"/>'
123
+ subject { Reittiopas::Location.parse xml }
124
+
125
+ it { subject.should be_a Reittiopas::Location::Stop }
126
+ it { subject.address.should eql 'Ratsukuja' }
127
+ it { subject.city.should eql 'Espoo' }
128
+ it { subject.name.should eql 'Sello' }
129
+ it { subject.type.should eql 10 }
130
+ it { subject.code.should eql 2112201 }
131
+ it { subject.coordinates[:kkj].x.should eql 2545011 }
132
+ it { subject.coordinates[:kkj].y.should eql 6678850 }
133
+ it { subject.coordinates[:wgs].longitude.should eql 24.80882 }
134
+ it { subject.coordinates[:wgs].latitude.should eql 60.21867 }
135
+ it { subject.to_s.should eql 'Sello' }
136
+ end
137
+
138
+ context "example 2" do
139
+ xml = parse_elem '<LOC name1="Kahisevantie" number="2" city="Espoo" code="" address="" type="900" category="street" x="2541494" y="6680344" lon="24.74568" lat="60.23245"/>'
140
+ subject { Reittiopas::Location.parse xml }
141
+
142
+ it { subject.should be_a Reittiopas::Location::Street }
143
+ it { subject.should_not respond_to :address }
144
+ it { subject.should_not respond_to :code }
145
+ it { subject.city.should eql 'Espoo' }
146
+ it { subject.name.should eql 'Kahisevantie' }
147
+ it { subject.type.should eql 900 }
148
+ it { subject.number.should eql 2 }
149
+ it { subject.coordinates[:kkj].x.should eql 2541494 }
150
+ it { subject.coordinates[:kkj].y.should eql 6680344 }
151
+ it { subject.coordinates[:wgs].longitude.should eql 24.74568 }
152
+ it { subject.coordinates[:wgs].latitude.should eql 60.23245 }
153
+ it { subject.to_s.should eql 'Kahisevantie 2' }
154
+ end
155
+
156
+ context "example 3" do
157
+ xml = parse_elem '<LOC name1="Teeripuisto" number="" city="Helsinki" code="1700" address="" type="3" category="poi" x="2556686" y="6682815" lon="25.02051" lat="60.2528" />'
158
+ subject { Reittiopas::Location.parse xml }
159
+
160
+ it { subject.should be_a Reittiopas::Location::PointOfInterest }
161
+ it { subject.should_not respond_to :address }
162
+ it { subject.city.should eql 'Helsinki' }
163
+ it { subject.name.should eql 'Teeripuisto' }
164
+ it { subject.type.should eql 3 }
165
+ it { subject.coordinates[:kkj].x.should eql 2556686 }
166
+ it { subject.coordinates[:kkj].y.should eql 6682815 }
167
+ it { subject.coordinates[:wgs].longitude.should eql 25.02051 }
168
+ it { subject.coordinates[:wgs].latitude.should eql 60.2528 }
169
+ it { subject.to_s.should eql 'Teeripuisto' }
170
+ end
171
+
172
+ context "example 4" do
173
+ xml = parse_elem '<LOC name1="Otakaari" number="9" city="Espoo" />'
174
+ subject { Reittiopas::Location.parse xml }
175
+
176
+ it { subject.should be_a Reittiopas::Location }
177
+ it { subject.city.should eql 'Espoo' }
178
+ it { subject.name.should eql 'Otakaari' }
179
+ it { subject.number.should eql 9 }
180
+ it { subject.should_not respond_to :address }
181
+ it { subject.should_not respond_to :code }
182
+ it { subject.type.should_not be }
183
+ it { subject.coordinates.should_not be }
184
+ it { subject.to_s.should eql 'Otakaari 9' }
185
+ end
186
+ end
187
+
188
+ context "when given LOC has 'poi' as category" do
189
+ xml = parse_elem '<LOC name1="Teeripuisto" number="" city="Helsinki" code="1700" address="" type="3" category="poi" x="2556686" y="6682815" lon="25.02051" lat="60.2528" />'
190
+ subject { Reittiopas::Location.parse xml }
191
+
192
+ it "should return a Location" do
193
+ should be_a Reittiopas::Location::PointOfInterest
194
+ end
195
+ end
196
+
197
+ context "when given LOC has 'stop' as category" do
198
+ xml = parse_elem '<LOC name1="Teeritie" number="" city="Vantaa" code="4810204" address="Korsontie" type="10" category="stop" x="2559002" y="6694007" lon="25.06559" lat="60.35291" />'
199
+ subject { Reittiopas::Location.parse xml }
200
+
201
+ it "should return a Stop" do
202
+ should be_a Reittiopas::Location::Stop
203
+ end
204
+ end
205
+
206
+ context "when given LOC has 'street' as category" do
207
+ xml = parse_elem '<LOC name1="Kahisevantie" number="2" city="Espoo" code="" address="" type="900" category="street" x="2541494" y="6680344" lon="24.74568" lat="60.23245"/>'
208
+ subject { Reittiopas::Location.parse xml }
209
+
210
+ it "should return a Street" do
211
+ should be_a Reittiopas::Location::Street
212
+ end
213
+ end
214
+ end
215
+ end
216
+
217
+ describe Reittiopas::Location::PointOfInterest do
218
+ it { should respond_to :code }
219
+ end
220
+
221
+ describe Reittiopas::Location::Stop do
222
+ it { should respond_to :address }
223
+ it { should respond_to :code }
224
+ end
225
+
226
+ describe Reittiopas::Location::Street do
227
+ it { should respond_to :number }
228
+ it { should_not respond_to :code }
229
+ end
230
+
231
+ describe Reittiopas::Location::Coordinates::KKJ do
232
+ subject { Reittiopas::Location::Coordinates::KKJ.new(:x => 2541494, :y => 6680344) }
233
+
234
+ it { should respond_to :x }
235
+ it { should respond_to :y }
236
+ end
237
+
238
+ describe Reittiopas::Location::Coordinates::WGS do
239
+ subject { Reittiopas::Location::Coordinates::WGS.new(:lon => 24.74568, :lat => 60.23245) }
240
+
241
+ it { should respond_to :latitude }
242
+ it { should respond_to :longitude }
243
+
244
+ it { subject.to_s.should eql '60.23245, 24.74568' }
245
+ end
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --format specdoc
3
+ --loadby mtime
4
+ --reverse
@@ -0,0 +1,19 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
5
+ gem 'rspec'
6
+ require 'spec'
7
+ end
8
+
9
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
10
+ require 'reittiopas'
11
+
12
+ require 'webmock/rspec'
13
+ include WebMock
14
+
15
+ BASE_URI = "http://api.reittiopas.fi/public-ytv/fi/api/"
16
+
17
+ def parse_elem(xml)
18
+ Nokogiri::XML(xml).children[0]
19
+ end
@@ -0,0 +1,38 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
5
+ require 'spec'
6
+ end
7
+ begin
8
+ require 'spec/rake/spectask'
9
+ rescue LoadError
10
+ puts <<-EOS
11
+ To use rspec for testing you must install rspec gem:
12
+ gem install rspec
13
+ EOS
14
+ exit(0)
15
+ end
16
+
17
+ desc "Run the specs under spec/models"
18
+ Spec::Rake::SpecTask.new do |t|
19
+ t.spec_opts = ['--options', "spec/spec.opts"]
20
+ t.spec_files = FileList['spec/**/*_spec.rb']
21
+ end
22
+
23
+ namespace :spec do
24
+ desc "Run all examples with RCov"
25
+ Spec::Rake::SpecTask.new(:rcov) do |t|
26
+ t.spec_files = FileList['spec/**/*_spec.rb']
27
+ t.rcov = true
28
+ t.rcov_opts = [
29
+ '--exclude', 'spec'
30
+ ]
31
+ end
32
+
33
+ desc "Browse the code coverage report."
34
+ task :browse => "spec:rcov" do
35
+ require "launchy"
36
+ Launchy::Browser.run("coverage/index.html")
37
+ end
38
+ end
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: reittiopas
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Raine Virta
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-04-05 00:00:00 +03:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: webmock
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :development
31
+ version_requirements: *id001
32
+ - !ruby/object:Gem::Dependency
33
+ name: hoe
34
+ prerelease: false
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ segments:
40
+ - 2
41
+ - 6
42
+ - 0
43
+ version: 2.6.0
44
+ type: :development
45
+ version_requirements: *id002
46
+ description: |-
47
+ Reittiopas is a Ruby library for accessing the {Reittiopas Developer API}[http://developer.reittiopas.fi/pages/fi/reittiopas-api.php].
48
+
49
+ Requires an account to the service that can be requested through {the account request page}[http://developer.reittiopas.fi/pages/fi/accountrequest.php].
50
+ email:
51
+ - raine.virta@gmail.com
52
+ executables: []
53
+
54
+ extensions: []
55
+
56
+ extra_rdoc_files:
57
+ - History.txt
58
+ - Manifest.txt
59
+ - README.rdoc
60
+ files:
61
+ - History.txt
62
+ - Manifest.txt
63
+ - README.rdoc
64
+ - Rakefile
65
+ - deps.rip
66
+ - lib/reittiopas.rb
67
+ - lib/reittiopas/coordinates.rb
68
+ - lib/reittiopas/geocoding.rb
69
+ - lib/reittiopas/http.rb
70
+ - lib/reittiopas/location.rb
71
+ - lib/reittiopas/reittiopas.rb
72
+ - lib/reittiopas/utils.rb
73
+ - script/console
74
+ - script/destroy
75
+ - script/generate
76
+ - spec/fixtures/key.xml
77
+ - spec/fixtures/reverse_geocoding.xml
78
+ - spec/reittiopas_spec.rb
79
+ - spec/spec.opts
80
+ - spec/spec_helper.rb
81
+ - tasks/rspec.rake
82
+ has_rdoc: true
83
+ homepage: http://github.com/raneksi/reittiopas
84
+ licenses: []
85
+
86
+ post_install_message:
87
+ rdoc_options:
88
+ - --main
89
+ - README.rdoc
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ segments:
97
+ - 0
98
+ version: "0"
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ segments:
104
+ - 0
105
+ version: "0"
106
+ requirements: []
107
+
108
+ rubyforge_project: reittiopas
109
+ rubygems_version: 1.3.6
110
+ signing_key:
111
+ specification_version: 3
112
+ summary: Reittiopas is a Ruby library for accessing the {Reittiopas Developer API}[http://developer.reittiopas.fi/pages/fi/reittiopas-api.php]
113
+ test_files: []
114
+