+ def tags_as_hash
+ tags
+ end
+
+ def tags
+ @tags ||= Hash[node_tags.collect { |t| [t.k, t.v] }]
+ end
+
+ attr_writer :tags
+
+ def add_tag_key_val(k, v)
+ @tags ||= {}
+
+ # duplicate tags are now forbidden, so we can't allow values
+ # in the hash to be overwritten.
+ raise OSM::APIDuplicateTagsError.new("node", id, k) if @tags.include? k
+
+ @tags[k] = v
+ end
+
+ ##
+ # are the preconditions OK? this is mainly here to keep the duck
+ # typing interface the same between nodes, ways and relations.
+ def preconditions_ok?
+ in_world?
+ end
+
+ ##
+ # dummy method to make the interfaces of node, way and relation
+ # more consistent.
+ def fix_placeholders!(_id_map, _placeholder_id = nil)
+ # nodes don't refer to anything, so there is nothing to do here
+ end
+
+ private
+
+ def save_with_history!
+ t = Time.now.getutc
+
+ self.version += 1
+ self.timestamp = t
+
+ Node.transaction do
+ # clone the object before saving it so that the original is
+ # still marked as dirty if we retry the transaction
+ clone.save!
+
+ # Create a NodeTag
+ tags = self.tags
+ NodeTag.where(:node_id => id).delete_all
+ tags.each do |k, v|
+ tag = NodeTag.new
+ tag.node_id = id
+ tag.k = k
+ tag.v = v
+ tag.save!
+ end
+
+ # Create an OldNode
+ old_node = OldNode.from_node(self)
+ old_node.timestamp = t
+ old_node.save_with_dependencies!
+
+ # tell the changeset we updated one element only
+ changeset.add_changes! 1
+
+ # save the changeset in case of bounding box updates
+ changeset.save!
+ end
+ end