module ActsAsBookable::Bookable::Core::ClassMethods

Public Instance Methods

initialize_acts_as_bookable_core() click to toggle source

Initialize the core of Bookable

# File lib/acts_as_bookable/bookable/core.rb, line 14
def initialize_acts_as_bookable_core
  # Manage the options
  set_options
end
validate_booking_options!(options) click to toggle source

Check if options passed for booking this Bookable are valid

@raise ActsAsBookable::OptionsInvalid if options are not valid

# File lib/acts_as_bookable/bookable/core.rb, line 24
def validate_booking_options!(options)
  unpermitted_params = []
  required_params = {}

  #
  # Set unpermitted parameters and required parameters depending on Bookable options
  #

  # Switch :time_type
  case self.booking_opts[:time_type]
  # when :range, we need :time_start and :time_end
  when :range
    required_params[:time_start] = [Time,Date]
    required_params[:time_end] = [Time,Date]
    unpermitted_params << :time
  when :fixed
    required_params[:time] = [Time,Date]
    unpermitted_params << :time_start
    unpermitted_params << :time_end
  when :none
    unpermitted_params << :time_start
    unpermitted_params << :time_end
    unpermitted_params << :time
  end

  # Switch :capacity_type
  case self.booking_opts[:capacity_type]
  when :closed
    required_params[:amount] = [Integer]
  when :open
    required_params[:amount] = [Integer]
  when :none
    unpermitted_params << :amount
  end

  #
  # Actual validation
  #
  unpermitted_params = unpermitted_params
    .select{ |p| options.has_key?(p) }
    .map{ |p| "'#{p}'"}
  wrong_types = required_params
    .select{ |k,v| options.has_key?(k) && (v.select{|type| options[k].is_a?(type)}.length == 0) }
    .map{ |k,v| "'#{k}' must be a '#{v.join(' or ')}' but '#{options[k].class.to_s}' found" }
  required_params = required_params
    .select{ |k,v| !options.has_key?(k) }
    .map{ |k,v| "'#{k}'" }

  #
  # Raise OptionsInvalid if some invalid parameters were found
  #
  if unpermitted_params.length + required_params.length + wrong_types.length > 0
    message = ""
    message << " unpermitted parameters: #{unpermitted_params.join(',')}." if (unpermitted_params.length > 0)
    message << " missing parameters: #{required_params.join(',')}." if (required_params.length > 0)
    message << " parameters type mismatch: #{wrong_types.join(',')}" if (wrong_types.length > 0)
    raise ActsAsBookable::OptionsInvalid.new(self, message)
  end

  #
  # Convert options (Date to Time)
  #
  options[:time_start] = options[:time_start].to_time if options[:time_start].present?
  options[:time_end] = options[:time_end].to_time if options[:time_end].present?
  options[:time] = options[:time].to_time if options[:time].present?

  # Return true if everything's ok
  true
end

Private Instance Methods

set_options() click to toggle source

Set the options

# File lib/acts_as_bookable/bookable/core.rb, line 98
def set_options
  # The default preset is 'room'
  self.booking_opts[:preset]

  defaults = nil

  # Validates options
  permitted_options = {
    time_type: [:range, :fixed, :none],
    capacity_type: [:open, :closed, :none],
    preset: [:room,:event,:show],
    bookable_across_occurrences: [true, false]
  }
  self.booking_opts.each_pair do |key, val|
    if !permitted_options.has_key? key
      raise ActsAsBookable::InitializationError.new(self, "#{key} is not a valid option")
    elsif !permitted_options[key].include? val
      raise ActsAsBookable::InitializationError.new(self, "#{val} is not a valid value for #{key}. Allowed values are: #{permitted_options[key]}")
    end
  end

  case self.booking_opts[:preset]
  # Room preset
  when :room
    defaults = {
      time_type: :range,      # time_start is check-in, time_end is check-out
      capacity_type: :closed,  # capacity is closed: after the first booking the room is not bookable anymore, even though the capacity has not been reached
      bookable_across_occurrences: true # a room is bookable across recurrences: if a recurrence is daily, a booker must be able to book from a date to another date, even though time_start and time_end falls in different occurrences of the schedule
    }
  # Event preset (e.g. a birthday party)
  when :event
    defaults = {
      time_type: :none,       # time is ininfluent for booking an event.
      capacity_type: :open,    # capacity is open: after a booking the event is still bookable until capacity is reached.
      bookable_across_occurrences: false # an event is not bookable across recurrences
    }
  # Show preset (e.g. a movie)
  when :show
    defaults = {
      time_type: :fixed,      # time is fixed: a user chooses the time of the show (the show may have a number of occurrences)
      capacity_type: :open,    # capacity is open: after a booking the show is still bookable until capacity is reached
      bookable_across_occurrences: false # a show is not bookable across recurrences
    }
  else
    defaults = {
      time_type: :none,
      capacity_type: :none,
      bookable_across_occurrences: false
    }
  end

  # Merge options with defaults
  self.booking_opts.reverse_merge!(defaults)
end