[talk] Using Ruby Modules
-
@thomthom said:
@morgan74 said:
But I have a question about adding methods to Sketchup classes :
I want to add a method to "Geom::Point3d", how can I use a special name ??Here my current code :
> > class Geom;;Point3d > > def myFirstMethod > > return(self.z*self.z) > > end > > end > >
It's impossible to be 100% sure no one else implements a method of the same name as your when you extend a shared module/class. But if you for instance prefix with your initials you decrease the likely hood that your method is overwritten.
Personally I don't extend the base Ruby and SketchUp classes because of the potential of name conflict. (Doesn't look as good - but it's safe.)
-
Hmm, i was wondering when\if these posts would get moved.
PS: if you guys need a easier hint to the 1264 thing send me a PM. I fear i may have set the bar too high!
-
@jessejames said:
Hmm, i was wondering when\if these posts would get moved.
This is an example of people who just cannot follow instructions. (sigh!) And then compound the error, by posting AGAIN, to acknowledge he sould not have posted there. (I shake my head in wonder..)
It just shows that the forum environment is not so good for tutorials. Even the dedicated Tutorials Forum allows reply posts. I wish we could lock our own topics such as my [info] thread.
But at least I tried...
-
@jessejames said:
Anyway the real reason i replied is because i would for you and I to create a nice WORKING example of the very nested module system you are referring to. And what better example to use than all the script in the default SketchUp examples folder...
- animation.rb
- attributes.rb
- box.rb
- contextmenu.rb
- linetool.rb
- selection.rb
Well yes I have been thinking about this.. but there are isssues.
-
I just know that some newbies are going to tweek, change and update the examples, without changing the namespaces. The examples need to be in some 'Google' namespace, as opposed to MY examples which would be in my namespace. These 'examples' I don't think would be sub-namspaced under the normal "Plugin" namespace ::PINE, but in an ::EXAMPLE namespace. (Most are not "true" plugins anyhow, more like code snippets we are supposed to paste into our own plugins.) I haven't yet finalized what the proper organized namespace trees should be, but I'm semi-close to publishing a proposed "Community Standard."
-
I have a huge list of my own projects I'm working on, or want to work on. (Some I've had to put aside, because they will rely on another project; or there's some bug in the API; or some missing feature not in the API that I will need. Anyway I either must wait until the API is updated, or create the functionality myself, propbably in C code.)
-
There is an issue of compensation. These scripts are the intellectual property of Google, although they have released them under terms close to the language of the MIT License. Yes, I would be helping everyone in the community, but ALSO, one of the largest software corporations in the world. I need income! I have bills, and am not employed. (The unemplyment rate here on the Florida Space Coast, is high and getting higher with the end of the Space Shuttle program.) I'd love to whip the Examples into shape. I'd love to correct every typo and missing argument description, etc within the API documents. But technical documentation is what I do for a living, and I feel that I should be paid, even if in the short term it's a discount payrate (I'm not greedy, and my expenses are low.)
@jessejames said:
The bad thing about a system like this is the fact that if people find it too confusing to implement they will just choose to be lazy instead -- and the last thing we need to do is help spread MORE laziness around this group! I always say a working example is the key to understanding systems like this.
True.. but there is also immense value in this. Last week one of the newbies I've been mentoring, PM'd me to ask for just this same thing. He wished me to provide him with a working skeleton of a tool plugin, into which he could paste his Tool class definition. (He even put a "## my tool code goes here" comment in his outline.)
I spent three 10 hour days putting together just such a skeleton, and then realized I could not keep doing these things. That is between 500-1000 dollars of work (depending on what you think the payrate should be.) I took a break, went on a walk, thought about it, and came to the conclusion that I need to genericize the code, AND implement it as a "Plugin Builder Wizard" (which would be a plugin itself.) Think about how a Software Installation Wizard works, and you'll get the idea. Sucessive forms, with choice controls (checkboxes, etc.) and the person would either use an "import file pathname" box (with a 'Browse' button of course,) OR a "paste code here textarea." (Their choice.)
So that's what I'm going to do with that project. But this cannot be free. I must have some kind of income from it.
Either individual license, or some entity, (commercial or benevolent,) needs to purchase it from me, for the salary-time I've put into it.To complicate it a bit... I had to stop work on that, in order to resume my project to update the Sketchup Extension class as the "wizard" project will require it. I had already revised the Extension class to v1.1.0 back in January, and have been running it since (but did not release it.) It was only a few simple, minor changes.
This update will be v2.0.0, and will have major changes, BUT also be BACKWARD COMPATIBLE with v1.0.0 (the original un-numbered Google release.)
In addition I have some features I want to put in there, but they may need to wait for v3.0.0 or I'll never get it (or my other projects) finished.
This also has the same compensation issues like I had stated above. How to release it? I will have 2 weeks (say 100 hours invested in v2.0.0,) and really need to be paid for this somehow. Either Google buys it and they release it, OR I need to convince users and developers that it's a good thing and pay some small token license fee. (Somewhere between one and five dollars US.) -
@dan rathbun said:
Well yes I have been thinking about this.. but there are isssues. [...snip...]
Ok Dan, let me make sure i follow you. I going to summarize your post and tell me if i am correct...?
You want to create a "namespace manager" plugin (for lack of better term?) that works like a typical installation wizard. A user of such plugin would create a script by writing code in a "toplevel" manner without worring about modules or even nested modules. THEN they would run the plugin which would auto wrap their code into a proper nesting of module namespaces with their name being the toplevel module space. So in the end, the scripter no longer has to worry about the confusing aspects of Ruby modules and can concentrate on writing usable code that will be safe from invading outside namespaces.
Is this correct?
Hey, this plugin may even work nicely on a nested folder structure of scripts in which to base it's "module nesting" on..? You create a toplevel folder with your name, then maybe a tools folder full of tools, then maybe a lib folder, and on and and on. -
@thomthom said:
What plugin was that? People can edit their own posts.
Hmm, i'll give a clue... the sum of his name is 1264. I'll let the advanced readers decifer the meaning
PS: I'm just glad it was not 666
-
@jessejames said:
@dan rathbun said:
Well yes I have been thinking about this.. but there are isssues. [...snip...]
I going to summarize your post and tell me if i am correct...?You want to create a "namespace manager" plugin (for lack of better term?) that works like a typical installation wizard.
Yes.. and NO. There would be a "Coder's Config" feature (dialog) where they set up defaults (name, company, Location, TopLevel Namespace, etc. etc.) but these defaults should be able to be overriden on a project basis, if say they were doing contract work for other than themselves (ie: another company.) So yes.. there ARE project management aspects.
And there would be Namespace Managemnt aspects, as some prolific coders are likely to subdivide their namespace into Catagorical subnamespaces (Anim, Export, Import, Report, Tool, Utility, Widget, whatever and however they'd want to organize their products.)
But it is really a "Proper Plugin Code Generator and Functionality Adder."
@jessejames said:
A user of such plugin would create a script by writing code in a "toplevel" manner without worring about modules or even nested modules. THEN they would run the plugin which would auto wrap their code into a proper nesting of module namespaces with their name being the toplevel module space.
Yes.. but with flexibility. (I'll just say that [for future possibilites,] they'll have the option of nesting their TopLevel namespace within other namespaces, even nested ones.)
More important. What I was speaking of in the previous post... is much more than a simple wrapper. It is specifically aimed at Tool class, and auto generates Extension loader scripts, optional Smustard Compatible Menu Scripts, Normal Menu Scripts, Toolbar Scripts, etc. It more than just "wraps" the raw tool class code, it also adds management functions, auto unload functions. It takes care of "doing it the correct AND safe way", ie it takes over the setup of the menu / toolbar command, so it's done correctly without creating a zillion uneeded tool objects every time the menu is clicked, etc. It sets things up so a coder can "publish" a safe tool call for other poeple to call (from another script, or a custom toolbar, etc.)
I suppose it could also work for normal non-plugins like Importers / Exporters etc. I'll just need to keep that in mind.@jessejames said:
So in the end, the scripter no longer has to worry about the confusing aspects of Ruby modules and can concentrate on writing usable code that will be safe from invading outside namespaces.
More exactly: "code that will NOT invade outside namespaces." (Meaning that crap scripts can still poop on the Objectspace, but it won't then do much more than waste memory. I still hate poop methods in Object getting inherited by every module and class.)
You are actually describing another item on my todo list. The "wrapper". (A linear command script really does not need a wizard; I've already shown in the forum how to put a couple of module blocks around them.) There's the possibility someone like you and I want to autowrap all code in our plugins folder, rather than manually edit every script we download.
And.. a proplific coder, may want a batch utility to autowrap all his project folders, rather than do it manually.
I may be speaking of several separate utilities here.@jessejames said:
Hey, this plugin may even work nicely on a nested folder structure of scripts in which to base it's "module nesting" on..? You create a toplevel folder with your name, then maybe a tools folder full of tools, then maybe a lib folder, and on and and on.
Yea you speak of a project folder and it's subfolders, such as we'd use with MS Visual Studio. They would contain the "raw" code snippets, and the Wizard would output the "distro" files in folders beneath the project's "distro" folder (which has a "plugins" folder.) Any file (a Extension registration rb,) that needs to go in the Plugins folder, would be put in the "distro/plugins" folder itself. From there it's manual copy to the real plugins folder (for your own testing,) or zip the fake "distro/plugins" folder for distribution/posting.
-
Of course the next campaign.. when we get everyone to wrap there code.
Is to get them to change their $vars to @@vars.Like $my_specific_plugin_menu_is_loaded
-
I use that syntax Dan. As far as I know, I was the first to try to make multiple plugins all work under the same main sub-menu, so as to not clutter the plugins menu.
If you have a problem with my coding, you can always PM me, or mention it in a specific plugin thread. But generalizing about all us noobs with bad habits or pros with bad habits, and talking bad about many of us who are trying hard to contribute is just bad taste. Knock it off.
Chris
-
@dan rathbun said:
Of course the next campaign.. when we get everyone to wrap there code.
Is to get them to change their $vars to @@vars.Like $my_specific_plugin_menu_is_loaded
Dan you bring up another very important point. Too many folks have this knee jerk reaction to create a global when they should be creating either class level or instance level variables. And i don't think they realize the danger of such behaviors. There is a reason why we feel pain, it both protects and teaches us.
I am starting to think that you should be the captain of this lost ship. Too many bad habits are propagating throughout this community. Someone needs to step up and say enough is enough already!
-
@chris fullmer said:
I use that syntax Dan. As far as I know, I was the first to try to make multiple plugins all work under the same main sub-menu, so as to not clutter the plugins menu.
Thats not even what this thread is about Chris. We are talking about namespaces here NOT how many Plugins Menu "commands" your script adds. Your inability to understand what we are talking about is the root of the problem. I don't blame you for learning how to script in a poor manner (namespace wise!) i blame Google and the other pros here who have not stepped up to the plate and made the tough decisions for all of us.
@chris fullmer said:
If you have a problem with my coding, you can always PM me, or mention it in a specific plugin thread. But generalizing about all us noobs with bad habits or pros with bad habits, and talking bad about many of us who are trying hard to contribute is just bad taste.
Sorry Chris but that is NOT how a community works. If i have a problem with your coding style, or if Dan has a problem, or even if John Doe has a problem, we can and should voice our problem publicly. THAT IS OUR RIGHT CHRIS! You made the decision to release public scripts and your public scripts are available for our criticism. If you cannot handle the heat, then get your scripts out of the kitchen!
You act as if we are just making up lies and i can assure you that is not the case. The problems we speak of are very real and infect this community from top to bottom. Obviously the problem is real because you're acting out in a "knee-jerk" emotional way to real criticism. If we are lying then feel free to offer the truth and correct us.
@chris fullmer said:
Knock it off.
Don't you even dare try to use your moderator status to scare anyone away from free speech Chris. You will never scare me, I can assure you of that!
However i want you to understand that nobody is picking on you "personally". Heck, believe it not i like you -- even when your insulting me sometimes . You have given much to the community however you missed something very important. Everyone in this group is guilty of writing poor Ruby code and I want to fix that. Even i have written poor Ruby code because i did not know any better. So we must reign in this madness or it will get out control and sink the whole ship!
I would really like for you to get involved with this effort Chris. Bring some real discussion to the table and we can work it out. But instead of getting all emotional -- try to bring some logic next time.
-
Could you guys (me saying this "generalizing" for the time being) take a little break, go out for a walk in the fresh air and come back a bit more relaxed?
Programming, coding and scripting should not be a reason for such heated discussions.
-
@gaieus said:
Could you guys (me saying this "generalizing" for the time being) take a little break, go out for a walk in the fresh air and come back a bit more relaxed?
Hi Gaieus,
I don't think these discussions are heated at all. SketchUp modelers and scripters are by far the most laid back and good hearted bunch of folks I've had the luxury of dealing with. I admit that I myself over react to criticism -- it's human nature. Chris is a very good Ruby scripter and deep down he knows that what we are talking about is real.
-
RUBY VERSION ISSUE: The toplevel scope operator
Ruby v1.8.0 does not allow the TopLevel scope operator prefix, ie:
class **::**MyTopLevel::MyPlugin::ThisClass
Ruby v1.8.6 does allow it. It basically tells Ruby to start looking at the TopLevel for an indentifier, instead of backing up thru each nesting level from the current level. (It speeds things up. It's similar to telling a system to start at the root of a drive when finding a file.)
I've removed the use of it in the examples in the [info] thread, as many users will be running v1.8.0 on Win32, and not know how to update their Sketchup Ruby. Also if the script is evaluated at the toplevel [which is the norm,] the prefix operator is really not needed.
-
@gaieus said:
Could you guys (me saying this "generalizing" for the time being) take a little break, go out for a walk in the fresh air and come back a bit more relaxed?
Gaieus.. I DID do just that when I first read Chris' responce (the day he posted it.) I was shocked and a bit angry at being treated this way!
I am just trying to teach. I am not using cuss words, and try not use ridicule tactics. (I had a math teacher in high school who did that if she called on you and you gave the wrong answer. "(Snidely) Eww.. looks like someone needs to do more homework." I hated that.)
Let's look at what I said:
@dan rathbun said:Of course the next campaign.. when we get everyone to wrap there code.
Is to get them to change their $vars to @@vars.Like $my_specific_plugin_menu_is_loaded
I see very few adjectives in that post. Certainly no cuss words. I wrote it in a very matter of fact way... just making a statement.
Look at Chris' responce! Chris says (or implies,) I'm "talking bad about many of us who are trying hard to contribute" and that what I have to say is "in bad taste." Then he ominously declares "Knock it off."
I would indeed, 'knock it off', if he can provide proof he also required the other respected SCF members who have previously said the same thing, to also "knock it off."
from topic: $ versus @@didier bur said:
I also use globals but it is a bad habit, ... But it is a lazy way of retaining values for your dialog boxes for instance, .... One can avoid globals when using classes and methods, class variables (@@) and objects variables (@).
@unknownuser said:
never, ever use globals in Ruby - beside name clash conflicts (as Didier said) you will have a lot of problems debugging it when someone else (your script or other) changes and you don't know why. of course you can use trace variable and see the caller stack, but why shoot yourself in the foot ?
@unknownuser said:
So, ensuring that variables are only accessible and changeable by certain well known bits of your program is just to make your life easier. ... Thinking about who needs to be able to access variables is a good exercise before you even approach a keyboard to ensure you've thought things through. ... The flip side is that those who have worked on multi-million line projects adopt these ways or working for a good reason and not just for the hell of it.
@unknownuser said:
For persistent data for Dialog Boxes, you should use Sketchup.write_default and Sketchup.read_default. The keys and values are stored in the registry (Windows) and the plist (Mac).
@tig said:
For a dialog's default values that you want keeping from session to session within a particular model, I write them as attributes to the model itself: ...
@unknownuser said:
So, there you have it - three solutions that avoid globals:
- Sketchup.read_default and Sketchup.write_default (persistent across SketchUp sessions and models)
- Attributes (persistent within a given model, between sessions)
- Class variables (@@variable) (persistent only within a SketchUp session)
All these things were said almost 2 years ago. The only thing that has changed is it's me saying it.
Chris also says that I'm "generalizing about all us noobs with bad habits or pros with bad habits..."
Well yes I may be.. but what am I supposed to do? Create a "Wall of Shame" thread, and start posting specific examples and naming names? That would embarass people. That is NOT my style.It has been done before... and noone said much about it. (Apparently because it was true.) It also seems that some commercial developers publish a list of scripts that cause conflicts with their products. (I think that is their right.)
I would rather generalize, than shame or embarass any certain person. If my arguments can convice someone to change their ways... then they will know themselves who they are, and whether they should should change their ways. ThomThom admits he's constantly changing his code for the better, but of course usually at the next revision. (He can't just snap his fingers.) I never said it should be done before any deadline.
The sadest part about all this... I clicked on Chris' plugin link in his signature line, and checked his list of plugins against my plugins folder. I've never downloaded any of them, so I can never have seen any of his code.
The statement about globals I made.. was prompted by someone else who sent me a code snippet, that had a global in it. That person probably learned it from seeing someone else's code.
I'm not going to name the noob, ... and I'm certainly not clairvoyant. There's no way I can possibly know who's code they learned it from.
Well.. I guess Chris wants to take credit for spreading the use of globals for submenu handles.
@Chris, Sorry if I inadvertantly struck a nerve Chris. Really... I'm not trying to make you angry. I'm trying to get you to see the better and easier way.
If you use a TopLevel "Fullmer" module (or whatever you want to name it,) your global $vars can just become module @@vars and they will serve you the same way. But then, they can never clash with anyone else's variables: global, class, module, instance or local.
Just as you can create getter and setter methods for instance @vars, you can create module getter and setter methods for @@vars.
So your Fullmer module can have Fullmer.submenu and Fullmer.submenu= methods that get and set the @@submenu variable.
Any plugin submodules can do the same thing, but each for their specific menuitem: @@menuitem, .menitem and .menuitem=
The bottome line is ... I tend to teach. I teach the right way. I will not tell anyone that a way is OK if not the right way.
It's a free country. Do what you want on your own computer. Do what you want in your own scripts. I dont have to use them.. OR I can modify the ones I may wish to use myself. No big deal.
Hey ... you don't need to even listen to me, or read what I say. But you absolutely DO NOT have the right to censure me when I speak the truth; or supress my freedom of expression if I'm not being profane.
I will apologize if I have let my exasperation and frustration with the state of Sketchup things (API etc.,) cause me to be sarcastic in some of my posts. Sorry for that.. I know I've done it.
I think I deserve an apology as well.
-
@Dan - I am sorry, I see now its all my fault. I saw your example line of code and assumed you must be pointing me out directly, because that is precisely my code. It is also virtually the only global I use, because I DO try hard to write clean code that won't mess up other people's scripts. I've used all those other tips you mentioned, because I don't want to be the one that messes someone elses code up. That precise example, of the global variable, is one I used a global on because that is how @Last had done it.
Anyhow, none of that matters. I'm sorry I came off so abruptly. I really thought you were calling my out directly. Even if you were, I should not have been so rough.
I did like the solid bit of example you provided. That is ALWAYS welcome.
ok, ok, back to the regularly scheduled thread about Modules...
-
Discussion of Wiki purpose and motives moved here.
Advertisement