svlt-ruby-geonames 0.2.7

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown ADDED
@@ -0,0 +1,87 @@
1
+ # Geonames Ruby API
2
+
3
+ Ruby library for [Geonames Web Services](http://www.geonames.org/export/)
4
+
5
+ Created by [TouchBase Counsulting](http://www.tbcn.ca/geonames) to support GIS processes for [Carpool Connect](http://www.carpoolconnect.com/). Inspired by the Geonames [Java Client API library](http://www.geonames.org/source-code/).
6
+
7
+ Modified by Suomen Verkkoliiketoiminta Oy to include place name searching and to get timezone at the same time
8
+
9
+ ## Installing ruby-geonames
10
+
11
+ Install from the command line:
12
+
13
+ sudo gem install svlt-ruby-geonames
14
+
15
+ ## Examples
16
+
17
+ The following exercises several of the Geonames web services, [full list of services](http://www.geonames.org/export/).
18
+
19
+ **Load the the geonames API**
20
+
21
+ require 'geonames'
22
+
23
+ **get list of places near by longitude/longitude location**
24
+
25
+ places_nearby = Geonames::WebService.find_nearby_place_name 43.900120387, -78.882869834
26
+ p places_nearby
27
+
28
+ outputs:
29
+
30
+ `[#<Geonames::Toponym:0x6c8c98 @population=nil, @geoname_id='6094578', @longitude=-78.849568878, @feature_class_name=nil, @country_name='Canada', @latitude=43.900120387, @feature_class='P', @country_code='CA', @name='Oshawa', @feature_code_name=nil, @elevation=nil, @distance=2.6679930307932, @alternate_names=nil, @feature_code='PPL'>]`
31
+
32
+ **get timezone for longitude/longitude location**
33
+
34
+ timezone = Geonames::WebService.timezone 43.900120387, -78.882869834
35
+ p timezone
36
+
37
+ **get country code for longitude/longitude location**
38
+
39
+ country_code = Geonames::WebService.country_code 43.900120387, -78.882869834
40
+ p country_code
41
+
42
+ **get country sub-division info for longitude/longitude location**
43
+
44
+ country_subdivision = Geonames::WebService.country_subdivision 43.900120387, -78.882869834
45
+ p country_subdivision
46
+
47
+ **get postal codes for a given location**
48
+
49
+ postal_code_sc = Geonames::PostalCodeSearchCriteria.new
50
+ postal_code_sc.place_name = "Oshawa"
51
+ postal_codes = Geonames::WebService.postal_code_search postal_code_sc
52
+ p postal_codes
53
+
54
+ **get nearby postal codes for a place name**
55
+
56
+ postal_code_sc = Geonames::PostalCodeSearchCriteria.new
57
+ postal_code_sc.place_name = "Oshawa"
58
+ postal_codes_nearby = Geonames::WebService.find_nearby_postal_codes postal_code_sc
59
+ p postal_codes_nearby
60
+
61
+ **get timezone for a place name**
62
+
63
+ sc = Geonames::SearchCriteria.new
64
+ sc.name_starts_with = "tampere"
65
+ sc.feature_class = "P"
66
+ sc.style="full"
67
+ sc.country="fi"
68
+ location = Geonames::WebService.search sc
69
+ p location.toponyms[0].score
70
+ p location.toponyms[0].timezone
71
+
72
+
73
+ ## Commercial Service Support
74
+
75
+ If you use the commercial service, you should put something like this in your configuration:
76
+
77
+ Geonames::username = 'username'
78
+ Geonames::base_url = 'http://ws.geonames.net'
79
+
80
+ In a Rails application, this would go in the `config/environment.rb` file.
81
+
82
+ # Contributors
83
+
84
+ 1. Adam Wisniewski
85
+ 2. Nicolas Marchildon (elecnix)
86
+ 3. Ahto Jussila
87
+
data/lib/Rakefile.rb ADDED
@@ -0,0 +1,21 @@
1
+ #=============================================================================
2
+ #
3
+ # Copyright 2007 Adam Wisniewski <adamw@tbcn.ca>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ # use this file except in compliance with the License. You may obtain a copy of
7
+ # the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ # License for the specific language governing permissions and limitations under
15
+ # the License.
16
+ #
17
+ #=============================================================================
18
+
19
+ require 'rake'
20
+ require 'rake/testtask'
21
+ require 'rake/rdoctask'
data/lib/address.rb ADDED
@@ -0,0 +1,25 @@
1
+ #=============================================================================
2
+ #
3
+ # Copyright 2007 Adam Wisniewski <adamw@tbcn.ca>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ # use this file except in compliance with the License. You may obtain a copy of
7
+ # the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ # License for the specific language governing permissions and limitations under
15
+ # the License.
16
+ #
17
+ #=============================================================================
18
+
19
+ module Geonames
20
+ class Address
21
+
22
+ end
23
+ end
24
+
25
+
@@ -0,0 +1,18 @@
1
+ module Geonames
2
+ class BoundingBox
3
+ attr_reader :north_point, :south_point, :east_point, :west_point
4
+ attr_writer :north_point, :south_point, :east_point, :west_point
5
+
6
+ def initialize(north=0.0, south=0.0, east=0.0, west=0.0)
7
+ self.north_point = north
8
+ self.south_point = south
9
+ self.east_point = east
10
+ self.west_point = west
11
+ end
12
+
13
+ def contains?(point)
14
+ #todo implement me
15
+ return false
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,36 @@
1
+ module Geonames
2
+ class CountryInfo
3
+ attr_reader :country_code, :country_name, :iso_numeric, :iso_alpha_3
4
+ attr_reader :fips_code, :continent, :capital, :area_sq_km, :population
5
+ attr_reader :currency_code, :geoname_id
6
+
7
+ attr_writer :country_code, :country_name, :iso_numeric, :iso_alpha_3
8
+ attr_writer :fips_code, :continent, :capital, :area_sq_km, :population
9
+ attr_writer :currency_code, :geoname_id
10
+
11
+ def initialize
12
+ @langs = []
13
+ @bounding_box = BoundingBox.new()
14
+ end
15
+
16
+ def bounding_box
17
+ return @bounding_box
18
+ end
19
+
20
+ def bounding_box=(new_bb)
21
+ @bounding_box = new_bb
22
+ end
23
+
24
+ def set_bounding_box(north, south, east, west)
25
+ @bounding_box = BoundingBox.new(north, south, east, west)
26
+ end
27
+
28
+ def languages
29
+ return @langs
30
+ end
31
+
32
+ def languages=(new_langs)
33
+ @langs = new_langs
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,35 @@
1
+ #=============================================================================
2
+ #
3
+ # Copyright 2007 Adam Wisniewski <adamw@tbcn.ca>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ # use this file except in compliance with the License. You may obtain a copy of
7
+ # the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ # License for the specific language governing permissions and limitations under
15
+ # the License.
16
+ #
17
+ #=============================================================================
18
+
19
+ module Geonames
20
+ class CountrySubdivision
21
+ attr :country_code
22
+ attr :country_name
23
+ attr :admin_code_1
24
+ attr :admin_name_1
25
+ attr :code_fips
26
+ attr :code_iso
27
+
28
+ attr_writer :country_code, :country_name
29
+ attr_writer :admin_name_1, :admin_code_1
30
+ attr_writer :code_fips, :code_iso
31
+
32
+ end
33
+ end
34
+
35
+
data/lib/geonames.rb ADDED
@@ -0,0 +1,60 @@
1
+ #=============================================================================
2
+ #
3
+ # Copyright 2007 Adam Wisniewski <adamw@tbcn.ca>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ # use this file except in compliance with the License. You may obtain a copy of
7
+ # the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ # License for the specific language governing permissions and limitations under
15
+ # the License.
16
+ #
17
+ #=============================================================================
18
+
19
+ require 'cgi'
20
+ require 'net/http'
21
+ require 'rexml/document'
22
+
23
+ require 'web_service'
24
+ require 'toponym'
25
+ require 'toponym_search_result'
26
+ require 'toponym_search_criteria'
27
+ require 'postal_code'
28
+ require 'postal_code_search_criteria'
29
+ require 'timezone'
30
+ require 'country_subdivision'
31
+ require 'wikipedia_article'
32
+ require 'intersection'
33
+ require 'search_criteria'
34
+
35
+ module Geonames
36
+
37
+ GEONAMES_SERVER = "http://ws.geonames.org"
38
+ USER_AGENT = "geonames ruby webservice client 0.1"
39
+
40
+ @@username = nil
41
+ @@base_url = "http://ws.geonames.org"
42
+
43
+ def self.username
44
+ @@username
45
+ end
46
+
47
+ def self.username=(username)
48
+ @@username = username
49
+ end
50
+
51
+ def self.base_url
52
+ @@base_url
53
+ end
54
+
55
+ def self.base_url=(base_url)
56
+ @@base_url = base_url
57
+ end
58
+
59
+ end
60
+
@@ -0,0 +1,42 @@
1
+ #=============================================================================
2
+ #
3
+ # Copyright 2007 Adam Wisniewski <adamw@tbcn.ca>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ # use this file except in compliance with the License. You may obtain a copy of
7
+ # the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ # License for the specific language governing permissions and limitations under
15
+ # the License.
16
+ #
17
+ #=============================================================================
18
+
19
+ module Geonames
20
+ class Intersection
21
+ attr :street_1
22
+ attr :street_2
23
+ attr :latitude
24
+ attr :longitude
25
+ attr :distance
26
+ attr :postal_code
27
+ attr :place_name
28
+ attr :country_code
29
+ attr :admin_code_1
30
+ attr :admin_name_2
31
+ attr :admin_code_2
32
+ attr :admin_name_1
33
+
34
+ attr_writer :street_1, :street_2
35
+ attr_writer :postal_code, :place_name, :country_code
36
+ attr_writer :latitude, :longitude, :admin_name_1
37
+ attr_writer :admin_code_1, :admin_name_2, :admin_code_2
38
+ attr_writer :distance
39
+ end
40
+ end
41
+
42
+
data/lib/main.rb ADDED
@@ -0,0 +1,75 @@
1
+ #=============================================================================
2
+ #
3
+ # Copyright 2007 Adam Wisniewski <adamw@tbcn.ca>
4
+ # Contributions by Andrew Turner, High Earth Orbit
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
7
+ # use this file except in compliance with the License. You may obtain a copy of
8
+ # the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
+ # License for the specific language governing permissions and limitations under
16
+ # the License.
17
+ #
18
+ #=============================================================================
19
+
20
+ require 'geonames'
21
+ require 'pp'
22
+
23
+ Geonames::username = 'svlt'
24
+ Geonames::base_url = 'http://ws.geonames.net'
25
+ # get the nearest intersection
26
+ intersection = Geonames::WebService.find_nearest_intersection 40.7574053333333, -73.9734773333333
27
+ puts intersection.street_1 #=> Park Ave
28
+ puts intersection.street_2 #=> E 51st St
29
+
30
+ # get wikipedia articles by lat / long
31
+ articles_nearby = Geonames::WebService.find_nearby_wikipedia :lat => 43.900120387, :long => -78.882869834
32
+ p articles_nearby
33
+
34
+ # get wikipedia articles by bounding box
35
+ articles_nearby = Geonames::WebService.find_bounding_box_wikipedia :north => 43.900120387, :east => -78.882869834, :south => 43.82, :west => 79.0
36
+ p articles_nearby
37
+
38
+ # get list of places near by longitude/longitude location
39
+ places_nearby = Geonames::WebService.find_nearby_place_name 43.900120387, -78.882869834
40
+ p places_nearby
41
+
42
+ # get timezone for longitude/longitude location
43
+ timezone = Geonames::WebService.timezone 43.900120387, -78.882869834
44
+ p timezone
45
+
46
+ # get country code for longitude/longitude location
47
+ country_code = Geonames::WebService.country_code 43.900120387, -78.882869834
48
+ p country_code
49
+
50
+ # get country sub-division info for longitude/longitude location
51
+ country_subdivision = Geonames::WebService.country_subdivision 43.900120387, -78.882869834
52
+ p country_subdivision
53
+
54
+ # get postal codes for a given location
55
+ postal_code_sc = Geonames::PostalCodeSearchCriteria.new
56
+ postal_code_sc.place_name = "Oshawa"
57
+ postal_codes = Geonames::WebService.postal_code_search postal_code_sc
58
+ p postal_codes
59
+
60
+ # get nearby postal codes for a place name
61
+ postal_code_sc = Geonames::PostalCodeSearchCriteria.new
62
+ postal_code_sc.place_name = "Oshawa"
63
+ postal_codes_nearby = Geonames::WebService.find_nearby_postal_codes postal_code_sc
64
+ p postal_codes_nearby
65
+
66
+ # get score and timezone of search hit
67
+ sc = Geonames::SearchCriteria.new
68
+ sc.name_starts_with = "tampere"
69
+ sc.feature_class = "P"
70
+ sc.style="full"
71
+ sc.country="fi"
72
+ location = Geonames::WebService.search sc
73
+ p location.toponyms[0].score
74
+ p location.toponyms[0].timezone
75
+
@@ -0,0 +1,40 @@
1
+ #=============================================================================
2
+ #
3
+ # Copyright 2007 Adam Wisniewski <adamw@tbcn.ca>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ # use this file except in compliance with the License. You may obtain a copy of
7
+ # the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ # License for the specific language governing permissions and limitations under
15
+ # the License.
16
+ #
17
+ #=============================================================================
18
+
19
+ module Geonames
20
+ class PostalCode
21
+ attr :postal_code
22
+ attr :place_name
23
+ attr :country_code
24
+ attr :latitude
25
+ attr :longitude
26
+ attr :admin_name_1
27
+ attr :admin_code_1
28
+ attr :admin_name_2
29
+ attr :admin_code_2
30
+ attr :distance
31
+
32
+ attr_writer :postal_code, :place_name, :country_code
33
+ attr_writer :latitude, :longitude, :admin_name_1
34
+ attr_writer :admin_code_1, :admin_name_2, :admin_code_2
35
+ attr_writer :distance
36
+
37
+ end
38
+ end
39
+
40
+
@@ -0,0 +1,84 @@
1
+ #=============================================================================
2
+ #
3
+ # Copyright 2007 Adam Wisniewski <adamw@tbcn.ca>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ # use this file except in compliance with the License. You may obtain a copy of
7
+ # the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ # License for the specific language governing permissions and limitations under
15
+ # the License.
16
+ #
17
+ #=============================================================================
18
+
19
+ module Geonames
20
+ class PostalCodeSearchCriteria
21
+
22
+ attr :postal_code
23
+ attr :place_name
24
+ attr :country_code
25
+ attr :latitude
26
+ attr :longitude
27
+ attr :style
28
+ attr :max_rows
29
+ attr :is_or_operator
30
+ attr :radius
31
+
32
+ attr_writer :postal_code, :place_name, :country_code
33
+ attr_writer :latitude, :longitude, :style
34
+ attr_writer :max_rows, :is_or_operator, :radius
35
+
36
+ def initialize
37
+ @is_or_operator = false
38
+ end
39
+
40
+ def to_query_params_string
41
+ url = ''
42
+
43
+ if !@postal_code.nil?
44
+ url = url + "&postalcode=" + CGI::escape( @postal_code )
45
+ end
46
+
47
+ if !@place_name.nil?
48
+ url = url + "&placename=" + CGI::escape( @place_name )
49
+ end
50
+
51
+ if !@latitude.nil?
52
+ url = url + "&lat" + CGI::escape( @latitude.to_s )
53
+ end
54
+
55
+ if !@longitude.nil?
56
+ url = url + "&lng" + CGI::escape( @longitude.to_s )
57
+ end
58
+
59
+ if !@style.nil?
60
+ url = url + "&style" + CGI::escape( @style )
61
+ end
62
+
63
+ if !@country_code.nil?
64
+ url = url + "&country=" + CGI::escape( @country_code )
65
+ end
66
+
67
+ if !@max_rows.nil?
68
+ url = url + "&maxRows=" + CGI::escape( @max_rows )
69
+ end
70
+
71
+ if !@radius.nil?
72
+ url = url + "&radius=" + CGI::escape( @radius.to_s )
73
+ end
74
+
75
+ if @is_or_operator
76
+ url = url + "&operator=OR"
77
+ end
78
+
79
+ url
80
+ end
81
+ end
82
+ end
83
+
84
+
@@ -0,0 +1,37 @@
1
+ module Geonames
2
+ class SearchCriteria
3
+
4
+ attr :q
5
+ attr :name
6
+ attr :name_equals
7
+ attr :name_starts_with
8
+ attr :max_rows
9
+ attr :start_row
10
+ attr :country
11
+ attr :country_bias
12
+ attr :continent_codes
13
+ attr :admin_code_1
14
+ attr :admin_code_2
15
+ attr :admin_code_3
16
+ attr :feature_class
17
+ attr :feature_codes
18
+ attr :language
19
+ attr :type
20
+ attr :style
21
+ attr :is_name_required
22
+ attr :tag
23
+ attr :operator
24
+ attr :charset
25
+
26
+
27
+ attr_writer :q, :name, :name_equals, :name_starts_with
28
+ attr_writer :max_rows, :start_row
29
+ attr_writer :country, :country_bias, :continent_code
30
+ attr_writer :admin_code_1, :admin_code_2, :admin_code_3
31
+ attr_writer :feature_class, :feature_codes, :language
32
+ attr_writer :type, :style, :is_name_required
33
+ attr_writer :tag, :operator, :charset
34
+
35
+
36
+ end
37
+ end
@@ -0,0 +1,56 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
+
3
+ require 'geonames'
4
+ require 'test/unit'
5
+
6
+ class TestCountryInfo < Test::Unit::TestCase
7
+ def setup
8
+ @test_code = "TH"
9
+
10
+ @expected =
11
+ {:country_code => 'TH', :country_name => 'Thailand', :iso_numeric => 764,
12
+ :iso_alpha_3 => 'THA', :fips_code => 'TH', :continent => 'AS',
13
+ :capital => 'Bangkok', :area_sq_km => 514000.0, :population => 65493000,
14
+ :currency_code => 'THB', :geonameId => 1605651,
15
+ :languages => ['th', 'en'],
16
+ :box_north => 20.4631977081299, :box_south => 5.60999917984009,
17
+ :box_east => 105.63939666748, :box_west => 97.3456268310547}
18
+ end
19
+
20
+ def teardown
21
+ #nothing here really
22
+ end
23
+
24
+ def test_simple_values
25
+ info = Geonames::WebService.country_info(@test_code)
26
+
27
+ assert_equal(@expected[:country_code], info.country_code)
28
+ assert_equal(@expected[:country_name], info.country_name)
29
+ assert_equal(@expected[:iso_numeric], info.iso_numeric)
30
+ assert_equal(@expected[:iso_alpha_3], info.iso_alpha_3)
31
+ assert_equal(@expected[:fips_code], info.fips_code)
32
+ assert_equal(@expected[:continent], info.continent)
33
+ assert_equal(@expected[:capital], info.capital)
34
+ assert_equal(@expected[:area_sq_km], info.area_sq_km)
35
+ assert_equal(@expected[:population], info.population)
36
+ assert_equal(@expected[:currency_code], info.currency_code)
37
+ assert_equal(@expected[:geonameId], info.geoname_id )
38
+ end
39
+
40
+ def test_languages
41
+ info = Geonames::WebService.country_info(@test_code)
42
+
43
+ assert_equal(2, info.languages.size)
44
+ assert_equal(@expected[:languages][0], info.languages[0])
45
+ assert_equal(@expected[:languages][1], info.languages[1])
46
+ end
47
+
48
+ def test_bounding_box
49
+ info = Geonames::WebService.country_info(@test_code)
50
+
51
+ assert_equal(@expected[:box_north], info.bounding_box.north_point)
52
+ assert_equal(@expected[:box_south], info.bounding_box.south_point)
53
+ assert_equal(@expected[:box_east], info.bounding_box.east_point)
54
+ assert_equal(@expected[:box_west], info.bounding_box.west_point)
55
+ end
56
+ end
data/lib/timezone.rb ADDED
@@ -0,0 +1,29 @@
1
+ #=============================================================================
2
+ #
3
+ # Copyright 2007 Adam Wisniewski <adamw@tbcn.ca>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ # use this file except in compliance with the License. You may obtain a copy of
7
+ # the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ # License for the specific language governing permissions and limitations under
15
+ # the License.
16
+ #
17
+ #=============================================================================
18
+
19
+ module Geonames
20
+ class Timezone
21
+ attr :timezone_id
22
+ attr :gmt_offset
23
+ attr :dst_offset
24
+
25
+ attr_writer :timezone_id, :gmt_offset, :dst_offset
26
+ end
27
+ end
28
+
29
+