I created accept_waiver
endpoint that allows user to sign a gym waiver. The next step is adding validation method :sign_only_one_waiver
in the Gym model that validates user is just accepting only one waiver but the method is not being called.
I added on: :create
so the validation will run when the relationship UserGymWaiver is created, which means that user has signed a waiver but still creates the relationship even if errors exist.
app/models/gym.rb
class Gym < ApplicationRecord
include PgSearch::Model
validate :sign_only_one_waiver, on: :create
enum tier: {
standard: 'standard',
premium: 'premium'
}
has_many :gym_amenities, dependent: :destroy
has_many :amenities, through: :gym_amenities
reverse_geocoded_by :latitude, :longitude
pg_search_scope :search,
against: [
:name,
:tier
],
using: {
tsearch: {prefix: true}
}
def sign_only_one_waiver
user_waiver_collection = UserGymWaiver.where(gym_id: self.gym_id)
errors.add(:gym, "you can only sign one waiver") if user_waiver_collection.count > 1
end
app/controllers/api/v1/gyms_controller.rb
class Api::V1::GymsController < ApplicationController
before_action :load_gym, only: %i[accept_waiver]
def accept_waiver
gym_waiver = GymWaiver.find_by(gym_id: @gym.id)
waiver_signed_by_user = UserGymWaiver.create!(user_id: current_user.id,
gym_id: gym_waiver.gym_id)
render json: UserGymWaiverBlueprint.render(waiver_signed_by_user, root: :data)
end
private
def load_gym
@gym = Gym.find(params[:id])
end
CodePudding user response:
The validation is in the Gym
model, but you are creating a UserGymWaiver
, so this code belongs in the UserGymWaiver
model!
You could probably also solve it with a uniqueness validation and a scope, you can only allow one waiver per gym per user, you can find more info here:
https://guides.rubyonrails.org/active_record_validations.html#uniqueness
It could look something like this:
class UserGymWaiver < ApplicationRecord
belongs_to :gym
belongs_to :user
validates :user, uniqueness: { scope: :gym,
message: "you can only sign one waiver per gym" }
end