Add Custom Attribute uppercase/lowercase in ruby

When I enter a custom attribute manually, it normally accepts any information, lowercase letter with uppercase letter, numbers, but when I use this script to insert the attribute, if I use uppercase letters it generates an error in the attribute afterwards:
ERROR: Unable to get property ‘value’ from undefined or null reference @ /components.js[309]

I tried to create the g10PorJan attribute through the script and it generates this error, if I put everything in lower case, g10porjan works normally.
But if you go manually in the component and type g10PorJan, it also works.

How to make the script create g10PorJan without error?

    module Attriperso
      def self.wrap_selection(entities)
        return if entities.empty?

        entities.grep(Sketchup::ComponentInstance).each do |entity|
          attribute_name = UI.inputbox(["Digite o nome do atributo"], ["NovoAtributo"], "Nome do Atributo")
          if attribute_name
            attribute_name = attribute_name[0].strip
            entity.set_attribute "dynamic_attributes", attribute_name, "-"
            entity.set_attribute "dynamic_attributes", "_#{attribute_name}_units", "_user"
            entity.set_attribute "dynamic_attributes", "_#{attribute_name}_formulaunits", "CENTIMETERS"

Is it necessary for the attribute to be in dynamic components?
this may help you:

anyway, I think you should replace (but I’m not sure…):

entity.set_attribute "dynamic_attributes", "#{attribute_name}" , "-"

No, this is frivolous as attribute_name is already a string.

The KEYS in the "dynamic_attributes" dictionaries must be lowercase. - CORRECTED (Twice) -

        dict = "dynamic_attributes"
        entities.grep(Sketchup::ComponentInstance) do |inst|
          results = UI.inputbox(
            ["Digite o nome do atributo"], ["NovoAtributo"], "Nome do Atributo"
          next unless results
          attribute_form  = results[0].strip
          attribute_label = attribute_form.gsub(/(\s+)/,'_')
          attribute_key   = attribute_label.downcase
          # DC attributes are defined upon the definition for components,
          # (but on the instance for groups):
          definition = inst.definition
          # The user sees the form label with spaces:
          definition.set_attribute( dict, "_#{attribute_key}_formlabel", attribute_form )
          # The internals use the attribute label in formulae with underscores:
          definition.set_attribute( dict, "_#{attribute_key}_label", attribute_label )
          definition.set_attribute( dict, "_#{attribute_key}_access", "TEXTBOX" )
          definition.set_attribute( dict, "_#{attribute_key}_units", "DEFAULT" )
          definition.set_attribute( dict, "_#{attribute_key}_formulaunits", "CENTIMETERS" )
          # This is the default attribute value:
          definition.set_attribute( dict, attribute_key, "1")
          $dc_observers.get_latest_class.redraw_with_undo( inst )

Note that #grep is an iterator method so you do not need to call #each on it’s results.

Use next instead of if to save an indentation block within iterators and make code more readable.

1 Like

Hi Dan, thank you very much.

But why manually can I capitalize letters without any problem, and in code I can’t?
It is very common to use capital letter in custom attribute.

You CAN use capital letters in the form label or label (ie, what the user sees in the dialog.)

However, the key for the actual value of the attribute will be the lowercase "_#{attribute_key}_label" value.
In the example I gave above, I had set the value to attribute_key but it also can be attribute_label (as long as any spaces are converted to underscore.) In fact, attribute_key also must have no spaces.

I’ll correct the example above rather than post it again.

This is the way that the author of the DC extension wrote the code and the way that it works.
As you have found, violate how the code works and then it does not work anymore.

It does not matter that the attribute dictionary keys are all lowercase as the user never sees any of the keys directly, especially keys beginning with "_" (underscore) as they are hidden. The author did this I suppose to ensure text matching which is important as a mismatch would cause an error.

By the way, I just noticed that this attribute is set to have numeric units settings. What if the user wants to create a STRING attribute ?

Also, the DEFAULT is units is text STRING.

Okay, I have edited the example above for clarity.

attribute_name is renamed to: attribute_key (This is the substring that is inserted into dictionary keys.)

attribute_label, what the user sees in the form as the label for the value editbox, is now: attribute_form
(This is exactly as entered in the inputbox with spaces.)

attribute_label is now only the name used in formulae to get this attribute’s value (from another attribute’s formula.)
This is what you would were thinking of as the attribute “name”. It must have whitespace replaced with underscore.

Dan, thanks again.
I’ll explain, we build many dynamic components, we have a portal with several subscribers, and in the production of components, we standardize several attribute names to facilitate visual identification during the process.

As many things we do are repetitive, I’m creating a plugin for internal use, which facilitates our creation of components.
One of the buttons is the one I put the code here.
As we have to set it to centimeters in every attribute, and also that the display in is the user’s measurement, then I created this button, it works perfectly, but there is this problem of not capitalizing the letters, which breaks our pattern of development.

But since we already use the default of every field having the first letter in capitals in all the attributes that we create in all components, I would need the plugin button to be able to place the attributes just as we place them manually.

See in the attached image that all our attributes made manually have the first identification letters in capital letters.

And the script that would be very useful for us, cannot set the attribute equal to the manual way.

I edited the example above. Did you see this ? Did you try it as edited ?

It now uses the attribute label as it is entered in your inputbox.

I see that the attribute labels actually begin with a listing order prefix like "b0", not a capital letter.

If you wish your code to do similar, then the code will need to prepend the listing order prefix onto both the attribute_key and attribute_label variables.

Yes, I tested Dan, it stops working and does not add the attribute, it gave an error in gsub.

Error: #<NoMethodError: undefined method `gsub' for nil:NilClass>


          attribute_form  = results[0].strip!

… should be:

          attribute_form  = results[0].strip

… because if the bang method does not do anything (found nothing to strip off,) then it returns nil.

This is a lesson. A common mistake in Ruby when using the bang (“!”) form of a method when the normal form should be used.

I corrected the above example (again). :roll_eyes:

1 Like

Nice Dan, worked perfectly!!! Thks very much!

1 Like

although this is a bit older topic (please excuse me) - just for me to be sure:

i probably programmed it wrong:

in my plugin i can enter a name of the attribute (key)

“a” or “A” (for now)

and give them different values.

when i read out via ruby, i get both “a” and “A” with their corresponding different values.
so somehow they are held in the dictionary.

but when i read them via sketchup-component-attribute-window -

they both are shown, but both with the value of “a”.

so: do i have to force the key-name-input to lower case generally?

thanx al lot!

view via ruby:

vie in sketchup:

regards stan

  1. Better to start your own topic, since this one is already solved!
  2. You are using the wrong tool to inspect your IFC attributes. The DC extension does not handle properly as you can see above posts.
    You can perhaps use, Attribute Inspector, Attribute Helper, Attribute Editor.… from Extension warehouse

ok, thanx a lot. stan