Error when updating dynamic attribute with Ruby

Hi all,
when I try to update a dynamic component with a custom Ruby plugin I get the following errors:

Error: #<ArgumentError: comparison of Length with nil failed>

or

Error: #<TypeError: can't convert nil into an exact number>

depending on the value type I pass to set_attribute method.

In my code, I import a dynamic component saved in a hidden project and add it to current project, updating some dynamic attributes: length, width, …

my_instance = my_group.entities.add_instance(my_component, [0, 0, 0])
# updating custom_width, not LenX, because I need to perform some formulas
my_instance.definition.set_attribute('dynamic_attributes', 'custom_width', 20)

Once I force the redraw with

$dc_observers.get_latest_class.redraw(my_instance)

I get the errors above.
I’ve also tried to use 20.cm or "20" but I always get an error.

I get an error even when forcing the redraw without applying any changes.

my_instance = my_group.entities.add_instance(my_component, [0, 0, 0])
$dc_observers.get_latest_class.redraw(my_instance)

I also tried to apply changes before adding the component to the project:

my_component.set_attribute('dynamic_attributes', 'custom_width', 20)
my_instance = my_group.entities.add_instance(my_component, [0, 0, 0])
$dc_observers.get_latest_class.redraw(my_instance)

So my guess is that there’s an error somewhere in my dynamic component, but…

If I apply the change without redrawing the component, I see it in the “Component Options” window so it’s accepted. If I click on the “Apply” button the component is updated without any error.

Do you know where’s the problem?
Thanks for your help.

Basically, the Dynamic Components interface is a proprietary extension which has mostly methods that are for it’s own internal use.

It’s redraw method is needs to be called only after “certain other things” are set properly.

So, try instead using …

$dc_observers.get_latest_class.redraw_with_undo(my_instance)

… which does do the other “certain things” before calling it’s redraw method.

If you are using centimeters as the DC field units, the 20.cm in Ruby will be correct because everything on the Ruby-side is in inches.

However, if this dynamic field will differ between DC instances then you need to also set the particular instance’s field in it’s own dynamic dictionary. The field value in the definition’s dynamic dictionary is the “default” value for any new instances. (Whenever an instance is changed by the user, the definition’s value is changed so that the “default” is also the “most recently used” value.)

If instance(s) do not vary from each other or the definition default, then they will not have the field, and the DC code will use the definition’s dictionary value. (This reduces repetitive data.)

So this mean’s your plugin code must always check the instance’s dictionary first and then the definition.

But, nested dynamic groups always have all of their “dynamic attributes” within the group instance’s dynamic dictionary and not the definition.

Actually … modify this.

I reproduced your ArgumentError when just writing a numeric into the dictionary.

You need to basically do …

# At top of module:
DYNADICT ||= 'dynamic_attributes'

# later on ...
def set_dyna_attribute(instance, attr_name, value)
  instance.set_attribute(DYNADICT, attr_name, value)
  unless instance.is_a?(Sketchup::Group)
    instance.definition.set_attribute(DYNADICT, attr_name, value)
  end
end

# ... call it from elsewhere ...
set_dyna_attribute(my_instance, 'custom_width', 30.cm.to_s)

Now there are likely some conditional expressions that can be inserted into the method to convert the attribute value type to what the DC dictionary and it’s code expect.

  if instance.definition.get_attribute(DYNADICT, attr_name).is_a?(String)
    value = value.to_s
  end

I did not get the error calling plain-Jane redraw when a String value was written (as above.)

1 Like

Thanks, @DanRathbun.
And what about this:

my_instance = my_group.entities.add_instance(my_component, [0, 0, 0])
$dc_observers.get_latest_class.redraw(my_instance)

that generates an error even if no changes are applied to the component?

I just tried this, only using the model.entities rather than my_group.entities.

I get no error with a dynamic component definition from SketchUp’s own “Dynamic Components Training” collection.

It did take over 5 seconds to redraw (which is excessive IMO,) and did show the “This is taking a long time … Continue? Y/N” messagebox, but it did complete without errors.

If you are seeing an error then there is likely an error in your dynamic component’s attributes.

1 Like

Thank you for your precious help, @DanRathbun

1 Like