Issue with passing arguments

Hello,
I am new to the Ruby API for sketchup and am having an issue with passing arguments to a ruby tool I have created. The intent is to build a set of typing savers or quick commands to use via the ruby console.

I created a move command ‘m’ that is defined by the following code: (The various ‘puts’ lines are me trying to figure out what’s going on)

# /Rubies/bst.rb  -- temporary test file

require 'sketchup'
puts( 'Loading Brad''s bst' ) #test msg
load File.dirname( __FILE__ )+'/bst_classes.rb'
puts( 'Brad''s bst loaded') #test msg
......
<   a bunch of other command function defs.   >
......
def m (*args)
    #Invoke with "m comp_name, [r,g,b], repeat_count <,optional>"
	# example "m test, [10,10,30], 10"
	puts '# of args ' +args.length.to_s
	puts 'args[0] is ' +args[0]
	puts 'args[1] is ' +args[1].to_s
	puts 'Sketchup ComponentInstance is ' +args[0]
	puts 'Sketchup::ComponentInstance is ' +args[0].is_a?(
	unless ( args.length > 0 ) && ( args[0].is_a?(Sketchup::ComponentInstance) )
		UI.messagebox( "First argument of \"m()\" must be a Sketchup::ComponentInstance.\n" +
            'Use "xm()" to translate by r, g, b values.') 
        return
    end
   
    case args.length
        when 2 then move( args ) # static move
        when 3 then movie( args ) # animated move
        when 1 then xmove( args[0] )
        else UI.messagebox( 'm args must be: ( transformation ) or ( comp, vec ) or ( comp, vec, ntimes ).' )
    end
end # of m()


< more commands

The code is part of an .rb file my tools are in. the file is loaded via the Ruby console with “load ‘c:/rubies/bst.rb’” , again without the quotes.

First, in SketchUp 2017 (Make), I draw a rectangle, pushpull it, make it a component called test and select it. I would then type “m ‘test’, [10,10,10]” to provide the component name, and a move vector.
Without fail, i get the following message and nothing happens. Can someone please help. I think the problem is in the name of the component but I don’t see why. The screenshot at the bottom shows the argument are passed in ok, but apparently “test” is not seen as a component name.

m ‘test’, [10,10,10]

of args 2

args[0] is test
args[1] is [10, 10, 10]
Sketchup ComponentInstance is test
Sketchup::ComponentInstance is false

If i pass the name in as just test without the single quotes, I get an argument error.
m test, [10,10,10]

Error: #<ArgumentError: wrong number of arguments (0 for 2…3)>

:in `test' :in `' SketchUp:1:in `eval'


Thanks
Brad Smith

I can’t comment on your code, but I have two recommendations for you to revise your post.

  1. Format your Ruby code properly. As a minimum, put three back ticks and the word ruby on a single line, before your code, with no spaces or tabs anywhere in the line. Then on the line after your code, put three back ticks again, then a new line.

  2. Remove your email address and other personal details from your post to avoid bots picking it up and spamming you.

thank you for the suggestions. the code was copy pasted from the console. I have replaced it with the code from the editor. Also I am not sure what a "back tick’ is
Brad

See

John
Thanks Much I did not know that trick. Very Nice!!
Brad


See:

Also you can wrap your sample console output in

```text

delimiters.


puts( 'Loading Brad''s bst' ) #test msg

You cannot embed a single quote character within a single quoted string like this.
See String literals section of the Ruby Literals primer.
ie …

puts( "Loading Brad's bst" )
# or
puts( %{Loading Brad's bst} )
# or
puts( %Q[Loading Brad's bst] )
# ... etc., ...

Please do not put a space between the method identifier and it’s parameter list.
This will cause warnings output to the console and/or warnings from Rubocop if you are using it.


Ruby uses 2 space indents. Using larger indentation causes readers of your code to do excessive horizontal scrolling when you post in the forum.

Also many forums and GitHub will use 8 spaces for TABs. So it’s best to have your code editor automatically replace TABs with 2 spaces for .rb files. (Good editors allow different settings for different coding languages. (4 for .py files, 8 for .c,.cpp,.h, etc.)


Ruby does not force the use of frivolous parenthesis around each conditional expression. Ie:

  unless args.length > 0 && args[0].is_a?(Sketchup::ComponentInstance)

The convention is to use them only when it is necessary to force order of evaluation.


Of course you do, because literal strings must be enclosed in some kind of quotation.
But it is acceptable to set a reference to a string and use this reference in the call.

comp = 'test'
m(comp, [10,10,10])

Because you did not properly quote the string, the Ruby interpreter looked for an object identified with the reference test and found it was the global method #test, from module Kernel, which is mixed into class Object which is the top level ObjectSpace called main. (Ruby is implemented in C so it’s interpretive program loop is the C function main().)

So, because Kernel#test has a minimum of 2 and maximum of 3 arguments and your statement …

m test, [10,10,10]

… did not pass any arguments in a parameter list with test (ie, it was followed immediately by a comma,)

you get an ArgumentError that correctly informs you that you passed 0 args instead of between 2…3 to the method test (the method name always follows “in” for error messages.)
The second blank “:in ‘’ SketchUp” means it was at the top level. (Normally this would give the Ruby filename followed by the line number.)


Incorrect nomenclature. A Ruby tool is a code object that implements abstract SketchUp::Tool class interface. It is a tool that the user interacts with using the cursor (usually a tool specific cursor icon or icons,) in order to manipulate the model.

What you describe is more of a utility. A command that runs, does it’s thing and finishes.

Your not the first to try this. However, SketchUp Ruby is a shared environment. Ruby’s top level namespace is a special instance of Object. Everything in Ruby is an object, therefore a subclass of Object. Whatever you define at the top level becomes global and every other object (classes and modules) of Ruby’s and the SketchUp API and all other author’s extension objects will inherit what you define at the the top level.

So everything (using your example) is going to inherit a m() method. This is unacceptable in a shared environment.

You are going to run into clashes when you try to define a p(), pp(), j() and jj() methods because these are already globally defined. If you defined these you redefine them and can cause havoc with other extensions.

This is why the number 1 rule of SketchUp coding is stay within YOUR namespace module.

Every author needs to invent a unique top level namespace module name. Your name or your company’s name. Then each of your extensions need to be separated into it’s own submodule inside your top level namespace module, so they do not interfere with one another.

2 Likes

Dan,
Thankyou for taking the time for such a detailed response. I really appreciate it. I said I was new to Ruby and I guess it shows :grinning:. I would like to comment on your various points below. Hopefully I get the quoting right. (Not sure how to use the block quote but I will try.) Hopefully it does not mess up too badly…

I was aware of these and have actually accessed them and am working through them. And thanks for the tip on the colorized code and text back ticks.

Noted for the single quotes imbed and the tab spacing. I use Notepad++ and Textpad for my text editing. Both have tab setting and colorization capabilities based on the file extension. I will use two spaces for tabs from here on, thanks. I am new to notepad++ but have used Textpad for years. Beginning to think I like Notepad better.

As regards the space between the method id and the param list, This is easy to comply with. will do. I assume Rubocop is a play on the TV movie. And no I don’t use it but I will google it and check it out. Anything that helps with my coding is a plus.

[quote=“DanRathbun, post:6, topic:190140”]

Ruby does not force the use of frivolous parenthesis around each conditional expression. Ie:

  unless args.length > 0 && args[0].is_a?(Sketchup::ComponentInstance)

The convention is to use them only when it is necessary to force order of evaluation.

Noted: I am still experimenting with this for readability, etc.

I wondered about this but could not quite figure out how to implement it properly. I appreciate the coding tips and explanation

You are correct that this is more a utility then a command. This was my intent I just did not know the proper way to describe it. (still learning here)

Your comments on SketchUp Ruby and shared environments concern me. I certainly do NOT want to impact this shared environment, or other users with my code, nor do I want my code impacted by this.

At the moment, I am only running my utilities file via Sketchup Make and its Ruby console. I think I see where I might impact the Sketchup environment in my local session of Sketchup, and possibly code implemented by any extensions I am using. I am unclear how this could go farther. I (currently) only run my bst.rb file from the console and it is not in the sketchup plugins subdirectory so it does not load automatically with Sketchup. I HAD planned do just that if I found enough usefulness in the utils. might want to rethink this. Right now its a means for learning Ruby.

Can you explain more about creating my own namespace and how I might accomplish this an run my utils and any future tools I may write without risking impact on other code. My reading to date has not yet touched on namespaces or creating submodules.

One last question. when I invoke the utility m() with

m 'test', [10,10,10]

the console responds with

m 'test', [10,10,10]
# of args 2
args[0] is test
args[1] is [10, 10, 10]
Sketchup ComponentInstance is test
Sketchup::ComponentInstance is false

which is correct according to the code, but WHY does the component instance test come back with FALSE? I created the component and gave it the name test. How should I access/name the component so that args[0] is the name of the component I want to move?

Again, thank you for your advice and for taking time to help me.
Brad Smith

You are using a boolean method for that line. BUT … what you posted above is incomplete:

	puts 'Sketchup::ComponentInstance is ' +args[0].is_a?(

… there is no class identifier and closing ")".

If you want to test what type the args are, then use:

	puts '# of args  : '<< args.length.to_s
	puts "args[0] is (#{args[0].class}): #{args[0].inspect}"
	puts "args[1] is (#{args[1].class}): #{args[1].inspect}"

This uses string interpolation with code enclosed in #{} within double-quoted strings.
This also avoids the creation of an extra String object that occurs with String#+.

Whenever you need to append stuff to the end of a string and it is okay to modify that string (because it’ll be GC’d at the end of the method,) then favor String#<<.


Now, again looking at the code, is see in messagbox text via a type sniffing saying the first arg needs to be a instance reference.

When I first read your post, you explained how the m() method worked. I thought you had said the first argument was to be the instance name. So I assumed the first arg needed to be a String that you would assign to the instance’s name property via ComponentInstance#name().

But apparently, you meant an object reference to an existing instance. This is far different from a value stored in an object’s internal data that just happens to have the key “name”.

So let us step back. IF you have created the cuboid component and named it “Test” (internal property) and it’s new instance is selected, you can assign an object reference using Ruby’s interpretive assignment operator (=) like so …

model = Sketchup.active_model
test = model.selection[0]

test is now a local reference (which happens to be global) pointing at your new instance object.

Now, as said previously, there is also a global method that has an identifier “test”.

Now you call your method m(test, [10,10,10]) … what does Ruby do ?

The answer is that it first looks for local references, so it should find and pass your object reference test to the m() method, rather than attempting to call the Kernel#test method.

So originally, you were confounding the idea of a data name property with an object reference identifier. Two separate and distinct things.


Revisiting what your intentions were …

Okay, I was correct, you had already given the instance a name, and you want the first arg to be the string name.

That can be done rather than pass a reference, you want the m() method to find the reference.

Easy-Peezy …

You said that the new instance was selected, so it’s even easier thus:

    inst = Sketchup.active_model.selection.first

It’s simple. You create a top level namespace module and use it for ALL of you extensions, even be they little utilities.

module BDS
  module NiftyUtility
    extend self

    # Local Constant definitions

    # Module variables

    # Local Class definitions

    # Methods

    # Rub Once at Startup code
    if !defined?(@loaded)
      # Define submenus, commands, menu items and toolbars
      @loaded = true
    end

  end # submodule
end # namespace module

The interpreter sees a module Identifier statement and will determine if such module already exists. If not, it basically creates a new one via a call to Identifier = Module.new.

But if such a module already exists, then it will open it for edits and additions via Identifier.module_eval.

This means you can open and modify any module, any number of times, in any number of files.

In this way a developer can break up the code for large extensions across multiple files.

This is what’s called a dynamic programming language, where code objects can be modified during runtime.

Well at the least this utilities methods could be wrapped into a BST module. Ie …

module BST

  extend self

  def m(*args)
    #Invoke with "m comp_name, [r,g,b], repeat_count <,optional>"
    # example "m test, [10,10,30], 10"
    puts '# of args  : '<< args.length.to_s
    puts "args[0] is (#{args[0].class}): #{args[0].inspect}"
    puts "args[1] is (#{args[1].class}): #{args[1].inspect}"
    unless args.length > 0 && args[0].is_a?(Sketchup::ComponentInstance)
      UI.messagebox(
        'First argument of "m()" must be a Sketchup::ComponentInstance.'<<
        "\n"<<'Use "xm()" to translate by r, g, b values.'
      ) 
      return
    end

    case args.length
      when 2 then move( args ) # static move
      when 3 then movie( args ) # animated move
      when 1 then xmove( args[0] )
      else UI.messagebox(
        'm args must be: ( transformation ) or ( comp, vec ) or ( comp, vec, ntimes ).'
      )
    end
  end # of m()

end

It won’t go further unless you release code without module wrapping it.

And if you do not run many other extensions from other authors, then you might not see any impact.

Hi again,

Yeah, I know. Somehow when I copy pasted the code from the editor I truncated that line to what you see. And then I saved it and just spent 10 minutes figuring out what I deleted and putting it back. It used to work. Fat Fingers (sigh). What it DID say (and now does again) is:

	puts 'Sketchup::ComponentInstance is ' +args[0].is_a?(Sketchup::ComponentInstance).to_s

Useful info. Thanks.

I did say it was the instance name and I can see why you assumed I wanted to use it to name the component. And as you pointed out on reflection, I actually want to reference the existing component ‘test’ (now renamed ‘testblock’, Please don’t tell me this is also global :grin:) Thanks for the correction. I want to do all this from within the m() utility so I will add the lines

model = Sketchup.active_model
args[0] = model.selection[0]

within the m() utility but before I do anything else.
I think this gives me the following in my code:

def m(*args)
  #Invoke with "m comp_name, [r,g,b], repeat_count <,optional>"
	# example "m test, [10,10,30], 10"
  puts '# of args ' +args.length.to_s
	puts 'args[0] is ' +args[0]
	puts 'args[1] is ' +args[1].to_s
	puts 'Sketchup ComponentInstance is ' +args[0].to_s
  model = Sketchup.active_model
  args[0] = model.selection[0]
  puts 'Value of comp is '+args[0].to_s
	puts 'Sketchup::ComponentInstance is ' +args[0].is_a?(Sketchup::ComponentInstance).to_s
    unless ( args.length > 0 ) && ( args[0].is_a?(Sketchup::ComponentInstance) )
   		UI.messagebox( "First argument of \"m()\" must be a Sketchup::ComponentInstance.\n" +
            'Use "xm()" to translate by r, g, b values.') 
        return
    end
=begin    commented out until i get the parameter passing to work
    case args.length
        when 2 then move( args ) # static move
        when 3 then movie( args ) # animated move
        when 1 then xmove( args[0] )
        else UI.messagebox( 'm args must be: ( transformation ) or ( comp, vec ) or ( comp, vec, ntimes ).' )
    end
=end    
end # of m()

I did this and this is the result.

m 'testblock', [10,10,10]
# of args 2
args[0] is testblock
args[1] is [10, 10, 10]
Sketchup ComponentInstance is testblock
Value of comp is #<Sketchup::ComponentInstance:0x00022aa94c5600>
Sketchup::ComponentInstance is true

so now it sees testblock as a component. now let’s see if I can get it to move.

Didn’t see the above until after I did the above new code. Have to give your version a try. Its all good. I need to learn this stuff.

Namespace stuff

I have to think about this some. sounds pretty cool though.

This i will do first. that way I keep my “NiftyUtilities” (love that name) from impacting others. Then my own namespace for ALL my new code.

It is unlikely I will release ANY code for a while. Just now I am too nervous about my own state of knowledge. You know, A little knowledge is a dangerous thing. I do run a few extensions so wrapping bst.rb with NiftyUtilities code as you describe will be done.
Brad

Actually it does not. The first arg is frivolous and being discarded because you brute force reassign …

  model = Sketchup.active_model
  args[0] = model.selection[0]

You might rearrange the method arguments, put the transform first and the object 2nd as an optional argument:

    def m(trans, obj = Sketchup.active_model.selection[0])

So that you can move a selected obj, or specify something to move.

You can then check obj and if it’s a string, then search for the obj in the model.active_entities.


And did you name the instance "testblock" or the definition ?

Ok…I think I follow. I agree that my

args[0] = model.selection[0]

replaced “testblock” with a bunch of hex as I added some puts.

  puts '# of args ' +args.length.to_s
	puts 'args[0] is ' +args[0]
	puts 'args[1] is ' +args[1].to_s
	puts 'Sketchup ComponentInstance is ' +args[0].to_s
  model = Sketchup.active_model
  args[0] = model.selection[0]
  puts 'model.selection is' +model.selection[0].to_s
  puts 'name of component is '+args[0].to_s
	puts 'Sketchup::ComponentInstance is ' +args[0].is_a?(Sketchup::ComponentInstance).to_s

and it came back with a bunch of hex.

m 'testblock', [10,0,0]
# of args 2
args[0] is testblock
args[1] is [10, 0, 0]
Sketchup ComponentInstance is testblock
model.selection is#<Sketchup::ComponentInstance:0x00022aa97873e8>
name of component is #<Sketchup::ComponentInstance:0x00022aa97873e8>
Sketchup::ComponentInstance is true
#<Sketchup::View:0x00022aa96a1f00>

But it moved!!! YAY

according to Entity Info in SU tray I named the definition. Should I have named the instance? is that why I got hex back instead of testblock? My puts that returned testblock should have read

puts 'arg[0] is ' +args[0].to_s

instead of

puts 'Sketchup ComponentInstance is ' +args[0].to_s

I just repeated the earlier puts for args[0]. Oh well. live and learn.

So…to be able to use testblock as the actual name of what is to be moved (rather than the hex (i assume) Instance, what do I do?

BTW you are being very patient with me. It is appreciated.

That’s a Ruby inspection string giving class identifier and apparently a hex encoding of the integer Object#object_id.

I would encourage you to use #inspect rather than #to_s.

No. You are using #to_s on an object reference. Object#to_s says:

Returns a string representing obj . The default to_s prints the object’s class and an encoding of the object id. As a special case, the top-level object that is the initial execution context of Ruby programs returns “main’'.

SketchUp’s API says it overrides the #to_s method from Object in class Sketchup::Entity, but I think it only changes the output for some subclasses.


This is what I thought as the name field at the top of the Make Component dialog applies to the definition.

And you need to give the definition a unique name because the name is the key in the DefinitionList collection. Otherwise SketchUp will make up a generic unique name that does not mean much, like "Component#4".

It depends upon IF you wish to find and identify it specifically. Which is what you original idea implied.

All definitions must have a name property as it is a key into the collection. But instances can have a empty name property. A definition can have multiple instances. Each can have it’s own name, or the same name. It’s just a text data property for instances.

You can find a certain definition in the DefinitionList collection, like:

  cdef = model.definitions['testblock'] # nil if not found

Then you can find a specific instance of that definition in several ways.

Searching a definition’s instances collection:

  inst = cdef.instances.find {|i| i.name == 'test 3' } # nil if not found

Note that the #instances method returns an array “snapshot”, so any Array or Enumerable method can be used including access by index.

Searching the model’s entities collection

  insts = model.entities.grep(Sketchup::ComponentInstance)
  inst = insts.find {|i| i.name == 'test 3' } # nil if not found

Note that it is often safer to use model.active_entities because the user can have dug down into a component or group.

thanks again. you have been very helpful…

I am going to quit for a while, I am getting tired. I thought when I retired as an electrical engineer and took up woodworking I was done with programming. Never did it much. Mainly as an adjunct to hardware design (my forte) for hardware testing and VHDL and Verilog coding for FPGAs. I am enjoying myself though.

I’ll get back to this tomorrow. You have a good night.
Brad

1 Like

Dan
Good Afternoon,
I tried putting my utilities in a module as you described. After re-starting SU I loaded the bst.rb file from the console and it appeared my various methods were ignored as nothing happened when I ran the m() utility.
Here is what I had code-wise:

# /Rubies/bst.rb  -- temporary test file

require 'sketchup'
puts( "Loading Brad's bst" ) #test msg
  
module BST 
   extend self
  
  load File.dirname( __FILE__ )+'/bst_classes.rb'
  puts( 'Brad''s bst loaded') #test msg

  # ******************************************************************
  # SketchTalk Functions ------------------------------------------
  # ****************************************************************
  
	def all()
		#UI.messagebox( ' all here ' ) #test msg
		model = Sketchup.active_model()
		model.selection().clear()
		ents =  []
		for e in model.entities()
			ents.push(e) if e.layer().visible?()
		end
		model.selection().add(ents)
	end # of all()

	def box( near, far, pushpull )
	    b = Box.new( near, far, pushpull )
	    b.draw()
	    return b
	end # of box()

# followed by a bunch of  of other method defs until the m() util

	def m(*args)
	  #Invoke with "m 'comp_name', [r,g,b], repeat_count <,optional>"
		# example "m 'testcomp', [10,10,30], 10"
    puts 'arguments as passed'
    puts '# of args  : '<< args.length.to_s
    puts "args[0] is (#{args[0].class}): #{args[0].inspect}"
    puts "args[1] is (#{args[1].class}): #{args[1].inspect}"	  
    
    puts '# of args ' +args.length.inspect
		puts 'args[0] is ' +args[0].inspect
		puts 'args[1] is ' +args[1].inspect
		puts 'Sketchup ComponentInstance is ' +args[0].inspect
	  model = Sketchup.active_model
	  args[0] = model.selection[0]
    puts 'model.selection is ' +args[0].inspect
	  puts 'name of component is '+args[0].inspect
		puts 'Sketchup::ComponentInstance is ' +args[0].is_a?(Sketchup::ComponentInstance).inspect

	    unless args.length > 0 && args[0].is_a?(Sketchup::ComponentInstance) 
			UI.messagebox( "First argument of \"m()\" must be a Sketchup::ComponentInstance.\n" +
		    'Use "xm()" to translate by r, g, b values.') 
		return
	    end

	    case args.length
		when 2 then move( args ) # static move
		when 3 then movie( args ) # animated move
		when 1 then xmove( args[0] )
		else UI.messagebox( 'm args must be: ( transformation ) or ( comp, vec ) or ( comp, vec, ntimes ).' )
	    end  

	end # of m()

# and a bunch more method defs then some support function icluding this one

	def move( args ) # static move

	    inst = args[0]
	    trans = translate( inst.transformation, args[1] )
	    inst.move!( trans )
	    draw()

	end # of move()

#And finally the module end

end #of module /Rubies/bst.rb

If I comment out the module, extend self and end statements, then reload, it all works again.

load '/rubies/bst.rb'
Loading Brad's bst
Brads bst loaded
true
box [0,0,0],[10,10,10],25
Error: #<NoMethodError: undefined method `box' for main:Object>
<main>:in `<main>'
SketchUp:1:in `eval'

after reload

load '/rubies/bst.rb'
Loading Brad's bst
Brads bst loaded
true
m 'testblock',[10,10,10]
arguments as passed
# of args  : 2
args[0] is (String): "testblock"
args[1] is (Array): [10, 10, 10]
# of args 2
args[0] is "testblock"
args[1] is [10, 10, 10]
Sketchup ComponentInstance is "testblock"
model.selection is #<Sketchup::ComponentInstance:0x0001b12ebd92b0>
name of component is #<Sketchup::ComponentInstance:0x0001b12ebd92b0>
Sketchup::ComponentInstance is true
#<Sketchup::View:0x0001b1340fc918>
box [0,0,0],[10,10,10],25
#<Box:0x0001b1340fc3a0>

(the box util is just another method I wanted to see if worked. it did)
What did i do wrong?
Brad

FYI … “SketchTalk” is currently in use. IE: https://sketchtalk.io/
There is also a Twitter account by this name.

It really has to do with another app called “Sketch” that is distinct from SketchUp.


With regard to SketchUp, … there was a historical use by a programmer who I’ve not seen around the SketchUp forums for awhile. Ie …


It helps to do due diligence by Googling names before use.

(Nag): This is basic Ruby. By now you should have read several of the free downloadable books I list in the Ruby Learning Resources list.


You must make qualified method calls from outside the module. Ie …

BST.m('testblock', [10,10,10])

… and …

BST.box([0,0,0], [10,10,10], 25)

If for example you think typing capital BST is slowing you down, then temporarily you can create a local (global) reference to point at your BST module, like so …

x = BST

And now for the rest of the session you can do …

x.m('testblock', [10,10,10])

… and …

x.box([0,0,0], [10,10,10], 25)

etc., …

I chose “x” as it does not seem that it is a preset keyboard shortcut. It is likely that you’ll forget to focus the console window from time to time and be hitting the reference letter when the app window has focus. If it’s not set for a shortcut then this booboo won’t effect anything. (For example, I didn’t suggest “z” because it’s set for the Zoom tool.)


The other alternative is to code up a UI.inputbox that takes you method call as a string, and passes it to your module. Then create a menu item to bring up the inputbox and assign whatever shortcut you want to that menu command. (CTRL+i)

I am familiar with this. I have been following Martin Rineharts tutorial “Edges to Rubies” in producing this code. I ran into my original difficulty with his m() method and was trying to understand what was happening. I did not intend to claim credit for the code as mine. its not. but i have been altering it as I ran through the tutorial to suit myself.

Dan,

It may be basic Ruby but i have only been trying to learn ruby for about a week and have only been using SU about a month. I am reading “Automatic Sketchup” by Matthew Scarpino currently and have looked at several of the other books in your lists.

Ok this is helpful. And it makes sense when I think about how other SU Ruby code gets written, eg.

Sketchup.active_model.entities

Since SU is a module. (Just learned that today)

I did that "BST.m() call and it works. thanks

( as a side note, why does a block comment have to start at the beginning of a line, no spaces in front.)

=begin
misc. comments
=end

if I have any spaces or tabs in front of the =begin, it doesn’t see it as a comment

I did change things to use inspect rather than .to_s so thanks for that advice. I still can’t get

m 'testblock' [10,10,10]

to work directly as the args[0] parameter. I have to use

	  model = Sketchup.active_model
	  args[0] = model.selection[0]

to select the cuboid in order to move it

Brad