Reloading scripts not working

scripts
plugins

#1

Hello,

I made a simple script that is loading ruby scripts that are not located in the “Plugins” folder, and creating a button to reload those scripts, so I don’t have to exit SketchUp when I want to change a few things.
Thing is, loading on startup is working, but not the reloading, I have no idea why, it was working fine for a long time. I displayed the content of the reloaded .rb files, and the code is changed indeed, but the behaviour of the scripts remains unchanged.

Here is my “plugin_loader” file, am I missing something here ? plugin_loader_2018.rb (1.3 KB)

Thanks in advance,
Mickaël


#2

Sketchup.load is an alias for Sketchup.require, which says …

The require method is used to include encrypted and nonencrypted ruby files. This is an alias of the Sketchup.load method.

Both method docs say …

Parameters:

  • path (String) — The path, including the filename, to the file you want to require.

(I emboldened and underlined the key word above.)

So, Sketchup.load and Sketchup.require both act like Kernel.require not like Kernel.load.

(We’ve complained about this forever, but they will not change it now because it might break plugins out in the wild.)

So you need to use the global load method (that comes from the Kernel module to RELOAD unencrypted Ruby files.

NOTE: There is no way to reload RBS or RBE encrypted files into SketchUp once loaded. You are forced to restart SketchUp for reloading encrypted files.


@thomthom Please add this information to the Ruby docs so newbs do not waste time spinning their wheels trying to reload files using the API’s load method.


#3

Well, I am using the global method on line 38 from my script, that was working before. I added the Sketchup.load method just to see if this could improve the situation somehow. I though indeed that both method were somehow similar. My bad, I forgot to clean that line before sending the file.
So then, having the global method, I don’t understand why this is not working. None of my files are encrypted.


#4

Try this version.

mickael_plugin_loader_2018_revised.rb (1.8 KB)

It is module wrapped, uses a beginrescue block to trap any errors so that LoadErrors do not cause the load loop to “break” out prematurely.

Also uses ||= instead of “unless defined?” blocks. (This cannot be used with boolean references.)


#5

Are these scripts you are developing yourself?


#6

… and does the modified version work better for you ?


#7

Yes indeed, that is why I need to reload them before re-testing them.

Sorry for not replying quicker. Yes it does work fine, thanks a lot ! I also changed the structure of my plugins to make it “extension-compliant”, so I wonder if I was also having an issue with the previous structure …


#8

Do you encrypt them during your development?

The workflow I use is to load the extensions directly from the source repository. Only before I push a release will I take the scrambled/encrypted versions from and RBZ and test the full install experience.


#9

Just to be sure that the scripts that you reload do not contain this:
Code blocks that are registered as menu or toolbar button handlers (.add_item('MyPlugin'){ code block }) can not be updated. Thus the behavior defined in the code block remains the same, but method calls will call the reloaded methods.

In case of doubt it is also good practice to wrap everything that is inside a menu/button/dialog handler or observer method into a begin rescue block because otherwise exceptiobs therein are not reported.


#10

Nope. I plan to encrypt them for release / stable version, not before. But actually I havn’t encrypted any ruby files so far, would you have any tips ?

Well, that is a very good thing to know, thanks !


#11

This is very good advice - always call out to a simple method in UI::Comman, add_item and add_action_callback. It will make your developing life so much easier. If you make sure to do this you only have to restart if you change UI items (menus, toolbars) or change a class’ inheritance.

When I develop I usually have a reload helper method:

debug.rb:

module TT::Plugins::TrueBend

  # TT::Plugins::TrueBend::SETTINGS.debug = true

  # @note Debug method to reload the plugin.
  #
  # @example
  #   TT::Plugins::TrueBend.reload
  #
  # @return [Integer] Number of files reloaded.
  def self.reload
    original_verbose = $VERBOSE
    $VERBOSE = nil
    load __FILE__
    pattern = File.join(__dir__, '**/*.rb')
    Dir.glob(pattern).each { |file| load file }.size
  ensure
    $VERBOSE = original_verbose
  end

end # module

I then call that whenever I have made code changes. Since I call load the effects will take effect. And this saves me from working out which file or files needs reloading.

If you publish on EW then you just need to check the encryption checkbox upon submission. (You submit the unencrypted source)

If you don’t public on EW you need to use the Signing Portal: https://extensions.sketchup.com/en/developer_center/extension_signature

I’d advice to use the signing portal to test your RBZ package even if you plan to publish on EW. It’s a common rejection cause for first time uploads that some extensions doesn’t load because they hard code .rb file extensions into their Sketchup.require lines. (Upon encryption RB files are replaced with RBE and/or RBS).