Class: OpenStreetMap::Element

Inherits:
Object
  • Object
show all
Includes:
ActiveModel::Validations
Defined in:
lib/open_street_map/element.rb

Overview

This is a virtual parent class for the OSM objects Node, Way and Relation.

Direct Known Subclasses

Node, Relation, Way

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attrs = {}) ⇒ Element

:nodoc:

Raises:

  • (NotImplementedError)


39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/open_street_map/element.rb', line 39

def initialize(attrs = {}) #:nodoc:
  raise NotImplementedError.new('Element is a virtual base class for the Node, Way, and Relation classes') if self.class == OpenStreetMap::Element
  attrs = {'version' => 1, 'uid' => 1}.merge(attrs.stringify_keys!)
  @id         = attrs['id'].to_i if attrs['id']
  @version    = attrs['version'].to_i
  @uid        = attrs['uid'].to_i
  @user       = attrs['user']
  @timestamp  = Time.parse(attrs['timestamp']) rescue nil
  @changeset  = attrs['changeset'].to_i
  @tags       = Tags.new
  add_tags(attrs['tag']) if attrs['tag']
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args) ⇒ Object

All other methods are mapped so its easy to access tags: For instance obj.name is the same as obj.tags. This works for getting and setting tags.

node = OpenStreetMap::Node.new
node.add_tags( 'highway' => 'residential', 'name' => 'Main Street' )
node.highway                   #=> 'residential'
node.highway = 'unclassified'  #=> 'unclassified'
node.name                      #=> 'Main Street'

In addition methods of the form key? are used to check boolean tags. For instance oneway can be ‘true’ or ‘yes’ or ‘1’, all meaning the same.

way.oneway?

will check this. It returns true if the value of this key is either ‘true’, ‘yes’ or ‘1’.



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/open_street_map/element.rb', line 208

def method_missing(method, *args)
  methodname = method.to_s
  if methodname.slice(-1, 1) == '='
    if args.size != 1
      raise ArgumentError.new("wrong number of arguments (#{args.size} for 1)")
    end
    tags[methodname.chop] = args[0]
  elsif methodname.slice(-1, 1) == '?'
    if args.size != 0
      raise ArgumentError.new("wrong number of arguments (#{args.size} for 0)")
    end
    tags[methodname.chop] =~ /^(true|yes|1)$/
  else
    if args.size != 0
      raise ArgumentError.new("wrong number of arguments (#{args.size} for 0)")
    end
    tags[methodname]
  end
end

Instance Attribute Details

#changesetObject

The changeset the last change of this object was made with.



28
29
30
# File 'lib/open_street_map/element.rb', line 28

def changeset
  @changeset
end

#idObject

Unique ID



7
8
9
# File 'lib/open_street_map/element.rb', line 7

def id
  @id
end

#tagsObject (readonly)

Tags for this object



31
32
33
# File 'lib/open_street_map/element.rb', line 31

def tags
  @tags
end

#timestampObject

Last change of this object (as read from file, it is not updated by operations to this object)



25
26
27
# File 'lib/open_street_map/element.rb', line 25

def timestamp
  @timestamp
end

#uidObject

The user id of the user who last edited this object (as read from file, it is not updated by operations to this object) API 0.6 and above only



21
22
23
# File 'lib/open_street_map/element.rb', line 21

def uid
  @uid
end

#userObject

The user who last edited this object (as read from file, it is not updated by operations to this object)



16
17
18
# File 'lib/open_street_map/element.rb', line 16

def user
  @user
end

#versionObject

The version of this object (as read from file, it is not updated by operations to this object) API 0.6 and above only



12
13
14
# File 'lib/open_street_map/element.rb', line 12

def version
  @version
end

Class Method Details

.from_api(id, api = OpenStreetMap::API.new) ⇒ Object

Get OpenStreetMap::Element from API

Raises:

  • (NotImplementedError)


34
35
36
37
# File 'lib/open_street_map/element.rb', line 34

def self.from_api(id, api=OpenStreetMap::API.new) #:nodoc:
    raise NotImplementedError.new('Element is a virtual base class for the Node, Way, and Relation classes') if self.class == OpenStreetMap::Element
    api.get_object(type, id)
end

Instance Method Details

#[](key) ⇒ Object

Get tag value



86
87
88
# File 'lib/open_street_map/element.rb', line 86

def [](key)
  tags[key]
end

#[]=(key, value) ⇒ Object

Set tag



91
92
93
# File 'lib/open_street_map/element.rb', line 91

def []=(key, value)
  tags[key] = value
end

#add_tags(new_tags) ⇒ Object

Add one or more tags to this object.

call-seq: add_tags(Hash) -> OsmObject



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/open_street_map/element.rb', line 99

def add_tags(new_tags)
  case new_tags
  when Array # Called with an array
    # Call recursively for each entry
    new_tags.each do |tag_hash|
      add_tags(tag_hash)
    end
  when Hash # Called with a hash
    #check if it is weird {'k' => 'key', 'v' => 'value'} syntax
    if (new_tags.size == 2 && new_tags.keys.include?('k') && new_tags.keys.include?('v'))
      # call recursively with values from k and v keys.
      add_tags({new_tags['k'] => new_tags['v']})
    else
      # OK, this seems to be a proper ruby hash with a single entry
      new_tags.each do |k,v|
        self.tags[k] = v
      end
    end
  end
  self    # return self so calls can be chained
end

#attribute_listObject

The list of attributes for this object



64
65
66
# File 'lib/open_street_map/element.rb', line 64

def attribute_list # :nodoc:
  [:id, :version, :uid, :user, :timestamp, :tags]
end

#attributesObject

Returns a hash of all non-nil attributes of this object.

Keys of this hash are :id, :user, and :timestamp. For a Node also :lon and :lat.

call-seq: attributes -> Hash



76
77
78
79
80
81
82
83
# File 'lib/open_street_map/element.rb', line 76

def attributes
  attrs = Hash.new
  attribute_list.each do |attribute|
    value = self.send(attribute)
    attrs[attribute] = value unless value.nil?
  end
  attrs
end

#get_history_from_api(api = OpenStreetMap::API.new) ⇒ Object

Get the history of this object from the API.

The optional parameter is an OpenStreetMap::API object. If none is specified the default OSM API is used.

Returns an array of OpenStreetMap::Node, OpenStreetMap::Way, or OpenStreetMap::Relation objects with all the versions.



186
187
188
# File 'lib/open_street_map/element.rb', line 186

def get_history_from_api(api=OpenStreetMap::API.new)
  api.get_history(type, self.id.to_i)
end

#get_relations_from_api(api = OpenStreetMap::API.new) ⇒ Object

Get all relations from the API that have his object as members.

The optional parameter is an OpenStreetMap::API object. If none is specified the default OSM API is used.

Returns an array of Relation objects or an empty array.



175
176
177
# File 'lib/open_street_map/element.rb', line 175

def get_relations_from_api(api=OpenStreetMap::API.new)
  api.get_relations_referring_to_object(type, self.id.to_i)
end

#initialize_copy(from) ⇒ Object



228
229
230
231
# File 'lib/open_street_map/element.rb', line 228

def initialize_copy(from)
  super
  @tags = from.tags.dup
end

#is_tagged?Boolean

Has this object any tags?

call-seq: is_tagged?

Returns:

  • (Boolean)


139
140
141
# File 'lib/open_street_map/element.rb', line 139

def is_tagged?
  ! @tags.empty?
end

#shape(geom, attributes) ⇒ Object

Create a new GeoRuby::Shp4r::ShpRecord with the geometry of this object and the given attributes.

This only works if the GeoRuby library is included.

geom

Geometry

attributes

Hash with attributes

call-seq: shape(attributes) -> GeoRuby::Shp4r::ShpRecord

Example:

require 'rubygems'
require 'geo_ruby'
node = Node(nil, nil, nil, 7.84, 54.34)
g = node.point
node.shape(g, :type => 'Pharmacy', :name => 'Hyde Park Pharmacy')


160
161
162
163
164
165
166
# File 'lib/open_street_map/element.rb', line 160

def shape(geom, attributes)
  fields = Hash.new
  attributes.each do |key, value|
    fields[key.to_s] = value
  end
  GeoRuby::Shp4r::ShpRecord.new(geom, fields)
end

#update_attributes(attribute_hash) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/open_street_map/element.rb', line 121

def update_attributes(attribute_hash)
  dirty = false
  attribute_hash.each do |key,value|
    if self.send(key).to_s != value.to_s
      self.send("#{key}=", value.to_s)
      dirty = true
    end
  end

  puts "returning #{dirty}"
  dirty
end