# PreSave observer is called twice

**URL:** <https://forums.sketchup.com/t/presave-observer-is-called-twice/60297>\
**Category:** Ruby API\
**Created:** [January 23, 2018, 5:38pm UTC](https://forums.sketchup.com/t/presave-observer-is-called-twice/60297 "2018-01-23T17:38:01Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![rajawat](https://avatars.discourse-cdn.com/v4/letter/r/ecd19e/32.png) [@rajawat](https://forums.sketchup.com/u/rajawat)\
**Post date:** [January 23, 2018, 5:38pm UTC](https://forums.sketchup.com/t/presave-observer-is-called-twice/60297/1 "2018-01-23T17:38:02Z")

</div>

Hi,  
I have attached a AppObserver to my model.  
When I export the model to obj sometimes. PreSave in the app observer is called twice.

Console Logs  
Exporting C:\Users\Ajay\Documents\Hexagon.skp to obj  
Export path: C:/Users/Ajay/AppData/Local/Temp/sentio/Hexagon/Hexagon/Hexagon.obj  
Pre save callback  
Pre save callback  
Error: #\<TypeError: reference to deleted DrawingElement\>

Even if i press Ctrl+S presave is called twice. Followed by two postsave

---

<div class="post-metadata">

**Author:** ![kengey](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/kengey/32/234545_2.png) [@kengey](https://forums.sketchup.com/u/kengey)\
**Post date:** [January 24, 2018, 4:34pm UTC](https://forums.sketchup.com/t/presave-observer-is-called-twice/60297/2 "2018-01-24T16:34:59Z")

</div>

Could you show us some code?

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [January 24, 2018, 5:27pm UTC](https://forums.sketchup.com/t/presave-observer-is-called-twice/60297/3 "2018-01-24T17:27:14Z")

</div>

> [@rajawat](#):
>
> When I export the model to obj sometimes. PreSave in the app observer is called twice.

This callback is actually documented in the [**`Sketchup::ModelObserver`**](http://ruby.sketchup.com/Sketchup/ModelObserver.html).

> [@kengey](#):
>
> Could you show us some code?

Paste this into Ruby Console …

```ruby
class ModelSpy < Sketchup::ModelObserver
  def self.attach
    Sketchup.active_model.add_observer(self::new)
  end
  def respond_to?(meth)
    puts "SketchUp polled #{self.class} for a #{meth.to_s} callback."
    super(meth)
  end
end

```

… then execute this …

```ruby
ModelSpy.attach

```

_Upon saving the model_, I see the following in SU2016 … v `16.1.1449`

```plaintext
SketchUp polled ModelSpy for a onPreSaveModel callback.
SketchUp polled ModelSpy for a onSaveModel callback.
SketchUp polled ModelSpy for a onPostSaveModel callback.

```

… so all looks good and normal.

* * *

@rajawat **What SketchUp version are you seeing this on?**  
(Your forum profile needs to be updated to show your SketchUp version.)

This **might** happen if your code has attached an observer twice. (Although in most cases, SketchUp will check to see if the object is already attached, and move it to the end of the callback queue, or ignore the attachment call.)

---

<div class="post-metadata">

**Author:** ![kengey](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/kengey/32/234545_2.png) [@kengey](https://forums.sketchup.com/u/kengey)\
**Post date:** [January 24, 2018, 7:19pm UTC](https://forums.sketchup.com/t/presave-observer-is-called-twice/60297/4 "2018-01-24T19:19:43Z")

</div>

> [@DanRathbun](#):
>
> This might happen if your code has attached an observer twice.

For that reason I asked him to show us some of his code 🙂

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [January 24, 2018, 10:34pm UTC](https://forums.sketchup.com/t/presave-observer-is-called-twice/60297/5 "2018-01-24T22:34:00Z")

</div>

There have been double callback call bugs in the past.

But I ran the test again with an OBJ file export and got the same normal expected output.  
No double calls.

**However,** the `onSaveModel` callback was the **old name** (version `6`) that is still there for backward compatibility.  
Going forward you should use only `onPostSaveModel` callback (version 8+).

**If you define both, SketchUp polls your observer object and will call both if they are both defined**

---

<div class="post-metadata">

**Author:** ![rajawat](https://avatars.discourse-cdn.com/v4/letter/r/ecd19e/32.png) [@rajawat](https://forums.sketchup.com/u/rajawat)\
**Post date:** [January 25, 2018, 10:24am UTC](https://forums.sketchup.com/t/presave-observer-is-called-twice/60297/6 "2018-01-25T10:24:30Z")

</div>

Here the code

```
  module Solutionario
  module Sentio

    REG_KEY = 'Sentio'.freeze
    PLATFORM = (Object::RUBY_PLATFORM =~ /mswin|mingw32/i) ? :windows : ((Object::RUBY_PLATFORM =~ /darwin/i) ? :mac : :other)

    attr_accessor :login_dialog
    attr_accessor :upload_dialog

    def self.display
      initializeAppObserver

      initializeModelObserver

    end

    def self.initializeAppObserver
      puts "Init app observer"
      if @appObserver == nil
        @appObserver = SentioAppObserver.new
        @appObserver.set_open_callback {|model| self.on_open_model(model)}
        @appObserver.set_quit_callback {self.on_quit}
        Sketchup.add_observer(@appObserver)
      end
    end

    def self.initializeModelObserver
      puts "Init model observer"
      @modelObserver = nil
      @modelObserver = SentioModelObserver.new
      @modelObserver.set_post_save_callback { |model| self.onPostSave }
      @modelObserver.set_pre_save_callback { |model| self.onPreSave }
      Sketchup.active_model.add_observer(@modelObserver)
    end

    def self.on_open_model(model)
      puts "Open model"
      if @state.eql? "upload"
        if @upload_dialog != nil
          @upload_dialog.activate
        end
      end
      self.initializeModelObserver
    end

    def self.on_quit
      puts "Quitting sketchup"
      if @upload_dialog != nil
        @upload_dialog.onQuit
      end
      Sketchup.active_model.remove_observer(@modelObserver)
      Sketchup.remove_observer(@appObserver)
    end

    def self.onPreSave
      puts "Pre save callback"
      if @upload_dialog != nil
        @upload_dialog.onPreSave
      end
    end

    def self.onPostSave
      puts "Post save callback"
      if @upload_dialog != nil
        @upload_dialog.onPostSave
      end
    end

    class SentioAppObserver < Sketchup::AppObserver

      def set_open_callback(&block)
        @open_model_callback = block
      end

      def onOpenModel(model)
        puts "Model opened:#{model}"
        @open_model_callback.call(model)
      end #onOpenModel

      def set_quit_callback(&block)
        @quit_callback = block
      end

      def onQuit
        @quit_callback.call
      end #onQuit

    end #class end

    unless file_loaded?( __FILE__ )
      menu = UI.menu('Plugins')

      #TODO Group the multiple menu items.
      menu.add_item('Sentio') {
        self.display
      }

      file_loaded( __FILE__ )
    end

  end
end
`

```

Also in PreSave callback i am removing a entity - ComponentInstance - which i have added for user and do not want to save in his/her model.

---

<div class="post-metadata">

**Author:** ![rajawat](https://avatars.discourse-cdn.com/v4/letter/r/ecd19e/32.png) [@rajawat](https://forums.sketchup.com/u/rajawat)\
**Post date:** [January 25, 2018, 10:38am UTC](https://forums.sketchup.com/t/presave-observer-is-called-twice/60297/7 "2018-01-25T10:38:36Z")

</div>

Steps to reproduce  
-Open the plugin twice.  
or  
Open the plugin then close it and then again open it . Press Ctrl+S

---

<div class="post-metadata">

**Author:** ![rajawat](https://avatars.discourse-cdn.com/v4/letter/r/ecd19e/32.png) [@rajawat](https://forums.sketchup.com/u/rajawat)\
**Post date:** [January 25, 2018, 4:59pm UTC](https://forums.sketchup.com/t/presave-observer-is-called-twice/60297/8 "2018-01-25T16:59:21Z")

</div>

Removing observer when dialog is closed helped me.  
How can I have only single instance of plugin running at a time ?

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [January 26, 2018, 6:18am UTC](https://forums.sketchup.com/t/presave-observer-is-called-twice/60297/9 "2018-01-26T06:18:18Z")

</div>

> [@rajawat](#):
>
> How can I have only single instance of plugin running at a time ?

Only load it once.

Observer objects do not need to be instantiated classes. They can be a module. Try this …

```ruby
module Solutionario
  module Sentio

    extend self

    REG_KEY = 'Sentio'.freeze
    IS_WIN =( Sketchup.platform == :platform_win rescue RUBY_PLATFORM !~ /darwin/i )
    IS_OSX = !IS_WIN

    attr_accessor :login_dialog
    attr_accessor :upload_dialog

    def init
      Sketchup.add_observer(self)
    end

    def expectsStartupModelNotifications
      return true
    end

    def onNewModel(model)
      puts "New model"
      if @state.eql? "upload"
        if @upload_dialog != nil
          @upload_dialog.activate
        end
      end
      model.add_observer(self)
    end

    def onOpenModel(model)
      puts "Open model"
      if @state.eql? "upload"
        if @upload_dialog != nil
          @upload_dialog.activate
        end
      end
      model.add_observer(self)
    end

    def onQuit
      puts "Quitting sketchup"
      if @upload_dialog != nil
        @upload_dialog.onQuit
      end
      # You do not really need to do this as SketchUp
      # will detach all observers during shutdown.
      Sketchup.active_model.remove_observer(self)
      Sketchup.remove_observer(self)
    end

    def onPreSaveModel(model)
      puts "Pre save callback"
      if @upload_dialog != nil
        @upload_dialog.onPreSave
      end
    end

    def onPostSaveModel(model)
      puts "Post save callback"
      if @upload_dialog != nil
        @upload_dialog.onPostSave
      end
    end

    unless file_loaded?( __FILE__ )
      menu = UI.menu('Plugins')

      #TODO Group the multiple menu items.
      menu.add_item('Sentio') {
        self.display
      }

      init() # attach the Sentio module as an AppObserver

      file_loaded( __FILE__ )
    end

  end
end

```

---

<div class="post-metadata">

**Author:** ![rajawat](https://avatars.discourse-cdn.com/v4/letter/r/ecd19e/32.png) [@rajawat](https://forums.sketchup.com/u/rajawat)\
**Post date:** [January 26, 2018, 9:32am UTC](https://forums.sketchup.com/t/presave-observer-is-called-twice/60297/10 "2018-01-26T09:32:23Z")

</div>

Thanks @DanRathbun

---

<div class="post-metadata">

**Author:** ![kengey](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/kengey/32/234545_2.png) [@kengey](https://forums.sketchup.com/u/kengey)\
**Post date:** [March 13, 2018, 8:52pm UTC](https://forums.sketchup.com/t/presave-observer-is-called-twice/60297/11 "2018-03-13T20:52:52Z")

</div>

> [@DanRathbun](#):
>
> Observer objects do not need to be instantiated classes. They can be a module. Try this …

Didn’t know that. Thanks for sharing.

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [March 14, 2018, 1:49pm UTC](https://forums.sketchup.com/t/presave-observer-is-called-twice/60297/12 "2018-03-14T13:49:14Z")

</div>

> [@kengey](#):
>
> Didn’t know that. Thanks for sharing.

No problem. If you think about it, a module is an instance of class Module, so it also is actually an instance object.

However, the key here with regard to SketchUp API observers is that they are now all _semi_-abstract, in that the classes have been made devoid of the actual prototype callbacks, which never did anything anyway. So the core developers decided that it was faster to “duck-type” observer objects by asking them if they respond to a callback before calling that callback.

In addition, the API has **never** hard typed any observer object by testing if it is descended from any particular observer superclass. This means that you can write more robust hybrid observer classes that have a mixture of callbacks from multiple observers. You don’t even need to declare any superclass for an observer. These hybrid observers often make it easier as the single module or class can share object references that otherwise would need to be passed around as method parameters in a clunky way.

The API observer classes only exist now as a means of documenting the optional callbacks (via YARD.)

---

<div class="post-metadata">

**Author:** ![system](https://global.discourse-cdn.com/sketchup/original/3X/f/2/f2a121500b085ed60806607a82720b092d800bb3.png) [@system](https://forums.sketchup.com/u/system)\
**Post date:** [June 14, 2018, 5:49am UTC](https://forums.sketchup.com/t/presave-observer-is-called-twice/60297/13 "2018-06-14T05:49:15Z")

</div>

Closed on June 14, 2018, 5:49am UTC

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.
