class ResourceForm include ActiveModel::Model attr_accessor :agent, :resource attr_accessor :agent_id, :uuid, :name, :summary, :description, :email, :website, :phone_number, :address, :postal_code, :city, :entry_number, :latitude, :longitude, :section_ids, :source with_options presence: true do validates :name validates :email, allow_blank: true # validates :source validates :phone_number, allow_blank: true validates :website, allow_blank: true end validate :validate_models def initialize(agent, attributes = nil) @agent = agent @attributes = attributes || default_attributes raise ArgumentError "Attributes must be permitted" unless @attributes.permitted? # We use an empty hidden field to ensure this is always set, even if no # section is selected, so let's remove the empty value @section_ids = @attributes.extract!(:section_ids)[:section_ids].filter_map { |x| x.presence } rescue [] # We may have an existing and correct source, but anyway we must have one @resource = @agent.resources.build({ source: @agent.name }.merge(@attributes)) end def new_record? resource&.new_record? || true end # New forms can provide an existing classification, # and updates can prefer passed arguments to ensure correct changes def section_ids resource.present? && @section_ids.empty? ? resource.section_ids : @section_ids end # Ensure field values stick around # OMG this is ugly # TODO: use delegator or metaprog def name @name ||= resource&.name end def summary @summary ||= resource&.summary end def description @description ||= resource&.description end def email @email ||= resource&.email end def website @website ||= resource&.website end def phone_number @phone_number ||= resource&.phone_number end def address @address ||= resource&.address end def postal_code @postal_code ||= resource&.postal_code end def city @city ||= resource&.city end def longitude @longitude ||= resource&.longitude end def latitude @latitude ||= resource&.latitude end def save Rails.logger.info "--- Calling SAVE ---" return false if invalid? ActiveRecord::Base.transaction do resource.save! && \ @section_ids.each do |sec_id| Rails.logger.info("section " + sec_id) resource.categories << resource.classifications.find_or_create_by!(section_id: sec_id) end true rescue ActiveRecord::StatementInvalid => e errors.add(:base, e.message) false end rescue Exception => e Rails.logger.info "Unhandled Exception #{e.class}: #{e.message}" false end private def default_attributes ActionController::Parameters.new( { agent_id: @agent.id, uuid: '', name: '', summary: '', description: '', email: '', website: '', phone_number: '', address: '', postal_code: '', city: '', entry_number: nil, latitude: 0.0, longitude: 0.0, source: @agent.name, section_ids: [] }).permit! end # Validate underlying models def validate_models Rails.logger.info('--- validate_models ---') resource.valid? || promote_errors(resource.errors) end # Promote an error from the Model to the Form def promote_errors(model_errors) model_errors.each do |attribute, error| errors.add(attribute, error.full_message) end end end