add starred to maps API (#719)
* add starred to maps API and endpoint to create/delete * add token to requests without token param * add minor version number to api version * metacode/user use uri in schema * make code climate happier
This commit is contained in:
parent
40453242fa
commit
d193c9a53c
16 changed files with 92 additions and 13 deletions
29
app/controllers/api/v2/stars_controller.rb
Normal file
29
app/controllers/api/v2/stars_controller.rb
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
module Api
|
||||||
|
module V2
|
||||||
|
class StarsController < RestfulController
|
||||||
|
skip_before_action :load_resource
|
||||||
|
|
||||||
|
def create
|
||||||
|
@map = Map.find(params[:id])
|
||||||
|
@star = Star.new(user: current_user, map: @map)
|
||||||
|
authorize @map, :star?
|
||||||
|
create_action
|
||||||
|
|
||||||
|
if @star.errors.empty?
|
||||||
|
render json: @map, scope: default_scope, serializer: MapSerializer, root: serializer_root
|
||||||
|
else
|
||||||
|
respond_with_errors
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
@map = Map.find(params[:id])
|
||||||
|
authorize @map, :unstar?
|
||||||
|
@star = @map.stars.find_by(user: current_user)
|
||||||
|
@star.destroy if @star.present?
|
||||||
|
head :no_content
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -39,15 +39,8 @@ class Map < ApplicationRecord
|
||||||
Perm.short(permission)
|
Perm.short(permission)
|
||||||
end
|
end
|
||||||
|
|
||||||
# return an array of the contributors to the map
|
|
||||||
def contributors
|
def contributors
|
||||||
contributors = []
|
mappings.map(&:user).uniq
|
||||||
|
|
||||||
mappings.each do |m|
|
|
||||||
contributors.push(m.user) unless contributors.include?(m.user)
|
|
||||||
end
|
|
||||||
|
|
||||||
contributors
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def editors
|
def editors
|
||||||
|
@ -88,6 +81,10 @@ class Map < ApplicationRecord
|
||||||
updated_at.strftime('%m/%d/%Y')
|
updated_at.strftime('%m/%d/%Y')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def starred_by_user?(user)
|
||||||
|
user.stars.where(map: self).exists?
|
||||||
|
end
|
||||||
|
|
||||||
def as_json(_options = {})
|
def as_json(_options = {})
|
||||||
json = super(methods: [:user_name, :user_image, :topic_count, :synapse_count, :contributor_count, :collaborator_ids, :screenshot_url], except: [:screenshot_content_type, :screenshot_file_size, :screenshot_file_name, :screenshot_updated_at])
|
json = super(methods: [:user_name, :user_image, :topic_count, :synapse_count, :contributor_count, :collaborator_ids, :screenshot_url], except: [:screenshot_content_type, :screenshot_file_size, :screenshot_file_name, :screenshot_updated_at])
|
||||||
json[:created_at_clean] = created_at_str
|
json[:created_at_clean] = created_at_str
|
||||||
|
|
|
@ -2,4 +2,5 @@
|
||||||
class Star < ActiveRecord::Base
|
class Star < ActiveRecord::Base
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
belongs_to :map
|
belongs_to :map
|
||||||
|
validates :map, uniqueness: { scope: :user, message: 'You have already starred this map' }
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,9 +7,14 @@ module Api
|
||||||
:desc,
|
:desc,
|
||||||
:permission,
|
:permission,
|
||||||
:screenshot,
|
:screenshot,
|
||||||
|
:starred,
|
||||||
:created_at,
|
:created_at,
|
||||||
:updated_at
|
:updated_at
|
||||||
|
|
||||||
|
def starred
|
||||||
|
object.starred_by_user?(scope[:current_user])
|
||||||
|
end
|
||||||
|
|
||||||
def self.embeddable
|
def self.embeddable
|
||||||
{
|
{
|
||||||
user: {},
|
user: {},
|
||||||
|
|
|
@ -65,7 +65,10 @@ Metamaps::Application.routes.draw do
|
||||||
namespace :v2, path: '/v2' do
|
namespace :v2, path: '/v2' do
|
||||||
resources :metacodes, only: [:index, :show]
|
resources :metacodes, only: [:index, :show]
|
||||||
resources :mappings, only: [:index, :create, :show, :update, :destroy]
|
resources :mappings, only: [:index, :create, :show, :update, :destroy]
|
||||||
resources :maps, only: [:index, :create, :show, :update, :destroy]
|
resources :maps, only: [:index, :create, :show, :update, :destroy] do
|
||||||
|
post :stars, to: 'stars#create', on: :member
|
||||||
|
delete :stars, to: 'stars#destroy', on: :member
|
||||||
|
end
|
||||||
resources :synapses, only: [:index, :create, :show, :update, :destroy]
|
resources :synapses, only: [:index, :create, :show, :update, :destroy]
|
||||||
resources :tokens, only: [:create, :destroy] do
|
resources :tokens, only: [:create, :destroy] do
|
||||||
get :my_tokens, on: :collection
|
get :my_tokens, on: :collection
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#%RAML 1.0
|
#%RAML 1.0
|
||||||
---
|
---
|
||||||
title: Metamaps
|
title: Metamaps
|
||||||
version: v2
|
version: v2.0
|
||||||
baseUri: https://metamaps.cc/api/v2
|
baseUri: https://metamaps.cc/api/v2
|
||||||
mediaType: application/json
|
mediaType: application/json
|
||||||
|
|
||||||
|
|
|
@ -94,3 +94,15 @@ post:
|
||||||
responses:
|
responses:
|
||||||
204:
|
204:
|
||||||
description: No content
|
description: No content
|
||||||
|
/stars:
|
||||||
|
post:
|
||||||
|
responses:
|
||||||
|
201:
|
||||||
|
description: Created
|
||||||
|
body:
|
||||||
|
application/json:
|
||||||
|
example: !include ../examples/map.json
|
||||||
|
delete:
|
||||||
|
responses:
|
||||||
|
204:
|
||||||
|
description: No content
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
"desc": "Example map for the API",
|
"desc": "Example map for the API",
|
||||||
"permission": "commons",
|
"permission": "commons",
|
||||||
"screenshot": "https://s3.amazonaws.com/metamaps-assets/site/missing-map.png",
|
"screenshot": "https://s3.amazonaws.com/metamaps-assets/site/missing-map.png",
|
||||||
|
"starred": false,
|
||||||
"created_at": "2016-03-26T08:02:05.379Z",
|
"created_at": "2016-03-26T08:02:05.379Z",
|
||||||
"updated_at": "2016-03-27T07:20:18.047Z",
|
"updated_at": "2016-03-27T07:20:18.047Z",
|
||||||
"topic_ids": [
|
"topic_ids": [
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
"desc": "Example map for the API",
|
"desc": "Example map for the API",
|
||||||
"permission": "commons",
|
"permission": "commons",
|
||||||
"screenshot": "https://s3.amazonaws.com/metamaps-assets/site/missing-map.png",
|
"screenshot": "https://s3.amazonaws.com/metamaps-assets/site/missing-map.png",
|
||||||
|
"starred": false,
|
||||||
"created_at": "2016-03-26T08:02:05.379Z",
|
"created_at": "2016-03-26T08:02:05.379Z",
|
||||||
"updated_at": "2016-03-27T07:20:18.047Z",
|
"updated_at": "2016-03-27T07:20:18.047Z",
|
||||||
"topic_ids": [
|
"topic_ids": [
|
||||||
|
|
|
@ -18,6 +18,9 @@
|
||||||
"format": "uri",
|
"format": "uri",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"starred": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"created_at": {
|
"created_at": {
|
||||||
"$ref": "_datetimestamp.json"
|
"$ref": "_datetimestamp.json"
|
||||||
},
|
},
|
||||||
|
@ -61,6 +64,7 @@
|
||||||
"desc",
|
"desc",
|
||||||
"permission",
|
"permission",
|
||||||
"screenshot",
|
"screenshot",
|
||||||
|
"starred",
|
||||||
"created_at",
|
"created_at",
|
||||||
"updated_at"
|
"updated_at"
|
||||||
]
|
]
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"icon": {
|
"icon": {
|
||||||
|
"format": "uri",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"avatar": {
|
"avatar": {
|
||||||
|
"format": "uri",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"generation": {
|
"generation": {
|
||||||
|
|
|
@ -16,7 +16,8 @@ RSpec.describe 'mappings API', type: :request do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'GET /api/v2/mappings/:id' do
|
it 'GET /api/v2/mappings/:id' do
|
||||||
get "/api/v2/mappings/#{mapping.id}"
|
get "/api/v2/mappings/#{mapping.id}", params: { access_token: token }
|
||||||
|
|
||||||
|
|
||||||
expect(response).to have_http_status(:success)
|
expect(response).to have_http_status(:success)
|
||||||
expect(response).to match_json_schema(:mapping)
|
expect(response).to match_json_schema(:mapping)
|
||||||
|
|
|
@ -16,7 +16,7 @@ RSpec.describe 'maps API', type: :request do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'GET /api/v2/maps/:id' do
|
it 'GET /api/v2/maps/:id' do
|
||||||
get "/api/v2/maps/#{map.id}"
|
get "/api/v2/maps/#{map.id}", params: { access_token: token }
|
||||||
|
|
||||||
expect(response).to have_http_status(:success)
|
expect(response).to have_http_status(:success)
|
||||||
expect(response).to match_json_schema(:map)
|
expect(response).to match_json_schema(:map)
|
||||||
|
@ -45,6 +45,23 @@ RSpec.describe 'maps API', type: :request do
|
||||||
expect(Map.count).to eq 0
|
expect(Map.count).to eq 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'POST /api/v2/maps/:id/stars' do
|
||||||
|
post "/api/v2/maps/#{map.id}/stars", params: { access_token: token }
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
expect(response).to match_json_schema(:map)
|
||||||
|
expect(user.stars.count).to eq 1
|
||||||
|
expect(map.stars.count).to eq 1
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'DELETE /api/v2/maps/:id/stars' do
|
||||||
|
create(:star, map: map, user: user)
|
||||||
|
delete "/api/v2/maps/#{map.id}/stars", params: { access_token: token }
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:no_content)
|
||||||
|
expect(user.stars.count).to eq 0
|
||||||
|
expect(map.stars.count).to eq 0
|
||||||
|
end
|
||||||
|
|
||||||
context 'RAML example' do
|
context 'RAML example' do
|
||||||
let(:resource) { get_json_example(:map) }
|
let(:resource) { get_json_example(:map) }
|
||||||
let(:collection) { get_json_example(:maps) }
|
let(:collection) { get_json_example(:maps) }
|
||||||
|
|
|
@ -16,7 +16,8 @@ RSpec.describe 'topics API', type: :request do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'GET /api/v2/topics/:id' do
|
it 'GET /api/v2/topics/:id' do
|
||||||
get "/api/v2/topics/#{topic.id}"
|
get "/api/v2/topics/#{topic.id}", params: { access_token: token }
|
||||||
|
|
||||||
|
|
||||||
expect(response).to have_http_status(:success)
|
expect(response).to have_http_status(:success)
|
||||||
expect(response).to match_json_schema(:topic)
|
expect(response).to match_json_schema(:topic)
|
||||||
|
|
5
spec/factories/stars.rb
Normal file
5
spec/factories/stars.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
FactoryGirl.define do
|
||||||
|
factory :star do
|
||||||
|
end
|
||||||
|
end
|
Loading…
Add table
Reference in a new issue