ymaps 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,8 @@
1
- = ymaps
1
+ = YMaps
2
2
 
3
- Description goes here.
3
+ Helpers for using Yandex Maps service.
4
+
5
+ It includes Geokit-based Geocoder and helper for generating YMapsML files with data for Yandex Maps.
4
6
 
5
7
  == Note on Patches/Pull Requests
6
8
 
@@ -12,6 +14,4 @@ Description goes here.
12
14
  (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
15
  * Send me a pull request. Bonus points for topic branches.
14
16
 
15
- == Copyright
16
-
17
- Copyright (c) 2010 Alexander Semyonov. See LICENSE for details.
17
+ © Alexander Semyonov, 2010. See LICENSE for details.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.0.3
@@ -1,13 +1,48 @@
1
1
  require 'geokit'
2
+ require 'geokit/inflector'
2
3
  require 'geokit/geocoders'
3
4
 
4
5
  module Geokit
5
6
  self.default_units = :kms
6
7
 
7
8
  class LatLng
8
- def pos
9
+ def gml_pos
9
10
  "#{lng} #{lat}"
10
11
  end
12
+
13
+ def ymaps_lnglat
14
+ "#{lng},#{lat}"
15
+ end
16
+
17
+ def ymaps_lnglat=(lnglat)
18
+ self.lng, self.lat = lnglat[0], lnglat[1]
19
+ end
20
+ end
21
+
22
+ class GeoLoc
23
+ attr_accessor :kind
24
+ attr_writer :street_number, :street_name
25
+
26
+ # Extracts the street number from the street address if the street address
27
+ # has a value.
28
+ def street_number
29
+ @street_number ||= street_address && street_address[/(\d*)/]
30
+ end
31
+
32
+ # Returns the street name portion of the street address.
33
+ def street_name
34
+ @street_name ||= street_address && street_address[street_number.length, street_address.length].strip
35
+ end
36
+
37
+ # Do not use ugly Geokit::Inflector::titleize when set city’s name
38
+ def city=(city)
39
+ @city = city
40
+ end
41
+
42
+ # Do not use ugly Geokit::Inflector::titleize when set street address
43
+ def street_address=(address)
44
+ @street_address = address
45
+ end
11
46
  end
12
47
 
13
48
  module Geocoders
@@ -20,6 +55,23 @@ module Geokit
20
55
  end
21
56
 
22
57
  class YandexGeocoder < Geocoder
58
+ KIND_ACCURACY_MAP = {
59
+ 'country' => 1,
60
+ 'province' => 2,
61
+ 'area' => 3,
62
+ # 5 postal code
63
+ 'locality' => 4,
64
+ 'street' => 6,
65
+ 'route' => 6,
66
+ # 7 kreuzung
67
+ 'house' => 8,
68
+ 'metro' => 8,
69
+ 'railway' => 8,
70
+ # 9 building
71
+ # district hydro vegetation cemetery bridge km other
72
+ # 0 #unknown
73
+ }
74
+ PRECISIONS = %w{unknown country state state city zip zip+4 street address building}
23
75
 
24
76
  private
25
77
  def self.call_geocoder_service(geocode)
@@ -30,18 +82,18 @@ module Geokit
30
82
  end
31
83
 
32
84
  xml = res.body
33
- logger.debug "Yandex geocoding: '#{geocode}'. Result: #{xml}"
85
+ logger.debug("Yandex geocoding: '#{geocode}'. Result: #{xml}")
34
86
  return xml2GeoLoc(xml)
35
87
  end
36
88
 
37
89
  def self.do_reverse_geocode(latlng)
38
90
  latlng = LatLng.normalize(latlng)
39
- call_geocoder_service(latlng.ll)
91
+ call_geocoder_service(latlng.ymaps_lnglat) || GeoLoc.new
40
92
  end
41
93
 
42
94
  def self.do_geocode(address, options = {})
43
95
  address_str = address.is_a?(GeoLoc) ? address.to_geocodable_s : address
44
- call_geocoder_service(address_str)
96
+ call_geocoder_service(address_str) || GeoLoc.new
45
97
  end
46
98
 
47
99
  def self.xml2GeoLoc(xml, address="")
@@ -63,7 +115,7 @@ module Geokit
63
115
 
64
116
  return geoloc
65
117
  else
66
- logger.ingo "Yandex was unable to geocode address: #{address}"
118
+ logger.info("Yandex was unable to geocode address: #{address}")
67
119
  return GeoLoc.new
68
120
  end
69
121
  end
@@ -73,21 +125,22 @@ module Geokit
73
125
  res.provider = 'yandex'
74
126
 
75
127
  # basics
76
- coordinates = doc.elements['.//Point/pos'].text.to_s.split(' ')
77
- res.lng = coordinates[0]
78
- res.lat = coordinates[1]
128
+ res.ymaps_lnglat = doc.elements['.//Point/pos'].text.to_s.split(' ')
79
129
 
80
130
  # extended -- false if not available
81
- res.city = doc.elements['.//LocalityName'].try(:text)
82
- res.state = doc.elements['.//AdministrativeAreaName'].try(:text)
83
- res.province = doc.elements['.//SubAdministrativeAreaName'].try(:text)
84
- res.full_address = doc.elements['.//GeocoderMetaData/text'].try(:text)
85
- res.zip = doc.elements['.//PostalCodeNumber'].try(:text)
86
- res.street_address = doc.elements['.//ThoroughfareName'].try(:text)
87
- res.country = doc.elements['.//CountryName'].try(:text)
88
- res.district = doc.elements['.//DependentLocalityName'].try(:text)
89
-
90
- # TODO: translate accuracy into Yahoo-style token address, street, zip, zip+4, city, state, country
131
+ res.full_address = doc.elements['.//GeocoderMetaData/text'].try(:text)
132
+ res.country = doc.elements['.//CountryName'].try(:text)
133
+ res.state = doc.elements['.//AdministrativeAreaName'].try(:text)
134
+ res.province = doc.elements['.//SubAdministrativeAreaName'].try(:text)
135
+ res.city = doc.elements['.//LocalityName'].try(:text)
136
+ res.district = doc.elements['.//DependentLocalityName'].try(:text)
137
+ res.street_name = doc.elements['.//ThoroughfareName'].try(:text)
138
+ res.street_number = doc.elements['.//PremiseNumber'].try(:text)
139
+ res.zip = doc.elements['.//PostalCodeNumber'].try(:text)
140
+
141
+ res.kind = doc.elements['.//GeocoderMetaData/kind'].try(:text)
142
+ res.accuracy = KIND_ACCURACY_MAP.fetch(res.kind) { 0 } if res.kind.present?
143
+ res.precision = PRECISIONS[res.accuracy]
91
144
 
92
145
  if suggested_bounds = doc.elements['.//boundedBy']
93
146
  res.suggested_bounds = Bounds.normalize(
@@ -97,7 +150,6 @@ module Geokit
97
150
  end
98
151
 
99
152
  res.success = true
100
-
101
153
  res
102
154
  end
103
155
  end
@@ -0,0 +1,22 @@
1
+ require 'geokit/geocoders'
2
+
3
+ module Geokit
4
+ module Inflector
5
+ if ''.respond_to?(:bytesize) # Ruby 1.9
6
+ def bytesize(string)
7
+ string.bytesize
8
+ end
9
+ else # Ruby 1.8
10
+ def bytesize(string)
11
+ string.size
12
+ end
13
+ end
14
+ module_function :bytesize
15
+
16
+ def url_escape(s)
17
+ s.gsub(/([^ a-zA-Z0-9_.-]+)/nu) {
18
+ '%' + $1.unpack('H2' * bytesize($1)).join('%').upcase
19
+ }.tr(' ', '+')
20
+ end
21
+ end
22
+ end
@@ -6,6 +6,14 @@ module YMaps
6
6
 
7
7
  def self.geocode(query)
8
8
  require 'geokit/geocoders/yandex_geocoder'
9
- Geokit::Geocoders::Yandex.geocode(query)
9
+ Geokit::Geocoders::YandexGeocoder.geocode(query)
10
10
  end
11
11
  end
12
+
13
+ if defined? ActionView
14
+ ActionView::Base.send(:include, YMaps::ActionView::Helpers)
15
+ end
16
+
17
+ if defined? Mime
18
+ Mime::Type.register 'application/xml', :ymapsml
19
+ end
@@ -3,15 +3,15 @@ module YMaps
3
3
  module HtmlHelper
4
4
  class StaticMapPoint < Struct.new('MapPoint', :style, :color, :size, :number, :lat, :lng)
5
5
  def to_s
6
- "#{ll},#{style}#{color}#{size}#{number}"
6
+ "#{ymaps_lnglat},#{style}#{color}#{size}#{number}"
7
7
  end
8
8
 
9
- def ll
10
- @ll ||= "#{lat},#{lng}"
9
+ def ymaps_lnglat
10
+ @ymaps_lnglat ||= "#{lng},#{lat}"
11
11
  end
12
12
 
13
- def ll=(latlng)
14
- @ll = latlng
13
+ def ymaps_lnglat=(latlng)
14
+ @ymaps_lnglat = latlng
15
15
  end
16
16
 
17
17
  def attributes=(attrs)
@@ -24,10 +24,13 @@ module YMaps
24
24
  def map_link(resource = nil, options = {})
25
25
  resource, options = nil, resource if resource.is_a?(Hash)
26
26
 
27
+ url_params = options.delete(:url) { {} }
27
28
  href = if resource
28
- polymorphic_url(resource, :format => :ymapsml)
29
+ polymorphic_url(resource, {:format => :ymapsml}.merge(url_params))
29
30
  else
30
- url_for(:format => :ymapsml, :only_path => false, :time => Time.now)
31
+ url_for({:format => :ymapsml,
32
+ :only_path => false,
33
+ :time => Time.now}.merge(url_params))
31
34
  end
32
35
 
33
36
  tag(:link,
@@ -37,14 +40,22 @@ module YMaps
37
40
  :type => 'application/ymapsml+xml'))
38
41
  end
39
42
 
40
- def ymaps_include_tag(key = nil)
43
+ def ymaps_javascript_path(key = nil)
41
44
  key ||= YMaps.key
42
- javascript_include_tag("http://api-maps.yandex.ru/1.1/index.xml?key=#{key}")
45
+ "http://api-maps.yandex.ru/1.1/index.xml?key=#{key}"
46
+ end
47
+
48
+ def ymaps_include_tag(key = nil)
49
+ javascript_include_tag(ymaps_javascript_path)
43
50
  end
44
51
 
45
52
  def static_map(resources, options = {})
46
53
  title = options.delete(:title) { resources.to_s }
47
54
  map_type = options.delete(:map) { 'map' }
55
+ width = options.delete(:width) { 600 }
56
+ height = options.delete(:height) { 450 }
57
+ map_size = "#{width},#{height}"
58
+ zoom = options.delete(:zoom) { 16 }
48
59
 
49
60
  common_point = StaticMapPoint.new(
50
61
  options.delete(:style) { 'pm' },
@@ -54,18 +65,20 @@ module YMaps
54
65
  )
55
66
 
56
67
  collection = Array(resources).inject([]) do |result, resource|
57
- common_point.ll = resource.latlng.ll
68
+ common_point.ymaps_lnglat = resource.latlng.ymaps_lnglat
58
69
  common_point.number += 1
59
70
  result << common_point.to_s
60
71
  result
61
72
  end.join('~')
62
73
 
63
74
  content_tag(:div, :class => 'b-map') do
64
- image_tag("http://static-maps.yandex.ru/1.x/?key=#{YMaps.key}&l=#{map_type}&pt=#{collection}",
65
- :title => title,
66
- :alt => title,
67
- :class => 'static'
68
- )
75
+ image_tag("http://static-maps.yandex.ru/1.x/?key=#{YMaps.key}&l=#{map_type}&pt=#{collection}&size=#{map_size}&z=#{zoom}", options.merge(
76
+ :title => title,
77
+ :alt => title,
78
+ :class => 'static',
79
+ :width => width,
80
+ :height => height
81
+ ))
69
82
  end
70
83
  end
71
84
 
@@ -28,7 +28,7 @@ module YMaps
28
28
  class Builder
29
29
  YMAPS_TAG_NAMES = %w(GeoObject GeoObjectCollection style ymaps AnyMetaData).map(&:to_sym)
30
30
  GML_TAG_NAMES = %w(boundedBy description Envelope exterior featureMember
31
- featureMembers interior LineString LinearString lowerCorner
31
+ featureMembers interior LineString LinearRing lowerCorner
32
32
  metaDataProperty name Point Polygon pos posList upperCorner).map(&:to_sym)
33
33
  REPR_TAG_NAMES = %w(balloonContentStyle fill fillColor hintContentStyle iconContentStyle
34
34
  lineStyle href iconStyle mapType offset outline parentStyle polygonStyle
@@ -39,9 +39,18 @@ module YMaps
39
39
  @xml = xml
40
40
  end
41
41
 
42
+ protected
43
+ def prefixed_method(method, *arguments, &block)
44
+ @xml.__send__(*xmlns_prefix!(method, arguments), &block)
45
+ end
46
+
47
+ def link_to(name, href)
48
+ prefixed_method(name, "\##{href}")
49
+ end
50
+
42
51
  private
43
52
  def method_missing(method, *arguments, &block)
44
- @xml.__send__(*xmlns_prefix!(method, arguments), &block)
53
+ prefixed_method(method, *arguments, &block)
45
54
  end
46
55
 
47
56
  def xmlns_prefix!(method, arguments)
@@ -56,6 +65,15 @@ module YMaps
56
65
  end
57
66
 
58
67
  class YMapsReprBuilder < Builder
68
+ ACCEPTABLE_STYLES = {
69
+ :balloon_content => [:template],
70
+ :hint_content => [:template],
71
+ :icon => [:href, :offset, :shadow, :size, :template],
72
+ :icon_content => [:template],
73
+ :line => [:stroke_color, :stroke_width],
74
+ :polygon => [:fill, :fill_color, :outline, :stroke_color, :stroke_width],
75
+ }
76
+
59
77
  def view(options = {})
60
78
  View {
61
79
  if options[:type]
@@ -65,12 +83,28 @@ module YMaps
65
83
  }
66
84
  end
67
85
 
86
+ # Add style definition
87
+ # @param [Symbol, String] id style name
88
+ # @param [Hash] options style options
68
89
  def style(id, options = {})
90
+ options[:hasBalloon] = options.delete(:balloon) if options.key?(:balloon)
91
+ options[:hasHint] = options.delete(:hint) if options.key?(:hint)
92
+ parent = options.delete(:parent) { false }
69
93
  Style(options.merge('gml:id' => id.to_s)) {
94
+ link_to(:parentStyle, parent) if parent
70
95
  yield
71
96
  }
72
97
  end
73
98
 
99
+ ACCEPTABLE_STYLES.each do |name, values|
100
+ define_method(name) do |options|
101
+ tag_name = "#{ActiveSupport::Inflector.camelize(name.to_s, false)}Style"
102
+ send(tag_name) do
103
+ style_options(options, values)
104
+ end
105
+ end
106
+ end
107
+
74
108
  def template(id, template_text = nil)
75
109
  Template('gml:id' => id.to_s) do
76
110
  text do
@@ -79,10 +113,42 @@ module YMaps
79
113
  end
80
114
  end
81
115
 
82
- def balloon_content(template)
83
- balloonContentStyle {
84
- @xml.repr(:template, "\##{template}")
85
- }
116
+ protected
117
+
118
+ def style_options(options = {}, acceptable = nil)
119
+ if acceptable
120
+ options.assert_valid_keys(acceptable)
121
+ end
122
+ # Filling options
123
+ fill(options[:fill] ? 1 : 0) if options.key?(:fill)
124
+ fillColor(options[:fill_color]) if options.key?(:fill_color)
125
+
126
+ # Outline options
127
+ outline(options[:outline] ? 1 : 0) if options.key?(:outline)
128
+ strokeColor(options[:stroke_color]) if options.key?(:stroke_color)
129
+ strokeWidth(options[:stroke_width]) if options.key?(:stroke_width)
130
+
131
+ href(options[:href]) if options.key?(:href)
132
+ size(*Array(options[:size])) if options.key?(:size)
133
+ offset(*Array(options[:offset])) if options.key?(:offset)
134
+ link_to(:template, options[:template]) if options.key?(:template)
135
+ shadow do
136
+ style_options(options[:shadow], [:href, :size, :template, :offset])
137
+ end if options.key?(:shadow)
138
+ end
139
+
140
+ def size(x, y = nil)
141
+ if x.is_a?(Hash)
142
+ x, y = x[:x], x[:y]
143
+ end
144
+ prefixed_method(:size, :x => x, :y => y)
145
+ end
146
+
147
+ def offset(x, y = nil)
148
+ if x.is_a?(Hash)
149
+ x, y = x[:x], x[:y]
150
+ end
151
+ prefixed_method(:offset, :x => x, :y => y)
86
152
  end
87
153
  end
88
154
 
@@ -113,7 +179,7 @@ module YMaps
113
179
 
114
180
  def point(latlng)
115
181
  Point {
116
- pos(latlng.pos)
182
+ pos(latlng.gml_pos)
117
183
  }
118
184
  end
119
185
 
@@ -1,53 +1,52 @@
1
1
  # Generated by jeweler
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ymaps}
8
- s.version = "0.0.2"
8
+ s.version = "0.0.3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Alexander Semyonov"]
12
- s.date = %q{2010-04-03}
12
+ s.date = %q{2011-01-27}
13
13
  s.description = %q{Different helpers for generating YMapsML, using YMaps widgets and geocoding via Yandex.Maps}
14
14
  s.email = %q{rotuka@rotuka.com}
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE",
17
- "README.rdoc"
17
+ "README.rdoc"
18
18
  ]
19
19
  s.files = [
20
20
  ".document",
21
- ".gitignore",
22
- "LICENSE",
23
- "README.rdoc",
24
- "Rakefile",
25
- "VERSION",
26
- "init.rb",
27
- "lib/geokit/geocoders/yandex_geocoder.rb",
28
- "lib/ymaps.rb",
29
- "lib/ymaps/action_view.rb",
30
- "lib/ymaps/action_view/html_helper.rb",
31
- "lib/ymaps/action_view/ymapsml_helper.rb",
32
- "test/helper.rb",
33
- "test/test_ymaps.rb",
34
- "ymaps.gemspec"
21
+ "LICENSE",
22
+ "README.rdoc",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "init.rb",
26
+ "lib/geokit/geocoders/yandex_geocoder.rb",
27
+ "lib/geokit/inflector.rb",
28
+ "lib/ymaps.rb",
29
+ "lib/ymaps/action_view.rb",
30
+ "lib/ymaps/action_view/html_helper.rb",
31
+ "lib/ymaps/action_view/ymapsml_helper.rb",
32
+ "test/helper.rb",
33
+ "test/test_ymaps.rb",
34
+ "ymaps.gemspec"
35
35
  ]
36
36
  s.homepage = %q{http://github.com/rotuka/ymaps}
37
- s.rdoc_options = ["--charset=UTF-8"]
38
37
  s.require_paths = ["lib"]
39
- s.rubygems_version = %q{1.3.6}
38
+ s.rubygems_version = %q{1.3.7}
40
39
  s.summary = %q{Helpers for using YMaps}
41
40
  s.test_files = [
42
41
  "test/helper.rb",
43
- "test/test_ymaps.rb"
42
+ "test/test_ymaps.rb"
44
43
  ]
45
44
 
46
45
  if s.respond_to? :specification_version then
47
46
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
48
47
  s.specification_version = 3
49
48
 
50
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
49
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
51
50
  s.add_development_dependency(%q<shoulda>, [">= 0"])
52
51
  s.add_development_dependency(%q<yard>, [">= 0"])
53
52
  s.add_runtime_dependency(%q<geokit>, ["= 1.5.0"])
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 2
9
- version: 0.0.2
8
+ - 3
9
+ version: 0.0.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - Alexander Semyonov
@@ -14,13 +14,14 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-03 00:00:00 +04:00
17
+ date: 2011-01-27 00:00:00 +03:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: shoulda
22
22
  prerelease: false
23
23
  requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
24
25
  requirements:
25
26
  - - ">="
26
27
  - !ruby/object:Gem::Version
@@ -33,6 +34,7 @@ dependencies:
33
34
  name: yard
34
35
  prerelease: false
35
36
  requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
36
38
  requirements:
37
39
  - - ">="
38
40
  - !ruby/object:Gem::Version
@@ -45,6 +47,7 @@ dependencies:
45
47
  name: geokit
46
48
  prerelease: false
47
49
  requirement: &id003 !ruby/object:Gem::Requirement
50
+ none: false
48
51
  requirements:
49
52
  - - "="
50
53
  - !ruby/object:Gem::Version
@@ -66,13 +69,13 @@ extra_rdoc_files:
66
69
  - README.rdoc
67
70
  files:
68
71
  - .document
69
- - .gitignore
70
72
  - LICENSE
71
73
  - README.rdoc
72
74
  - Rakefile
73
75
  - VERSION
74
76
  - init.rb
75
77
  - lib/geokit/geocoders/yandex_geocoder.rb
78
+ - lib/geokit/inflector.rb
76
79
  - lib/ymaps.rb
77
80
  - lib/ymaps/action_view.rb
78
81
  - lib/ymaps/action_view/html_helper.rb
@@ -85,11 +88,12 @@ homepage: http://github.com/rotuka/ymaps
85
88
  licenses: []
86
89
 
87
90
  post_install_message:
88
- rdoc_options:
89
- - --charset=UTF-8
91
+ rdoc_options: []
92
+
90
93
  require_paths:
91
94
  - lib
92
95
  required_ruby_version: !ruby/object:Gem::Requirement
96
+ none: false
93
97
  requirements:
94
98
  - - ">="
95
99
  - !ruby/object:Gem::Version
@@ -97,6 +101,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
97
101
  - 0
98
102
  version: "0"
99
103
  required_rubygems_version: !ruby/object:Gem::Requirement
104
+ none: false
100
105
  requirements:
101
106
  - - ">="
102
107
  - !ruby/object:Gem::Version
@@ -106,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
111
  requirements: []
107
112
 
108
113
  rubyforge_project:
109
- rubygems_version: 1.3.6
114
+ rubygems_version: 1.3.7
110
115
  signing_key:
111
116
  specification_version: 3
112
117
  summary: Helpers for using YMaps
data/.gitignore DELETED
@@ -1,23 +0,0 @@
1
- ## MAC OS
2
- .DS_Store
3
-
4
- ## TEXTMATE
5
- *.tmproj
6
- tmtags
7
-
8
- ## EMACS
9
- *~
10
- \#*
11
- .\#*
12
-
13
- ## VIM
14
- *.swp
15
-
16
- ## PROJECT::GENERAL
17
- coverage
18
- rdoc
19
- doc
20
- pkg
21
- .yardoc
22
-
23
- ## PROJECT::SPECIFIC