• Login
sketchucation logo sketchucation
  • Login
⚠️ Libfredo 15.4b | Minor release with bugfixes and improvements Update

Organising namespaces and loading scripts on demand

Scheduled Pinned Locked Moved Developers' Forum
7 Posts 3 Posters 260 Views 3 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.
  • A Offline
    archidave
    last edited by 2 Apr 2013, 17:47

    Hi,
    Trying to follow good practice for creating namespaces, I have some code which is structured along the lines given below:
    "File_A.rb" is loaded when Sketchup is launched if the plugin is active, amongst other things this a creates a menu / toolbar command which loads further libraries and code if required. The problem I am having is that since "File_B" is loaded from within the "My_library::Mod_A namespace", the files loaded by "File_B" create a set of nested namespaces such as "My_library::Mod_A::My_library::Mod_A" & "My_library::Mod_A::My_library::Mod_B". This is not of course the intention, the code should all sit in the same namespaces.
    Do I need to prepend all my module definitions with "::" in the loaded files to avoid this happening or is there a better way to organise this?
    thanks

    Dave

    "File_A.rb"

    module My_library
    	module Mod_A
    
    		# various classes,  method defs, statements etc
    	
    		cmd = ;;UI;;Command.new("Launch…") {
    			…
    			Sketchup;;require("File_B")
    		}
    		…
    	end
    end
    

    "File_B.rb"

    Sketchup;;require("File_B1")
    Sketchup;;require("File_B2")
    Sketchup;;require("File_B3")
    Sketchup;;require("File_B4")
    Sketchup;;require("File_B5")
    Sketchup;;require("File_B6")
    
    # some other stuff
    

    "File_Bn.rb"

    module My_library
    	module Mod_A
    		# various classes, method defs, statements etc
    	end
    
    	module Mod_B
    		# various classes, method defs, statements etc
    	end
    	…
    end
    
    1 Reply Last reply Reply Quote 0
    • T Offline
      thomthom
      last edited by 2 Apr 2013, 20:16

      You are loading scrambled files, correct?

      There is a known issue where scrambled files are not evaluated into the top level namespace.

      Place your require statements outside your modules - on the top level code and it will be ok.

      Note that if you are using the SketchupExtension class you probably need to use an unscrambled proxy .rb file to load the .rbs files. I had to do that for Vertex Tools because the files where being evaluated within the namespace of the SketchupExtension class.

      Thomas Thomassen — SketchUp Monkey & Coding addict
      List of my plugins and link to the CookieWare fund

      1 Reply Last reply Reply Quote 0
      • D Offline
        Dan Rathbun
        last edited by 3 Apr 2013, 03:09

        @archidave said:

        Do I need to prepend all my module definitions with " ::" in the loaded files to avoid this happening or is there a better way to organise this?

        NO on using the toplevel scope operator, instead change line 7 within "File_A.rb", so that you ensure the first call to Sketchup::require is evaluated within the toplevel scope:
        "File_A.rb"

        module My_library
        	module Mod_A
        
        		# various classes,  method defs, statements etc
        	
        		cmd = ;;UI;;Command.new("Launch…") {
        			…
        			eval('Sketchup;;require("File_B")',TOPLEVEL_BINDING)
        		}
        		…
        	end
        end
        

        If you still have problems.. do the same within "File_b".

        This is a bug with the Sketchup module's override of the require method, and as Thomas says, happens most often with rbs files.

        💭

        I'm not here much anymore.

        1 Reply Last reply Reply Quote 0
        • T Offline
          thomthom
          last edited by 3 Apr 2013, 07:58

          Ah, yea. I'd forgotten about the eval trick.

          Thomas Thomassen — SketchUp Monkey & Coding addict
          List of my plugins and link to the CookieWare fund

          1 Reply Last reply Reply Quote 0
          • A Offline
            archidave
            last edited by 3 Apr 2013, 09:27

            Hi Thomthom, Dan
            Many thanks for your replies, that seems to have cleared up the problem. (NB I've changed the subject slightly to be more useful to anyone searching the forum)

            @thomthom said:

            You are loading scrambled files, correct?

            Yes that is correct, I want to be able to load scrambled library files, hence the use of Sketchup::require().

            @thomthom said:

            There is a known issue where scrambled files are not evaluated into the top level namespace.
            Place your require statements outside your modules - on the top level code and it will be ok.

            @dan rathbun said:

            This is a bug with the Sketchup module's override of the require method, and as Thomas says, happens most often with rbs files.

            This does seem to be the key to the problem, and thanks for clarifying Dan (I have realised now that this issue only started to occur after I tested some scrambled scripts).

            @thomthom said:

            Note that if you are using the SketchupExtension class you probably need to use an unscrambled proxy .rb file to load the .rbs files.
            Yes, I currently do so there was no problem there.

            After some more testing it seems that there is no problem with the libraries themselves being scrambled, but the script that loads those libraries must be unscrambled, then it works fine. So to load scrambled libraries from within a module, they must be loaded by a proxy script that itself is unscrambled.
            I don't really want to use eval('Sketchup::require("my_library")',TOPLEVEL_BINDING) unless I have to, but good to know that option exists too.

            So using my abstract example again, it works ok if it is structured like this:

            "my_toolbars.rbs" (can be scrambled)

            module My_library
            	module Mod_A
            
            		# various classes,  method defs, statements etc
            	
            		cmd = ;;UI;;Command.new("Launch…") {
            			…
            			require("Load_libraries.rb")    # load unscrambled proxy script
            		}
            		…
            	end
            end
            

            "Load_libraries.rb" (must be plain text Ruby)

            Sketchup;;require("Library_1")
            Sketchup;;require("Library_2")
            Sketchup;;require("Library_3")
            Sketchup;;require("Library_4")
            Sketchup;;require("Library_5")
            Sketchup;;require("Library_n")
            

            "Library_n.rbs" (can be scrambled)

            module My_library
            	module Mod_A
            		# various classes, method defs, statements etc
            	end
            
            	module Mod_B
            		# various classes, method defs, statements etc
            	end
            	…
            end
            
            1 Reply Last reply Reply Quote 0
            • D Offline
              Dan Rathbun
              last edited by 3 Apr 2013, 10:58

              @archidave said:

              I don't really want to use eval('Sketchup::require("my_library")',TOPLEVEL_BINDING) unless I have to, but good to know that option exists too.

              And for future reference, you can use a block form of one of the eval methods.

              In this case the most appropriate would be instance_eval(), thus:

              TOPLEVEL_BINDING;;instance_eval(){
                Sketchup;;require("Library_1")
                Sketchup;;require("Library_2")
                Sketchup;;require("Library_3")
                Sketchup;;require("Library_4")
                Sketchup;;require("Library_5")
                Sketchup;;require("Library_n")
              }
              

              BUT... this also ignores another major issue with the Sketchup::require method when scrambled rbs files are evaluated ...
              ... and that is errors are reported as originating from a call to eval (with a bogus line number,) instead of the correct filename and line number. (In fact there may be no current workaround for the line number glitch.)

              So.. assuming the library files have an ordinal suffix, the loader could be similar to:

              for i in 1..n
                fname = "Library_#{i}"
                eval("Sketchup;;require( '#{fname}', TOPLEVEL_BINDING, '#{fname}.rbs', 1 )")
              end
              

              I'm not here much anymore.

              1 Reply Last reply Reply Quote 0
              • T Offline
                thomthom
                last edited by 3 Apr 2013, 11:56

                <span class="syntaxdefault"><br />filter </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> File</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">dirname</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">File</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">dirname</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">__FILE__</span><span class="syntaxkeyword">),</span><span class="syntaxdefault"> </span><span class="syntaxstring">'*.rbs'</span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">for filename in Dir</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">glob</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">filter</span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">  eval</span><span class="syntaxkeyword">(</span><span class="syntaxstring">"Sketchup;;require('#{filename }', TOPLEVEL_BINDING, '#{filename}', 1 )"</span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">end<br /></span>
                

                ?

                Thomas Thomassen — SketchUp Monkey & Coding addict
                List of my plugins and link to the CookieWare fund

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

                Advertisement