Farmbot-Web-App/app/controllers/api/points_controller.rb

106 lines
3.4 KiB
Ruby

require_relative "../../lib/hstore_filter"
module Api
class PointsController < Api::AbstractController
class BadPointerType < StandardError; end
ALL_POINTERS = Point::POINTER_KINDS.join(", ")
# How long we wait until emptying out the discarded points bin.
EXPIRY = 2.months
BAD_POINTER_TYPE = <<~XYZ
Please provide a JSON object with a `pointer_type` that matches one
of the following values: %s
XYZ
# WHY 1000?:
# * This limit is placed for _technical_ reasons, not business reasons.
# * 2019 RPis + Frontend UI cannot reliably handle > 1000 points.
# * Bots with > 800 points are outliers. Most users simply don't have that
# many plants
# * An XL bot at 100% capacity and 1000 evenly space plants =
# 5 inch point grid. Smaller bed = higher resolution.
POINT_HARD_LIMIT = 10 #00 # Not allowed to exceed this.
POINT_SOFT_LIMIT = (POINT_HARD_LIMIT * 0.8).to_i
rescue_from BadPointerType do |exc|
sorry BAD_POINTER_TYPE.split(/\n+/).join(" ") % [ALL_POINTERS], 422
end
def index
Point.discarded.where("discarded_at < ?", Time.now - EXPIRY).destroy_all
render json: points
end
def show
render json: points.find(params[:id])
end
def search
mutate Points::Query.run(raw_json, points: points)
end
def create
case point_count Point.where(device_id: current_device.id).count
when (0..POINT_SOFT_LIMIT)
mutate pointer_klass::Create.run(raw_json, device_params)
when (POINT_SOFT_LIMIT..POINT_HARD_LIMIT)
raise "Do a soft warning here."
when (POINT_HARD_LIMIT..nil) # nil means Infinity
raise "Do a hard warning here."
end
end
def update
mutate Points::Update.run(raw_json, { point: point }, device_params)
end
def destroy
# TODO: We don't need to do batch requests like this any more.
# This should be removed when possible. -RC 1 AUG 2018
ids = params[:id].to_s.split(",").map(&:to_i)
mutate Points::Destroy.run({point_ids: ids}, device_params)
end
private
# HISTORICAL CONTEXT:
# Originally, Points, Tools and Plants were all independantly created as
# separate tables.
# As time progressed, we were able to merge them into a unified "points"
# table and use polymorphic associations to iron out the minor differences.
# Polymorphic assns later proved to be error prove and inadequate, leading
# to a conversion to single table inheritance.
# STI is the current mecahnism. The method is a relic from previous
# iterations
def pointer_klass
puts "TODO: Unify these in to a single mutation in prep for HTTP free "\
"resource creation"
case raw_json&.dig(:pointer_type)
when "GenericPointer" then Points
when "ToolSlot" then ToolSlots
when "Plant" then Plants
else; raise BadPointerType
end
end
def point
@point ||= points.find(params[:id])
end
def points
@points ||= unrestricted_archival_scope.where(device_params)
end
def unrestricted_archival_scope
case params[:filter]
when "all" then return Point.all
when "old" then return Point.discarded
end
return Point.kept
end
def device_params
@device_params ||= {device: current_device}
end
end
end