Please post Ruby coding questions in the Ruby API subcategory.
(1) ALL of your extension’s code should be within a separate submodule that is within your unique top level namespace module. (Ie, is an an absolute non-no to define custom classes in the top level ObjectSpace
as they will become global classes. Only certain API classes and Ruby core classes should be defined at the top level.)
(2) Server requests should be delayed until absolutely necessary, not during SketchUp’s startup cycle.
The modal message boxes can either interrupt the loading of other extensions or might be suppressed by SketchUp as it loads (to avoid interference with the loading of other extensions.)
(3) Something like this should be fired by a method call, not during the load and evaluation of your extension’s classes.
(4) Generally try to avoid modal messageboxes for debugging and output informational strings to the console using puts()
.
(5) You are not properly naming your extension registrar file nor it’s folder, nor are you setting the correct pathname in the SketchupExtension
object’s constructor call.
Ie … the 2nd arg to the constuctor is "sample_extension/fetch_server"
, but the actually path given in the example is … "my_extension/my_own_extension.rb"
.
The “Plugins” file space is a shared space just as is SketchUp’s Ruby ObjectSpace
.
So let us say your unique namespace module identifier will be “MarcoSyu”, and your extension submodule name will be “SampleFetch”.
You name the regsistrar file and the extension subfolder both using the chained module names: "MarcoSyu_SampleFetch.rb"
and "MarcoSyu_SampleFetch/"
Ex:
# encodng: UTF-8
# File: "MarcoSyu_SampleFetch.rb"
#
module MarcoSyu
module SampleFetch
EXTENSION = SketchupExtension.new(
'Sample Fetch', 'MarcoSyu_SampleFetch/fetch_server'
)
Sketchup.register_extension(EXTENSION, true)
end
end
… and then the loader file must be as named in the constructor’s 2nd argument:
"MarcoSyu_SampleFetch/fetch_server.rb"
Now specifically I think your issue arises from violating the above conditions (during the startup cycle) and that you are misusing the class object.
Classes are for instantiating multiple instances of code that each keeps it’s own state and instance variables. A class instance object is created via a constructor call, usually to new()
that then automatically calls the new instance’s initialize()
method.
Your class does not define it’s initialize()
method so this raises a red flag that you might not be actually needing a class. Perhaps this should be wrapped up in a method and within your extension’s submodule ?
Example: Try using the AppObserver
to trigger a delayed call to a fetch_server()
method …
# encodng: UTF-8
# File: "MarcoSyu_SampleFetch/fetch_server.rb"
#
module MarcoSyu
module SampleFetch
extend self
# This is an AppObserver callback called by the
# SketchUp engine during the startup cycle.
def expectsStartupModelNotifications
UI.start_timer(5.0,false) {
# Call the server after 5 seconds:
fetch_server()
# Detach this submodule as an AppObserver:
Sketchup.remove_observer(self)
}
return false
end ###
def fetch_server
@request = Sketchup::Http::Request.new(
"http://localhost:3000", Sketchup::Http::POST
)
@request.start do |request, response|
if request.status == Sketchup::Http::STATUS_SUCCESS
puts "Request was successful."
# Read response.body here ...
@response = response.body
else
puts "Request was not sucessful!"
end
end
end ###
def get_status(status)
case status
when Sketchup::Http::STATUS_UNKNOWN
"Unknown"
when Sketchup::Http::STATUS_SUCCESS
"Success"
when Sketchup::Http::STATUS_PENDING
"Pending"
when Sketchup::Http::STATUS_CANCELED
"Canceled"
when Sketchup::Http::STATUS_FAILED
"Failed"
else
"Unknown"
end
end ###
def show_result
UI.messagebox(
"Request status was: #{get_status(@request.status)}"
)
end ###
# Run this block ONCE upon first load:
unless defined?(@loaded)
@request = nil
@response = nil
UI.menu('Extensions').add_item('SampleFetch: Result') {
show_result()
}
# Attach this submodule as an AppObserver object:
Sketchup.add_observer(self)
@loaded = true
end
end
end