Edges to Rubies The Complete SketchUp Tutorial


Transformation matrix diagram.

Appendix RM—Ruby Module Wrappers


You've written one of the finest Ruby plugins that SketchUp has ever known. You are ready to release it to the world. Fame and fortune are awaiting!

But not so fast. Your plugin could conflict with another plugin. With another plugin that you've never even tried. You may have chosen the same name for a function, a global variable or a class. What will happen?

Probably, it will depend on the order in which the plugins are loaded. Does yours load last? The class with the duplicate name is your class. You win. (Well, you win until your customer finds out that you've disabled his favorite other plugin. Then there will be a polite but less-than-complimentary post in the Plugins forum.)

What to do? Use a module as a namespace wrapper. Before you are ready to release your masterpiece, thoroughly Google your chosen name. If there is any doubt, choose another name. Be absolutely certain that your name is unique. Let's say you've settled on "Unique_name." (For the sake of argument. For the sake of popularity, choose something more meaningful!)

Colliding Plugins

Your Masterpiece Colliding Problem

# /r/t.rb

$glob = 'ugly global'

def is_ugly() 

    if $glob =~ /^ugly/
        puts "Yup. It's ugly."
    else
        puts "It's not ugly."
    end

end
        

Ruby Console Output
load '/r/t.rb'
true
$glob
ugly global
is_ugly()
Yup. It's ugly.

So far, so good. You loaded your masterpiece, checked your global and ran your function. All systems go.

Now another Ruby plugin was loaded after yours. (Simulated here by beginning it with a call to load yours.)

Your Masterpiece Colliding Problem

load '/r/t.rb'
true
$glob
ugly global
is_ugly()
Yup. It's ugly.

# /r/t2.rb

load '/r/t.rb'

puts $glob

$glob = 'pretty global'

is_ugly()

Ruby Console Output
load '/r/t2.rb'
ugly global
It's not ugly.
true

The value of the colliding global starts as your value. The collider replaces it. When the collider uses your function it gets an answer that's right for it, wrong for you. (You will get the wrong answer, too, if your code calls your function later.)

Modules for Private Namespaces

What to do? You wrap your entire plugin in a module that will create a private namespace. Your module name is the plugin's name. Now, what does the collider get?

Your Masterpiece Colliding Problem

# /r/t.rb

module Unique_name

    $glob = 'ugly global'

    def is_ugly() 

        if $glob =~ /^ugly/
            puts "Yup. It's ugly."
        else
            puts "It's not ugly."
        end

    end

end # of module Unique_name


# /r/t2.rb

load '/r/t.rb'

puts $glob

$glob = 'pretty global'

is_ugly()

Ruby Console Output
load '/r/t2.rb'
ugly global
It's not ugly.
true

That didn't do much. The globals still conflict and the collider is still calling your function with his own global value.

Fixups within the Module

You have more work to do. After wrapping your code in a module do these: Note: if the global starts with a capital letter, it is a constant. Global constants are fine. With a lowercase letter it can be changed from anywhere, which is probably a design error.

Your Masterpiece Colliding Problem

# /r/t.rb

module Unique_name

    $unique_name_glob = 'ugly global'

    def self.is_ugly() 

        if $unique_name_glob =~ /^ugly/
            puts "Yup. It's ugly."
        else
            puts "It's not ugly."
        end

    end

end # of module Unique_name

# /r/t2.rb

load '/r/t.rb'

puts $unique_name_glob

$glob = 'pretty global'

Unique_name::is_ugly()

Ruby Console Output
load '/r/t2.rb'
ugly global
Yup. It's ugly.
true

Now you see that the collider has to use your global name if it wants to access your global variable. (No unique_name_? Error.) And the collider has to prefix your functions with your module name and "::" if it wants to use your functions. (No Unique_name::? Error.)

Summary

  1. Find a unique name.
  2. Wrap your code in a module named with your unique name.
  3. Prefix your functions with self..
  4. Prefix any globals with your unique name.

  5. View of apartment contents. Transformation matrix diagram.