When I cancel this inputbox I get a ruby error - why?

It’s a minor issue, but mildly annoying. It’s part of a plugin I use to draw scenery when designing a theatre set. The code is adapted from a very old plugin originally designed to draw timber and sheet material for woodworking designs. It’s not even an extension yet, but I’m trying to get it to function better than the original I adapted many years ago - maybe around the time of SU8? Before namespace protection and extensions vs. plugins…

I create an inputbox in Ruby, which works fine when I click OK.

Here’s the code that creates it and processes the inputs.

  prompts = ["Flat Height        ","Custom height?     ","Flat Width     ","Custom width?     ","Flat Thickness     "]

    if @defaultsF.nil?
      @defaultsF = ["14'",'0"',"4'",'0"','1"']
    end
    list = ["14'|10'|8'|6'","","6'|5'|4'|3'|2'6'|2'|1'6|1'","",""]
    results = UI.inputbox(prompts,@defaultsF, list, "Flat Size")

    myHeight, customHeight, myWidth, customWidth, myDepth = results

    customHeight = customHeight.to_l unless customHeight.nil?
    customWidth = customWidth.to_l unless customWidth.nil?
    myHeight = myHeight.to_l unless myHeight.nil? #Line 119
    myWidth = myWidth.to_l unless myWidth.nil?
    myDepth = myDepth.to_l unless myDepth.nil?

    if customHeight > 0.inch
      usedHeight = customHeight
    else
      usedHeight = myHeight
    end

    if customWidth > 0.inch
      usedWidth = customWidth
    else
      usedWidth = myWidth
    end

Looks like this in use:

But if I Cancel it, the Ruby console shows an error whose cause I don’t really understand.

Error: #<NoMethodError: undefined method `to_l' for false:FalseClass>
/Users/JohnWMcC/Library/Application Support/SketchUp 2020/SketchUp/Plugins/scenery.rb:119:in `createFlat'
/Users/JohnWMcC/Library/Application Support/SketchUp 2020/SketchUp/Plugins/scenery.rb:333:in `block in <top (required)>'

Line 119 is marked in the code extract above.
myHeight = myHeight.to_l unless myHeight.nil?

Why does Ruby complain about this line, rather than one just before or after?

And how does myHeight get set to False, if that’s the issue? The unless condition might be true - myHeight may still be nil if the inputbox doesn’t process because I clicked Cancel.

But why False in the error?

Do i need to initialise the parameters myHeight, myWidth etc to zero or some value when I first load the plugin? If so, how?

A check for __FileLoaded?__ at the end, which would run once only and initialise things there?

Or should I set the variables to zero after the line
if @defaultsF.nil?

As I don’t normally have the Ruby console open when drawing, I won’t see the error in normal use.

But I’m trying to learn to write clean code, and expect delivery today of the 4th Edition ‘Pickaxe’ book, to help me understand better the fundamentals of Ruby. Mostly, the plugins I wrote myself for my own use were adapted (sometimes heavily) from others’ code, and others were collaborative efforts with a more experienced SU Ruby coder who did all the tricky bits (Steve Baumgartner @slbaumgartner).

Any comments or help on the code would be much appreciated.

UI.inputbox returns false if the user presses cancel. That is being assigned to myHeight because it is the first in the list you assign to the return. The others will get nil since there isn’t a returned array to read them from.

Ah. That makes sense now.

I’ll try to work out how to fix it, unless you have a quick answer to that?

Should I check if the results variable is false before doing anything else with it?

Yes you should.

OK. Will try that.

That does it. Just added

    if results
      myHeight, customHeight, myWidth, customWidth, myDepth = results
    else
      return
    end

Thanks for the near-instant response, Steve.

ALWAYS.

The simplest habit is to always follow your inputbox call with a one liner (rather than the ifelseend.)

return if !results

… or …

return unless results

… whichever you prefer.

Using …

return unless results = UI.inputbox(prompts,@defaultsF, list, "Flat Size")

… works, but is contrary to Rubocop and it’s style rules. (if you use it to check your code.)


This same paradigm also applies to the use of other UI window methods (UI::select_directory, UI::openpanel, UI::savepanel to name a few.)

Thank you Dan.

I tried one liners, but got them wrong to start with (tried unless conditionX performY instead of performY unless conditionX).

I had partially figured that out later in the code

I knew there should be a simpler way, and I’ll try to follow it in future.

Do it the hard way unless there is an easier way. :wink:

1 Like

I don’t but it might be a good habit to get into. Worth using all the time?

I see the code on GitHub, and instructions for use.

Will give it a go soon. Thanks again.

1 Like

BTW, when a conditional expression follows another code statement (ie, the one liner as opposed to a normal conditional block,) it is called a conditional being in modifier position.

Reference the syntax primer page on Control Expressions and it’s section on "Modifier if and unless"


These rdoc syntax primer pages are listed on the main Ruby Core documentation entry page.
They have the path beginning "doc/syntax/". They are great for refreshing the mind if you’ve been away from Ruby for awhile.

1 Like