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

      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
      • Chris FullmerC Offline
        Chris Fullmer
        last edited by

        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

          @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

            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

              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

                @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

                  @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