Wrote tests for Point#create

pull/315/head
Rick Carlino 2017-02-07 10:03:24 -06:00
parent 83511480cc
commit 1f4db54e70
12 changed files with 197 additions and 23 deletions

View File

@ -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

View File

@ -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

11
app/lib/pair.rb 100644
View File

@ -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

View File

@ -0,0 +1,3 @@
class Point < ApplicationRecord
belongs_to :device
end

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,3 @@
class PointSerializer < ActiveModel::Serializer
attributes :id, :x, :y, :z, :radius, :created_at, :meta
end

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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