I’ve getting this error in the Ruby console when running a test plugin that uses the parametric.rb file (with module name changed) from another plugin from Sketchucation, and the same from a second (Grid) from the Extension Warehouse.
Error: #<NoMethodError: undefined method `short_class_name' for JWM::Flat:Module>
/Users/JohnWMcC/Library/Application Support/SketchUp 2020/SketchUp/Plugins/JWM_Flats/parametric.rb:407:in `block in <module:Flat>'
And while I don’t get the error in the su_grid plugin, freshly downloaded and installed from the Extension Warehouse, and after a restart of SU. It exhibits the behaviour this error causes. R-click on the grid and the context menu now says Edit::Sketchup::Samples::Grid::Grid.
I thought it might have been something I did, but it no longer works properly even in the SU grid plugin. su_grid_111.rbz (6.9 KB)
That’s the version I installed, and even after a fresh download, deleting the old file and folder, then reinstalling and re-starting SU, the behaviour is still the same.
su_grid/grid.rb just has a string “Grid” for the menu name, it’s not using that above short_class_name method.
if (not $grid_loaded)
add_separator_to_ ("Tools")
UI.menu("Tools").add_item("Grid") {
Sketchup.active_model.select_tool Sketchup::Samples::Grid::GridTool.new
}
$grid_loaded = true
end
The grid extension seems to work ok here, unless you think it’s a bug that it displays the full class name of the object selected in the context menu.
In su_grid/parametric.rb:
if (not $parametric_loaded)
$parametric_loaded = true
UI.add_context_menu_handler do |menu|
klass = Parametric.selection_parametric?
if( klass )
menu.add_separator
menu.add_item("Edit #{klass}") { Parametric.edit_selection }
end
end
end
It’s using the method Parametric.parametric? which either returns false or the first item in the selection
def Parametric.selection_parametric?
ss = Sketchup.active_model.selection
false if ss.count != 1
Parametric.parametric? ss.first
end
Maybe you modified that to include a short_class_name method?
Well, I think it’s ugly. And I thought it did have the reference to the short_class_name it it, but I’ve got several versions of parametric.rb now, and have been getting confused which is which. I see now that Grid doesn’t try to use it, but I thought an earlier version I had just showed Edit Grid. Rusty and perhaps faulty memory, then.
The Sketchucation plugin SU Draw Parametric Shapes, which i adapted from the original Sketchup team version on the Extension Warehouse, with ThomThom’s help, had an improved version of parametric.rb, which Steve Baumgartner adapted to keep the parameters in Edit in the original order, is the one I most recently started from.
That does work to use the short name.
Draw and Edit a Box and you get this:
I’ll have to study the code carefully to see why that works and mine doesn’t.
Maybe as @eneroth3 Christina suggests, that does use extend self? Will look and check.
[Just checked]
No, it doesn’t.
# If you use it in your own plugin, CHANGE THE MODULE NAME to replace JWM by your own initials and the name
# of your calling program instead of Shapes.
require 'sketchup.rb'
#=============================================================================
module JWM::Shapes
# Abstract class which should be inherited by implementing class.
class Parametric
# TODO(thomthom): The arguments for this class needs documenting. It looks
# like they are overloaded. But how many different mutations are there?
# SLB: As supported here, the alternatives for args[0] are:
# - a Hash of key => value parameters for a new object (unknown here how they were obtained)
# - an Entity selected by the user (via right-click menu?)
# - nil/missing
# @param [Hash] data
# @param [Geom::Transformation] transformation for the instance being edited, nil/missing for new
#
def initialize(*args)
jwm_shapes/parametric.rb uses a short_class_name method, but it also hides this with a local variable of the same name when setting the context menu
unless file_loaded?(__FILE__)
UI.add_context_menu_handler do |menu|
# klass_name = Parametric.selection_parametric?
# if klass_name
ent = Sketchup.active_model.selection.first
klass_path = Parametric.get_class(ent)
unless klass_path.nil?
short_class_name = klass_path.rpartition(/::/)[2]
if Parametric.selection_parametric?
menu.add_separator
menu.add_item("Edit #{short_class_name}") { Parametric.edit_selection }
end
end
end
file_loaded(__FILE__)
end
Edit: it’s not actually inside the class but still a bit confusing that it uses the same name.
My Ruby skills aren’t up to much so I’ve missed that somewhere in my code. I AM trying to learn the basics better, but still a long way to go in the latest 2013 edition of the PickAxe book, which I only received last Sunday.
Will re-look and try to fix.
Many thanks for your help in pointing me in the right direction.
Edit: another thing I’d like to do is to be able to change parametric.rb to use a 4-parameter inputbox, to allow for passing a Combo pick list to a couple of my arguments.
I think, in a rather muddled way, I need to add a new method in the Parametric class which the calling program will override, but can’t yet see clearly how to approach that.
But let me try to get the simpler version using short_class_name working first, and understand why it doesn’t in the version I’m working on for Flats only, to get the parametric code to work without erroring.
Sorry, I wasn’t clear about what ‘it’ I was referring to.
The Parametric class has a short_class_name method.
Outside that class, but still inside the module JWM::Shapes is a local variable short_class_name.
The method in Parametric class would always return “Parametric”. It’s just used for the Undo menu and the title of the inputbox.
The local variable in the context menu handler gets the class of the selected entity via the Parametric.get_class(ent) method that gets it from attributes that the program added at some earlier time. It’s retreiving the name of the class of the selected entitity from the attributes dictionary.
This line
short_class_name = klass_path.rpartition(/::/)[2]
Takes the String e.g. "Sketchup::Face"
Converts to an array
[“Sketchup”, “::”, “Face”]’
and takes just the 3rd element: "Face"
Maybe. That’s a matter of opinion and programming style. I’d get confused if they were the same.
The NoMethodErrorgenerally means (if it is in fact defined,) it’s is not in the scope of where it is called from.
The main problem we all have with “Parametric.rb” is that it was never properly deployed as a community library. Instead it was “bundled” with a number of SketchUp example extensions, some of which revised the Parametric object code, and some have not. So there are a number of differing versions out there which are not being well controlled (ie, version management.)
I find it really silly that Trimble modified the code to wrap it in a Sketchup::Samples::Grid namespace and then left the global variables polluting the ObjectSpace.
Now I just looked at “su_grid” ver 1.1.1 code …
There is an issue with the Parametric class. It is defined in a common namespace module, ie: Sketchup::Samples. It is not within the Sketchup::Samples::Grid extension module.
This means if there are differing versions of this class, published in several installed “sample” extensions, and they are loading, … then they are overwriting each other, potentially creating chaos.
Evidence that John’s version that he pasted into his own module, has comments by ThomThom which means it’s likely a newer version. The version of the Parametric class in the Grid v1.1.1 extension, is older and does not have these comments.
Anyway, … if the method is out of scope, you can always just extract the class name right in the context menu handler block …
UI.add_context_menu_handler do |menu|
if obj = Parametric.selection_parametric?
menu.add_separator
obj_name = obj.respond_to?(:typename) ? obj.typename : obj.class.name.split('::').last
menu.add_item("Edit #{obj_name}") { Parametric.edit_selection }
end
end
There are several ways to use library objects. Depends upon whether they are a module or a class.
For a module, it depends upon how it is written. It can be a mixin module which is used with include, or a library module which is used by making qualified calls (ie, Sketchup.version is an example of making a qualified call to a library module.)
Or it can be both (if written correctly,) and the module has both types of methods (module functions and mixin instance methods.)
For a class, it’s a bit easier. Normally you create a subclass …
require "su_parametric"
module JWM::Shapes
class Parametric < Sketchup::Samples::Parametric
def my_new_instance_method()
# code here
end
# ... etc. ...
end # class
end # extension module
… but as said above, there is a clash going on with multiple versions being defined.
@DanRathbun, I’m sure I haven’t got the skill set (yet, at least - I’m trying to learn Ruby better from the ground up, but still have long way to go), but I wonder if you could confirm whether it would be possible in principle to do an improved version of parametric.rb that wouldn’t break backward compatibility, but that would allow not only a three parameter input box, but if the calling program implemented a method for a four parameter one, could detect that and allow combo/dropdown values too.
Then maybe get the SU team to make it a ‘proper’ Community version and maintain it as a common working version, with version control?
And see if plugin authors who have used it, would repackage it with their main program, so that at least only one version would need to be maintained for the future?
I currently have three slightly different versions in active use - one for the Sketchucatio SU Draw Parametric Shapes, one for Grid (su_grid|), and one for my attempt to make my Scenery plugin work parametrically. They (should) only differ in their Module names, but in fact at least the su_grid one differs in the way it implements the Context menu. And I think I’ve discovered a small typo difference betwee my Scenery and SU Draw Parametric Shapes versions.
All very confusing!
As to having multiple copies on one installation of SU, @slbaumgartner adapted the code that I packaged with SU Draw Parametric Shapes, so that it didn’t double up context menu Edit entries, if two or more plugins used different versions in their own extensions. (which earlier versions, including the Extension Warehouse Community SU Shapes extension and the su_grid did, and may still do for all I know).
Maybe @thomthom who has now joined the SU team could comment on this suggestion? When he did help me with extending and improving the SU shapes and its enclosed community version of parametric.rb, he hadn’t yet joined SU.
I don’t think I was aware of those discussions. If I took part, i don’t remember it.
@slbaumgartner has a later version in the SketchUcation SU Draw Parametric Shapes extension, which returns the parameters in the Edit inputbox in the same order as the original input, and tidied up a few other bits of the code…
I was interested to read in the PickAxe book that Hash is now supposed to remember the order that key/value pairs were entered, but that wasn’t my experience, and the Community version of SU Shapes didn’t do that.
That’s one of two principal differences between the Plugin Store and the Extension Store versions of SU Shapes. The other is that I added four new shapes: Sphere (adapted from Dome), Helix, Helical Ramp, and Helical Ramp with Sides.
I needed the latter two for a model I was building at the time, the Helix was a needed precursor of those, and I added the Sphere for completeness. Then published it on SketchUcation
@thomthom didn’t want to cloud the original SU Shapes with the latter three shapes, but I think included the Sphere. I haven’t used the Community/EW version of SU Shapes since shortly after finishing it with @thomthom’s help, after I added the other shapes.
So (in my rather limited experience) the SketchUcation version of parametric.rb is the latest version I know of. I don’t know about Window Maker. I know of it, but haven’t used it for years if at all. And I’d never even heard of Onion Dome Creator. Where is it to be found?
I will if I can try to find all the parametric.rb versions in those, and any others I can find, and do a file compare on them, to see how they differ other than in file save date.
Yeah, I remember reading this as well. But it’s #rehash method might mix up the order?
What Ruby version do you think this happened?
I also remember this. I was in Thomas’ camp. As the helical objects weren’t manifold. I thot they could be in a sister extension, and their command be on their own submenu.
But, hey … there is plenty of room in the world for different “flavors”.
“Grid Tool”, “Onion Dome” and “Window Maker” ALL use version “1.0” in the Sketchup::Samples module.
Have a look at the “Window Maker” extension code. It actually reloads the same Sketchup::Samples::Parametric class (as the other extensions,) but then in it’s ownSketchup::Samples::Windows extension module, it subclasses the shared Parametric class and then makes subclass overrides as it’s own Window class. Ie … it looks like …
require 'su_windows/parametric.rb'
module Sketchup::Samples::Windows
#=====================================================================
# Define the main parametric window class
class Window < Sketchup::Samples::Parametric
# method overrides and extra method definitions ...
# etc...
EDIT (ADD): The “Onion Dome” extension does this same thing. Loads (or reloads) the common "parametric.rb" file, and then implements it’s own subclass of it.