-
Ruby indents are 2 spaces not 4.
-
I had given you the correct way to conditionally add one menu item at the end of all of the extension code, using the value of the module var
@@loaded. You moved that code to an improper place without a conditionalifkeeping the menu item from creating multiple entries in the menu should you need to reload the file again during development. -
I had correctly put the control of the import command in a method rather than define it within a code block passed directly to the menu item constructor call. Doing it your way will mean you have to close SketchUp and restart it each time you make code changes and want them to be applied. This slows down development.
Ruby is a dynamic language. This means that classes, modules and methods can be redefined at anytime. So if you tweak a method and want to apply the changes, then you reload therbfile you just edited and saved using Ruby’s globalload()method instead of the globalrequire()method. -
The
require 'csv'statement in theparse_csv_data()method is not needed because it is loaded inside arescueblock in theget_csv_data()method, which should always be called first as it only calls theload_csv_data()andparse_csv_data()data methods IF there is no error in loading theCSVlibrary. -
The
require 'win32ole'statement in theparse_xls_data()method is not needed because it is loaded inside arescueblock in theget_xls_data()method, which should always be called first as it only calls theload_xls_data()andparse_xls_data()data methods IF there is no error in loading theWIN32OLElibrary. -
Calling the
==method on a boolean object within a boolean evaluation is frivolous.
ie …if cbl == false
The referencecblwill be evaluated anyway, and as an expression of theifstatement the result will be tested for truthiness / falsity anyway. So use …
unless cbl… or …if !cbl -
On line 100 you have the reference identifier
chosenjust sttting there on a line by itself with no assignment or anything else. It was not previously defined and nothing is being done with it. I remove it. -
Your
colorByLayer()method has several problems.
a. It should not be a module method. (You do not need to define it withself.)
b. Ruby methods are named with all lowercase words separated with underscores. CamelCase identifiers are reserved for Module and Class identifiers. Iecolor_by_layer_toggle()
c. It is not called from anywhere in the file, so I’ll omit this from the code for simplicity sake. -
In several places you inserted a space between a method identifier and it’s parameter list opening parenthesis. This is a big “no no” and generates a warning. In future Ruby releases this warning is going to change to a
SyntaxErrorand such files will no longer load.
A lot of what I am seeing is you not knowing the basics of Ruby programming.
Really you need to make your life (and ours) easier by taking advantage of all the free tutorials and books on Ruby that are available.
Now the biggest problem that you yourself caused and why you get the NoMethodError is because when YOU did what I explain in (3) above, YOU also moved all the method definitions into a local block of code that is passed to the add_item() method when you created your menu item.
(Code blocks are a scope level.)
I will repost the correct way with a few extra statements of yours added. BUT this is the last time.
If you are going to mess up the code by moving things around then I’ll no longer waste my time.
@sWilliams, My original template above was written correctly. The OP messed it up. Yours has non-rubyish method names and incorrect placement of module variable definitions. Module variables MUST be defined before any use. They are NOT usually put at the bottom of code. They and constants are usually put at the top of the code.
I know you are trying to help, but giving the newb two competing templates and advice is counterproductive, IMO.
Here is the updated template …
Sirius_LoudspekerImporter_0.2.0.rb (3.8 KB)
Which looks like this …
# encoding: UTF-8
require 'sketchup.rb'
require 'extensions.rb'
# Show ruby console, to see if there are any mistakes
SKETCHUP_CONSOLE.show
module Sirius
module LoudspekerImporter
extend self
# CONSTANTS
VERSION = '0.2.0'
IS_WIN =( Sketchup.platform == :platform_win rescue RUBY_PLATFORM !~ /darwin/i )
if IS_WIN
require 'win32ole'
wsh_shell = WIN32OLE.new("WScript.Shell")
USER_DESKTOP_PATH ||= wsh_shell.SpecialFolders("Desktop")
USER_DOCUMENTS_PATH ||= wsh_shell.SpecialFolders("MyDocuments")
wsh_shell = nil # let GC clean it up
else # it's a Mac
USER_DESKTOP_PATH ||= "~/Desktop"
USER_DOCUMENTS_PATH ||= "~/Documents"
end
# MODULE VARIABLES
@@loaded = false unless defined?(@@loaded)
@@last_path ||= USER_DESKTOP_PATH
# PLUGIN METHODS
def import_control
UI.messagebox("Let's import some loudspeakers !")
filepath = UI.openpanel(
"Import loudspeaker file...",
@@last_path,
"CSV (Comma Separated values)|*.csv|XLS (Excel Workbook)|*.xls;*.xlsx||"
)
if filepath.nil? # UI.openpaneel returns nil if user cances the dialog
UI.messagebox("Import cancelled by user.")
return false
end
case File.extname(filepath)
when '.csv'
@@last_path = File.dirname(filepath)
get_csv_data(filepath)
when '.xls','.xlsx'
@@last_path = File.dirname(filepath)
get_excel_data(filepath)
else
msg = "Unknown filetype! Import cancelled."
puts "#{Module.nesting[0].name}: #{msg}"
puts " Filepath: \"#{filepath}\""
UI.messagebox(msg)
end
end ###
def get_csv_data(filepath)
begin
require 'csv' # load CSV library on demand
rescue => e
msg = "Error loading CSV Library! Import cancelled."
puts "#{Module.nesting[0].name}: #{msg}"
UI.messagebox(msg)
else
# No error. Load the CSV file and parse the data.
puts "#{Module.nesting[0].name}: Loading loudspeaker data file ..."
puts " \"#{filepath}\""
data = load_csv_data(filepath)
parse_csv_data(data)
end
end ###
def get_excel_data(filepath)
begin
require 'win32ole' # load WIN32OLE class on demand
rescue => e
msg = "Error loading WIN32OLE class! Import cancelled."
puts "#{Module.nesting[0].name}: #{msg}"
UI.messagebox(msg)
else
# No error. Load the XLS file and parse the data.
puts "#{Module.nesting[0].name}: Loading loudspeaker data file ..."
puts " \"#{filepath}\""
data = load_xls_data(filepath)
parse_xls_data(data)
end
end ###
def load_csv_data(filepath)
data = []
# File load code goes here
CSV.read(filepath, headers: true) do |row|
data << row
end
rescue => e
puts e.inspect
UI.messagebox("Error reading CSV file.\n#{e.message}")
else
UI.messagebox("#{data.length}, Loudpspeakers Read from File.")
ensure
return data # may be empty if a CSV error occurs
end ###
def load_xls_data(filepath)
data = []
# File load code goes here
UI.messagebox("#{data.length}, Loudpspeakers Read from File.")
return data
end ###
def parse_csv_data(data)
# Parse code goes here
#UI.messagebox("#{data.length}, Loudpspeakers Imported..")
end ###
def parse_xls_data(data)
# Parse code goes here
end ###
# Define Menu items only ONCE
unless @@loaded
UI.menu("Extensions").add_item("LS Importer") { import_control() }
@@loaded = true
end
end
end
![]()