Wrote tests for Point#create
parent
83511480cc
commit
1f4db54e70
|
@ -0,0 +1,34 @@
|
|||
module Api
|
||||
class PointsController < Api::AbstractController
|
||||
|
||||
def index
|
||||
render json: Point.where(device_params)
|
||||
end
|
||||
|
||||
def create
|
||||
mutate Points::Create.run(raw_json, device_params)
|
||||
end
|
||||
|
||||
def update
|
||||
mutate Points::Update.run raw_json, { point: point }, device_params
|
||||
end
|
||||
|
||||
def destroy
|
||||
render json: point.destroy! && ""
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def point
|
||||
@point ||= points.find(params[:id])
|
||||
end
|
||||
|
||||
def points
|
||||
Point.where(device_params)
|
||||
end
|
||||
|
||||
def device_params
|
||||
@device_params ||= {device: current_device}
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,20 @@
|
|||
module Mutations
|
||||
class HstoreFilter < AdditionalFilter
|
||||
# At a minimum, expect the input to respond to these methods.
|
||||
HASHY_METHODS = [:[], :[]=, :map]
|
||||
def filter(input)
|
||||
not_hash = HASHY_METHODS
|
||||
.map{|x| input.respond_to?(x) }
|
||||
.uniq
|
||||
.include?(false)
|
||||
return [input, :not_hash] if not_hash
|
||||
output = input
|
||||
.map{|x| Pair.new(*x) }
|
||||
.inject({}) do |hash, pair|
|
||||
hash[pair.head.to_sym] = pair.tail.to_s
|
||||
hash
|
||||
end
|
||||
[output, nil]
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,11 @@
|
|||
# Every now and then, I need an array with EXACTLY two elements,
|
||||
# or a hash with EXACTLY one key/value. It always felt hacky.
|
||||
# I'm surprised this is not in the STDLIB. Please submit an issue if
|
||||
# it is.
|
||||
class Pair
|
||||
attr_accessor :head, :tail
|
||||
|
||||
def initialize(h, t)
|
||||
@head, @tail = h, t
|
||||
end
|
||||
end
|
|
@ -0,0 +1,3 @@
|
|||
class Point < ApplicationRecord
|
||||
belongs_to :device
|
||||
end
|
|
@ -0,0 +1,16 @@
|
|||
module Points
|
||||
class Create < Mutations::Command
|
||||
required do
|
||||
model :device, class: Device
|
||||
float :x
|
||||
float :y
|
||||
float :z
|
||||
float :radius
|
||||
hstore :meta
|
||||
end
|
||||
|
||||
def execute
|
||||
Point.create!(inputs)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,22 @@
|
|||
module Points
|
||||
class Update < Mutations::Command
|
||||
required do
|
||||
model :device, class: Device
|
||||
end
|
||||
|
||||
optional do
|
||||
float :x
|
||||
float :y
|
||||
float :radius
|
||||
hash :meta do
|
||||
string :*
|
||||
boolean :*
|
||||
float :*
|
||||
end
|
||||
end
|
||||
|
||||
def execute
|
||||
Point.create!(inputs)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,3 @@
|
|||
class PointSerializer < ActiveModel::Serializer
|
||||
attributes :id, :x, :y, :z, :radius, :created_at, :meta
|
||||
end
|
|
@ -1,28 +1,25 @@
|
|||
FarmBot::Application.routes.draw do
|
||||
|
||||
namespace :api, defaults: {format: :json}, constraints: { format: 'json' } do
|
||||
resource :sync, only: [:show]
|
||||
resource :public_key, only: [:show]
|
||||
resource :tokens, only: [:create]
|
||||
resource :users, only: [:create, :update, :destroy]
|
||||
resource :device, only: [:show, :destroy, :create, :update]
|
||||
resources :images, only: [:create, :destroy, :show, :index]
|
||||
resources :plants, only: [:create, :destroy, :index, :update]
|
||||
resources :images, only: [:create, :destroy, :show, :index]
|
||||
resources :plants, only: [:create, :destroy, :index, :update]
|
||||
resources :regimens, only: [:create, :destroy, :index, :update]
|
||||
resources :planting_area, only: [:create, :destroy]
|
||||
resources :peripherals, only: [:create, :destroy, :index]
|
||||
resources :corpuses, only: [:index, :show]
|
||||
resources :tool_bays, only: [:show, :index, :update]
|
||||
resources :logs, only: [:index, :create, :destroy]
|
||||
resources :sequences, only: [:create, :update, :destroy, :index, :show]
|
||||
resources :farm_events, only: [:create, :update, :destroy, :index]
|
||||
resources :tool_slots, only: [:create, :show, :index, :destroy, :update]
|
||||
resources :tools, only: [:create, :show, :index, :destroy, :update]
|
||||
resources :points, only: [:create, :show, :index, :destroy, :update]
|
||||
resource :sync, only: [:show]
|
||||
resource :public_key, only: [:show]
|
||||
resource :tokens, only: [:create]
|
||||
resource :users, only: [:create, :update, :destroy]
|
||||
resource :device, only: [:show, :destroy, :create, :update]
|
||||
resources :password_resets, only: [:create, :update]
|
||||
resources :regimens, only: [:create, :destroy, :index, :update]
|
||||
resources :planting_area, only: [:create, :destroy]
|
||||
resources :peripherals, only: [:create, :destroy, :index]
|
||||
resources :corpuses, only: [:index, :show]
|
||||
resources :tool_bays, only: [:show, :index, :update]
|
||||
resources :logs, only: [:index, :create, :destroy]
|
||||
resources :sequences, only: [:create, :update, :destroy,
|
||||
:index, :show]
|
||||
resources :farm_events, only: [:create, :update, :destroy,
|
||||
:index]
|
||||
resources :tool_slots, only: [:create, :show, :index,
|
||||
:destroy, :update]
|
||||
resources :tools, only: [:create, :show, :index,
|
||||
:destroy, :update]
|
||||
put "/password_resets" => "password_resets#update", as: :whatever
|
||||
put "/users/verify/:token" => "users#verify", as: :users_verify
|
||||
end
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
class CreatePoints < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
enable_extension "hstore"
|
||||
|
||||
create_table :points do |t|
|
||||
t.float :radius
|
||||
t.float :x
|
||||
t.float :y
|
||||
t.float :z
|
||||
t.references :device, foreign_key: true
|
||||
t.hstore :meta
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
add_index :points, :meta, using: :gin
|
||||
end
|
||||
end
|
19
db/schema.rb
19
db/schema.rb
|
@ -10,10 +10,11 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20170130154455) do
|
||||
ActiveRecord::Schema.define(version: 20170207132639) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
enable_extension "hstore"
|
||||
|
||||
create_table "delayed_jobs", force: :cascade do |t|
|
||||
t.integer "priority", default: 0, null: false
|
||||
|
@ -108,6 +109,19 @@ ActiveRecord::Schema.define(version: 20170130154455) do
|
|||
t.index ["planting_area_id"], name: "index_plants_on_planting_area_id", using: :btree
|
||||
end
|
||||
|
||||
create_table "points", force: :cascade do |t|
|
||||
t.float "radius"
|
||||
t.float "x"
|
||||
t.float "y"
|
||||
t.float "z"
|
||||
t.integer "device_id"
|
||||
t.hstore "meta"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["device_id"], name: "index_points_on_device_id", using: :btree
|
||||
t.index ["meta"], name: "index_points_on_meta", using: :gin
|
||||
end
|
||||
|
||||
create_table "regimen_items", force: :cascade do |t|
|
||||
t.bigint "time_offset"
|
||||
t.integer "regimen_id"
|
||||
|
@ -124,8 +138,8 @@ ActiveRecord::Schema.define(version: 20170130154455) do
|
|||
end
|
||||
|
||||
create_table "sequence_dependencies", force: :cascade do |t|
|
||||
t.integer "dependency_id"
|
||||
t.string "dependency_type"
|
||||
t.integer "dependency_id"
|
||||
t.integer "sequence_id"
|
||||
t.index ["dependency_id"], name: "index_sequence_dependencies_on_dependency_id", using: :btree
|
||||
t.index ["dependency_type"], name: "index_sequence_dependencies_on_dependency_type", using: :btree
|
||||
|
@ -202,4 +216,5 @@ ActiveRecord::Schema.define(version: 20170130154455) do
|
|||
t.index ["email"], name: "index_users_on_email", unique: true, using: :btree
|
||||
end
|
||||
|
||||
add_foreign_key "points", "devices"
|
||||
end
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Api::PointsController do
|
||||
include Devise::Test::ControllerHelpers
|
||||
describe '#create' do
|
||||
let(:user) { FactoryGirl.create(:user) }
|
||||
let(:device) { user.device }
|
||||
|
||||
it 'creates a point' do
|
||||
sign_in user
|
||||
body = { x: 1,
|
||||
y: 2,
|
||||
z: 3,
|
||||
radius: 3,
|
||||
meta: { foo: "BAR" } }
|
||||
post :create, body: body.to_json,
|
||||
params: { format: :json }
|
||||
expect(response.status).to eq(200)
|
||||
expect(json[:x]).to eq(body[:x])
|
||||
expect(json[:y]).to eq(body[:y])
|
||||
expect(json[:z]).to eq(body[:z])
|
||||
expect(json[:radius]).to eq(body[:radius])
|
||||
expect(json[:meta][:foo]).to eq(body[:meta][:foo])
|
||||
expect(Point.last.device).to eq(device)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
FactoryGirl.define do
|
||||
factory :point do
|
||||
radius 1.5
|
||||
x 1.5
|
||||
y 1.5
|
||||
z 1.5
|
||||
device nil
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue