]> git.openstreetmap.org Git - rails.git/blob - app/controllers/api/relations_controller.rb
Add frozen_string_literal comments to ruby files
[rails.git] / app / controllers / api / relations_controller.rb
1 # frozen_string_literal: true
2
3 module Api
4   class RelationsController < ApiController
5     before_action :check_api_writable, :only => [:create, :update, :destroy]
6     before_action :authorize, :only => [:create, :update, :destroy]
7
8     authorize_resource
9
10     before_action :require_public_data, :only => [:create, :update, :destroy]
11     before_action :set_request_formats, :except => [:create, :update, :destroy]
12     before_action :check_rate_limit, :only => [:create, :update, :destroy]
13
14     def index
15       raise OSM::APIBadUserInput, "The parameter relations is required, and must be of the form relations=id[,id[,id...]]" unless params["relations"]
16
17       ids = params["relations"].split(",").collect(&:to_i)
18
19       raise OSM::APIBadUserInput, "No relations were given to search for" if ids.empty?
20
21       @relations = Relation.includes(:relation_members, :element_tags).find(ids)
22
23       # Render the result
24       respond_to do |format|
25         format.xml
26         format.json
27       end
28     end
29
30     def show
31       relation = Relation.includes(:relation_members, :element_tags).find(params[:id])
32
33       response.last_modified = relation.timestamp unless params[:full]
34
35       @nodes = []
36       @ways = []
37       @relations = []
38
39       if relation.visible
40         if params[:full]
41           # with parameter :full
42           # returns representation of one relation object plus all its
43           # members, plus all nodes part of member ways
44
45           # first find the ids of nodes, ways and relations referenced by this
46           # relation - note that we exclude this relation just in case.
47
48           node_ids = relation.members.select { |m| m[0] == "Node" }.pluck(1)
49           way_ids = relation.members.select { |m| m[0] == "Way" }.pluck(1)
50           relation_ids = relation.members.select { |m| m[0] == "Relation" && m[1] != relation.id }.pluck(1)
51
52           # next load the relations and the ways.
53
54           relations = Relation.where(:id => relation_ids).includes(:element_tags)
55           ways = Way.where(:id => way_ids).includes(:way_nodes, :element_tags)
56
57           # now additionally collect nodes referenced by ways. Note how we
58           # recursively evaluate ways but NOT relations.
59
60           way_node_ids = ways.collect do |way|
61             way.way_nodes.collect(&:node_id)
62           end
63           node_ids += way_node_ids.flatten
64           nodes = Node.where(:id => node_ids.uniq).includes(:element_tags)
65
66           @nodes = []
67           nodes.each do |node|
68             next unless node.visible? # should be unnecessary if data is consistent.
69
70             @nodes << node
71           end
72
73           ways.each do |way|
74             next unless way.visible? # should be unnecessary if data is consistent.
75
76             @ways << way
77           end
78
79           relations.each do |rel|
80             next unless rel.visible? # should be unnecessary if data is consistent.
81
82             @relations << rel
83           end
84         end
85
86         # finally add self
87         @relations << relation
88
89         # Render the result
90         respond_to do |format|
91           format.xml
92           format.json
93         end
94       else
95         head :gone
96       end
97     end
98
99     def create
100       relation = Relation.from_xml(request.raw_post, :create => true)
101
102       Changeset.transaction do
103         relation.changeset&.lock!
104         relation.create_with_history current_user
105       end
106       render :plain => relation.id.to_s
107     end
108
109     def update
110       relation = Relation.find(params[:id])
111       new_relation = Relation.from_xml(request.raw_post)
112
113       raise OSM::APIBadUserInput, "The id in the url (#{relation.id}) is not the same as provided in the xml (#{new_relation.id})" unless new_relation && new_relation.id == relation.id
114
115       Changeset.transaction do
116         new_relation.changeset&.lock!
117         relation.update_from(new_relation, current_user)
118       end
119       render :plain => relation.version.to_s
120     end
121
122     def destroy
123       relation = Relation.find(params[:id])
124       new_relation = Relation.from_xml(request.raw_post)
125       if new_relation && new_relation.id == relation.id
126         Changeset.transaction do
127           new_relation.changeset&.lock!
128           relation.delete_with_history!(new_relation, current_user)
129         end
130         render :plain => relation.version.to_s
131       else
132         head :bad_request
133       end
134     end
135   end
136 end