• Login
sketchucation logo sketchucation
  • Login
🤑 SketchPlus 1.3 | 44 Tools for $15 until June 20th Buy Now

Module Wrapper for Your Ruby

Scheduled Pinned Locked Moved Developers' Forum
7 Posts 5 Posters 718 Views 5 Watching
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    MartinRinehart
    last edited by MartinRinehart 26 Sept 2009, 18:22

    It's a good idea, I was told, to wrap your Ruby code inside a module. I did this, placing "module Vismap" at the top, and "end" at the bottom. This would, I anticipated, avoid name collisions with other loaded Rubies. In fact, it broke nearly everything. I undid the change and went on with the non-module version.

    Today I had a minute to catch my breath, so I gave it another try, with help from Fredo, Chris Fullmer and Jim Foltz. This is a list of changes that I made. Hopefully, others will add to this list so that, over time, we can develop a comprehensive checklist.

    I assume your Ruby has a name, "Rubyname", and that you did a thorough bit of googling to ensure that "Rubyname" was unique.

    1. Just after you require 'sketchup', add "module Rubyname" and after the last line, add "end # module Rubyname".
    
    # rubyname.rb - purpose, author, etc.
    
    require 'sketchup'
    module Rubyname
    
    ... Ruby code
    
    end # module Rubyname
    # end rubyname.rb
    
    
    1. Functions defined in your code, at the outer level: Replace "def someFunc" with "def self.someFunc" (or "def Rubyname.someFunc").
    
    def self.thisFunc( args ) 
    ...
    end
    def Rubyname.thatFunc( args ) 
    ...
    end
    
    
    1. Classes - are fine as is, except as follows.

    2. Calls to outer module functions
      From other module-level code, they are fine as is.
      Called from class methods: change "someFunc" to "Rubyname.someFunc".

    
    class Rubyname_myclass
    ...
        @instVar = Rubyname.computeFunc this, that
    
    
    1. Nested functions in functions. Move the nested function out to the module level. Add "self." or "Rubyname." to the name. Within the formerly enclosing function, change calls to "someFunc" with calls to "Rubyname.someFunc".

    You have now protected your functions from inadvertent collisions. Your class names are not protected, even though your classes are defined in the module. You can achieve a good level of protection by changing the name from "Myclass" to "Rubyname_myclass". (See MSP_Greg's contribution, below, for a better, if not quite so simple, way to do this.)

    By the way, your "xxx.rb" file provides a namespace wrapper for its variables. Next time you see Matz, ask him why its just for variables.

    Author, Edges to Rubies - The Complete SketchUp Tutorial at http://www.MartinRinehart.com/models/tutorial.

    1 Reply Last reply Reply Quote 0
    • C Offline
      Chris Fullmer
      last edited by 26 Sept 2009, 22:39

      Great initiative Martin. "wrapping in a module" is a concept that took me a while to understand. And I do it, and I understand why its important with Ruby. But it took a bit of struggle to get my scripts to work. So thanks for starting this write-up.

      On #1 - the last line with end # rubyname.rb is not necessary. You can't end a "ruby file" with an end statement. It will throw an error. The last "end" should be ending the first defined class/method/module, whichever was first. So in the example given, it should look like this:

      # rubyname.rb - purpose, author, etc.
      
      require 'sketchup'
      module Rubyname
      def Rubyname.my_method
      
      ... Ruby code
      
      end # Rubyname.my_method
      end # module Rubyname
      
      

      #2 - I'm not sure about the syntax, perhaps Ruby accepts it. It looks odd, maybe it JS or C++ style, but normally you don't define methods like you have there. Try this:

      def self.thisFunc( args )
      ...
      end
      def Rubyname.thatFunc( args )
      ...
      end
      

      I suppose its not that different, but I have read that the standard ruby syntax is that brackets don't get used over multiple lines of code (I know it works - just int he book I read it said its not standard to do it that way in ruby). Also, I am wondering about the "do" statement in your method definition line. I've never seent hat before. It works?

      Hope my comments make sense? This is an area I've wanted to do a tutorial on, I'm still waiting for the SCF to get their tutorial section fixed...

      Chris

      Lately you've been tan, suspicious for the winter.
      All my Plugins I've written

      1 Reply Last reply Reply Quote 0
      • M Offline
        MartinRinehart
        last edited by 27 Sept 2009, 12:31

        @chris fullmer said:

        end # rubyname.rbIt will throw an error.
        ...

        def self.thisFunc( args )
        > ...
        > end
        > def Rubyname.thatFunc( args )
        > ...
        > end
        

        Thanks for the corrections. Original post now fixed. Remind me to never post code that hasn't actually been loaded.

        Author, Edges to Rubies - The Complete SketchUp Tutorial at http://www.MartinRinehart.com/models/tutorial.

        1 Reply Last reply Reply Quote 0
        • J Offline
          Jim
          last edited by 27 Sept 2009, 14:22

          Using "self" has the advantage that if you ever decide to change the module name, you only need to change it in one place. Of course your editor should be able to handle this easily with search-and-replace.

          Hi

          1 Reply Last reply Reply Quote 0
          • M Offline
            MSP_Greg
            last edited by 27 Sept 2009, 15:33

            Speaking of classes, one can sort of hide them by declaring them private and adding a module method to return an instance.

            I haven't written any Ruby code for while, so forgive the naming; I code in too many languages. Brief example of private both in a module and a class...

            module Is_Visible
              # method to return an instance of Test
              def self.get_Test
                Test.new
              end 
            
              private
            
              class Test
                def show ; puts "Test.show" ; end
                def self.self_show ; puts "Test.self_show" ; end
            
                def pub_show ; pri_show ; end
            
                private
                def pri_show ; puts "Test.pri_show" ; end
                
              end
            end
            
            # Can't create object since private in module
            begin
              t1 = Test.new
              t1.show
            rescue
              puts "Can't create Test"
            end
            
            # Create object and call instance method
            Is_Visible.get_Test.show
            
            # Call class method
            Is_Visible.get_Test.class.self_show
            
            # Can't call pri_show since private in class
            begin
              Is_Visible.get_Test.pri_show
            rescue
              puts "Can't call pri_show"
            end
            
            # Can call via public method
            Is_Visible.get_Test.pub_show
            
            

            FWIW,

            Greg

            1 Reply Last reply Reply Quote 0
            • M Offline
              MartinRinehart
              last edited by 27 Sept 2009, 16:07

              @msp_greg said:

              Speaking of classes, one can sort of hide them by declaring them private and adding a module method to return an instance.

              Very nice! Pointer to this edited into original.

              Author, Edges to Rubies - The Complete SketchUp Tutorial at http://www.MartinRinehart.com/models/tutorial.

              1 Reply Last reply Reply Quote 0
              • Dan RathbunD Offline
                Dan Rathbun
                last edited by 15 Jul 2010, 15:48

                @martinrinehart said:

                Your class names are not protected, even though your classes are defined in the module.

                Absolutely and totally WRONG ! A module namespace protects evrything inside it. It can have it's OWN constant of the same name as another constant in a higher namespace. The same for variables and method names. YOUR module can have a class Matrix, and MINE can have a class Matrix, and they are different.

                @martinrinehart said:

                By the way, your "xxx.rb" file provides a namespace wrapper for its variables. Next time you see Matz, ask him why its just for variables.

                Clarification: Only local_variables NOT instance_variables (@var), class_varaibles (@@avr) or Constants ( MSG, Value etc.)

                Running unwrapped code corrupts the ObjectSpace, with:
                Constants will be left behind in Object and become globally available.
                @vars will be left behind in Object and even when set nil, GC does not clean them up.
                @@vars will be left behind in Object and even when set nil, GC does not clean them up, AND worse... every class inherits them.

                I'm not here much anymore.

                1 Reply Last reply Reply Quote 0
                • 1 / 1
                • First post
                  Last post
                Buy SketchPlus
                Buy SUbD
                Buy WrapR
                Buy eBook
                Buy Modelur
                Buy Vertex Tools
                Buy SketchCuisine
                Buy FormFonts

                Advertisement