I’m using the self.reload
method from https://github.com/SketchUp/sketchup-ruby-api-tutorials/blob/main/load_tutorials.rb in order to quickly reload my plugins during development. However, I’ve noticed that changes made inside a Ruby block are not taken into account by the aforementioned method. For example, the following print statement will not execute unless I restart SketchUp:
cmd = UI::Command.new("My new command") {
...
puts "Why isn't this getting called?"
...
}
Is there any way to properly reload Ruby extension files? Quitting and opening SketchUp from time to time is far from the ideal development workflow.
You are not showing a generic Ruby block but actually a block argument to the UI::Command
constructor. This block is converted to a Proc
object and stored for use by the MS Windows menu command object.
These OS objects cannot be redefined or more specifically if they could, the SketchUp API does not exposed this. One of the main reasons we can surmise is security, so that “bad actors” cannot redirect existing commands to do nefarious purposes.
Fortunately, the workaround is simple. Do not put the command code in the block argument.
Instead, all command blocks should have one statement calling a local method that has the command code.
Methods can be redefined at any time, so you can tweak the code, reload, test, tweak again, repeat, … as many times as you need.
One of the paradigms I use often us to group my command methods together using a "command_"
or "cmd_"
prefix. (Ie, I always have my methods listed in alphabetical order within types. Ie, I group command methods and observer callback method, etc. together in groups and in alpha order within these groupings.)
So, for example …
module SomeAuthor
module SomePlugin
extend self
#{# COMMANDS
#
def cmd_nifty
# This code can be redefined at any time ...
end
#
#}#
#{# RUN ONCE BLOCK
#
if !defined?(@ui_loaded)
cmd = UI::Command.new("Do Nifty Thing") { cmd_nifty() }
@ui_loaded = true
end
#
#}#
end
end
What are #{# blocks? (...click to expand...)
The #{#
… #}#
blocks are collapsible blocks in Ruby (at least in Notepad++). They can be used to collapse and expand large portions of the code to enable better navigation.
3 Likes