+ # any remaining members must be new additions
+ changed_members += members
+
+ # update the members. first delete all the old members, as the new
+ # members may be in a different order and i don't feel like implementing
+ # a longest common subsequence algorithm to optimise this.
+ members = self.members
+ RelationMember.where(:relation_id => id).delete_all
+ members.each_with_index do |m, i|
+ mem = RelationMember.new
+ mem.relation_id = id
+ mem.sequence_id = i
+ mem.member_type = m[0]
+ mem.member_id = m[1]
+ mem.member_role = m[2]
+ mem.save!
+ end
+
+ old_relation = OldRelation.from_relation(self)
+ old_relation.timestamp = t
+ old_relation.save_with_dependencies!
+
+ # update the bbox of the changeset and save it too.
+ # discussion on the mailing list gave the following definition for
+ # the bounding box update procedure of a relation:
+ #
+ # adding or removing nodes or ways from a relation causes them to be
+ # added to the changeset bounding box. adding a relation member or
+ # changing tag values causes all node and way members to be added to the
+ # bounding box. this is similar to how the map call does things and is
+ # reasonable on the assumption that adding or removing members doesn't
+ # materially change the rest of the relation.
+ any_relations =
+ changed_members.collect { |_id, type| type == "relation" }
+ .inject(false) { |acc, elem| acc || elem }
+
+ update_members = if tags_changed || any_relations
+ # add all non-relation bounding boxes to the changeset
+ # FIXME: check for tag changes along with element deletions and
+ # make sure that the deleted element's bounding box is hit.
+ self.members
+ else
+ changed_members
+ end
+ update_members.each do |type, id, _role|
+ update_changeset_element(type, id) if type != "Relation"
+ end
+
+ # tell the changeset we updated one element only
+ changeset.add_changes! 1
+
+ # save the (maybe updated) changeset bounding box
+ changeset.save!