There is a fundamental problem with how observers were originally implemented - they hooked directly to the internal notifications. This means they fire in the middle of native operations. So if you modify the model during observer events you might erase entities might the native operation have completed.
For this reason there is that warning in the API docs which Dan pointed out.
We haven’t had many best practices examples for the Ruby API and this is something we want to improve.
For observers we do however have a GitHub code example: https://github.com/SketchUp/sketchup-safe-observer-events
This demonstrate how you can defer model changes until the operation which triggered it is done. (Though note it have to resort to an ugly timer hack in order to defer because
ModelObserver.onTransactionStart/Commit will trigger for intermediate Ruby operations. But currently this is the safest way to perform model changes.
Also - as Dan mentions, when you do make model changes in reaction to observers you need to make sure you handle the undo stack correctly. If you explode an instance when it’s added that will create a new undo step - meaning the user would have to perform two undo actions, which is bad for usability.
Model changes based on observer callbacks should make their operations transparent to the operation they react to. This means setting the fourth argument of
model.start_operation to true. (Don’t use the third argument - we have plans to deprecate this because it’s just too unpredictable and nearly every use of it cause undesired side-effects.)
The GitHub example also demonstrate how to correctly start a transparent operation.
Note that if you call
model.abort_operation during a transparent operation you will not only abort the one you started, but also the operation to chained to. So be cautious about this and consider manually cleaning up and committing instead.