0

I am creating a plugin for an existing rails application. I am not going to be able to make a change to the core application so I have to try and keep my changes external. As of now it seems like my best bet is an Observer (this is a pre-rails 4 project). I have setup a basic engine and observer, I can check that my observer is observing the right class in the console, but it isn't actually being loaded with the other Rails observers.

Here is my engine.rb:

module Moodlesync
  class Engine < ::Rails::Engine
    initializer "moodlesync.canvas_plugin" do
      require_dependency 'moodlesync/observer'

      Canvas::Plugin.register :moodlesync_importer, :export_system, {
          :name => proc { I18n.t(:name, 'Moodle Sync') },
          :author => 'Beau Severson',
          :description => proc { t(:description, 'Sync course changes across Canvas and Moodle.') },
          :version => Moodlesync::VERSION,
          :settings_partial => 'moodlesync/plugin_settings',
          :hide_from_users => true,
          :settings => {
            :api_key => nil,
            :api_url => nil,
          }
      }

      config.active_record.observers ||= []
      config.active_record.observers << ':course_observer'
    end
  end
end

Much of that is for setting up a "plugin" within this Rails app.

Here is my observer.rb:

class CourseObserver < ActiveRecord::Observer
  observe :course

  def after_update(course)
    p "------------------------------------"
    p "-- A course has just been updated --"
    p "------------------------------------"
  end
end

I took the namespacing off of here so I could access the base Course object. If I fire up my console I can check and see that the CourseObserver object is tracking the Course class correctly.

console > CourseObserver.observed_class
 => Course(id: integer, name: string, account_id: integer, ...

Unfortunately if I check to see which observers are actively running I don't see my CourseObserver.

console > ActiveRecord::Base.observers
 => [:cacher, :stream_item_cache, :live_events_observer] 

If I am in the console and check the configs, I do see it.

console > Rails.configuration.active_record.observers
 => [:cacher, :stream_item_cache, :live_events_observer, ":course_observer"] 

So it seems like my config is being pushed in after the observers are being loaded. I need to know how to get those injected BEFORE the pre-existing observers.

  • I don't necessarily have an answer, but it's worth noting that `":course_observer"` and `:course_observer` are two separate things, a string and a symbol. Do you see a change in behavior adding the symbol instead of a string? – kevinthompson Jul 10 '15 at 21:12
  • At this point I don't seem to get different functionality either way. I had brought in the quotes before when trying to use namespacing in my observers property. I had found another answer [here](http://stackoverflow.com/questions/17803809/observers-in-rails-engines) to a similar problem that suggested doing so. So it used to read `"Moodlesync::CourseObserver"`. Either way it seems my current issue is not having my `config.active_record.observers` assigned before Rails starts the observers in that array. – Beau Severson Jul 13 '15 at 15:51
  • Have you found a solution to your problem? I'm interested in doing something very similar to this. – FMCorz Aug 18 '17 at 09:51

1 Answers1

0

For the posterity's sake:

I think you are missing

config.before_initialize do
  config.active_record.observers << 'Moodlesync::CourseObserver'
end

If you have the observer inside your engine, you need to namespace it.

Here is how I managed to do something similar in one of my engines:

# lib/tool/engine.rb
module Tool
  class Engine < ::Rails::Engine
    isolate_namespace Tool

    config.before_initialize do
      config.active_record.observers << 'Tool::UserObserver'
    end
  end
end

# app/observers/tool/user_observer.rb
module Tool
  class UserObserver < ActiveRecord::Observer
   observe Tool::User

   # ...     
  end
end   

And in your rails console:

console > ActiveRecord::Base.observers
=> [:some_observer, :another_observer, "Tool::UserObserver"]
razvans
  • 3,172
  • 7
  • 22
  • 30