This is because OpenStudio::Model::ThermalZone::airLoopHVACTerminal() returns an optional HVACComponent, see SDK doc. You have to get it first.
 Try this:
 model.getThermalZones.each do |zone|
  # this returns an optional HVACComponent
  supplyTerminal = zone.airLoopHVACTerminal
  if supplyTerminal.empty?
    runner.registerInfo("Cannot find an airloop terminal for #{thermalZone.name}")
  else
    supplyTerminal = supplyTerminal.get
    runner.registerInfo("For '#{thermalZone.name}' the supply terminal '#{supplyTerminal.name}' was found.")
  end
end
 Like I said supplyTerminal, even after ".get" will be an HVACComponent, not an actual object such as OpenStudio::Model::AirTerminalSingleDuctUncontrolled for example. If you need to work with the actual underlying object, you'll have to cast it into what it's really.
 The clean way is to use to_XXXX method, but you have to test potentially a lot of cases...
 if supplyTerminal.to_AirTerminalSingleDuctUncontrolled.is_initialized
  supplyTerminal = supplyTerminal.to_AirTerminalSingleDuctUncontrolled.get
elsif supplyTerminal.to_AirTerminalSingleDuctVAVNoReheat.is_initialized
  supplyTerminal = supplyTerminal.to_AirTerminalSingleDuctVAVNoReheat.get
else
  runner.registerInfo("I don't know what this object is because there are too many possible ones!")
end
 
 You want the dirty way? I knew it! But I shall not be liable for any problems you might get :)
 Anyways, just add this method to the class ModelObject...
 # Extend ModelObject class to add a to_actual_object method
# Casts a ModelObject into what it actually is (OS:Node for example...)
class OpenStudio::Model::ModelObject
  def to_actual_object
    obj_type = self.iddObjectType.valueName
    obj_type_name = obj_type.gsub('OS_','').gsub('_','')
    method_name = "to_#{obj_type_name}"
    if self.respond_to?(method_name)
      actual_thing = self.method(method_name).call
      if !actual_thing.empty?
          return actual_thing.get
      end
    end
    return false
  end
end
 Then you can do supplyTerminal = supplyTerminal.to_actual_object
 It'll work with anything, since everything in OpenStudio::Model is after all a ModelObject: ModelObject instances, HVACComponent, even objects such as AirTerminalSingleDuctVAVNoReheat themselves (though that's completely pointless)