Skip to content

Instantly share code, notes, and snippets.

@EvgenyKungurov
Last active November 13, 2019 08:35
Show Gist options
  • Save EvgenyKungurov/92a3e2ed8771fc6a8b47e1fc3317ee33 to your computer and use it in GitHub Desktop.
Save EvgenyKungurov/92a3e2ed8771fc6a8b47e1fc3317ee33 to your computer and use it in GitHub Desktop.
class Booking::Contract < Dry::Validation::Contract
params do
required(:seansId).filled(:integer)
required(:email).value(:string)
required(:seatIds).value(:array).each(:integer).filled
end
rule(:email) do
unless /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i.match?(value)
key.failure('has invalid format')
end
end
end
class BookingsController < ApplicationController
skip_before_action :verify_authenticity_token
def create
result = Booking::Create.new.call(params)
if result.success?
render json: result.value!, status: 201
else
render json: result.failure[:errors], status: result.failure[:http_code]
end
end
end
require 'dry/monads'
require 'dry/monads/do'
class Booking::Create
include Dry::Monads[:result]
include Dry::Monads::Do.for(:call)
def call(params)
return Failure(errors: 'not authorized', http_code: 401) unless authorized?
params = yield validate(params.to_unsafe_h)
params = yield check_seats(params)
bookings = yield create_booking(params.to_h)
Success(bookings)
end
private
def authorized?
RestClient.get
end
def validate(params)
result = Booking::Contract.new.call(params)
if result.success?
Success(result)
else
Failure(errors: result.errors.to_h, http_code: 422)
end
end
def create_booking(params)
bookings = ActiveRecord::Base.transaction do
params[:seatIds].each do |seat_id|
Booking.new(seat_id: seat_id, showing_id: params[:seansId], user: user(params[:email])).save!
end
end
Success(bookings)
rescue ActiveRecord::RecordNotUnique
Failure(errors: { seat_busy: params[:seatIds] })
end
def check_seats(params)
bookings = Booking.where(seat_id: params[:seatIds], showing_id: params[:seansId])
if bookings.present?
Failure(errors: { seat_busy: bookings.pluck(:seat_id) }, http_code: 409)
else
Success(params)
end
end
def user(email)
User.find_by(email: email) || User.create(email: email)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment