Внедрить наблюдатель двигателя в приложение rails

Я создаю плагин для существующего приложения rails. Я не смогу внести изменения в основное приложение, поэтому я должен попытаться сохранить свои изменения внешними. На данный момент кажется, что мой лучший выбор — Observer (это проект до рельсов 4). Я настроил базовый движок и наблюдатель, я могу проверить, что мой наблюдатель наблюдает за правильным классом в консоли, но на самом деле он не загружается с другими наблюдателями Rails.

Вот мой движок.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

Большая часть этого предназначена для настройки «плагина» в этом приложении Rails.

Вот мой наблюдатель.rb:

class CourseObserver < ActiveRecord::Observer
  observe :course

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

Здесь я убрал пространство имен, чтобы получить доступ к базовому объекту Course. Если я запущу свою консоль, я смогу проверить и увидеть, что объект CourseObserver правильно отслеживает класс Course.

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

К сожалению, если я проверю, какие наблюдатели активно работают, я не увижу свой CourseObserver.

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

Если я нахожусь в консоли и проверяю конфиги, я это вижу.

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

Таким образом, похоже, что моя конфигурация загружается после загрузки наблюдателей. Мне нужно знать, как ввести их ДО появления ранее существовавших наблюдателей.


person Beau Severson    schedule 10.07.2015    source источник
comment
У меня не обязательно есть ответ, но стоит отметить, что ":course_observer" и :course_observer — это две разные вещи, строка и символ. Видите ли вы изменение в поведении при добавлении символа вместо строки?   -  person kevinthompson    schedule 11.07.2015
comment
На данный момент я, похоже, не получаю другой функциональности в любом случае. Раньше я приводил кавычки, когда пытался использовать пространство имен в свойстве наблюдателей. Я нашел другой ответ здесь на аналогичную проблему, которая предложила это сделать. Так что раньше читалось "Moodlesync::CourseObserver". В любом случае, моя текущая проблема заключается в том, что мой config.active_record.observers не назначен до того, как Rails запустит наблюдателей в этом массиве.   -  person Beau Severson    schedule 13.07.2015
comment
Вы нашли решение своей проблемы? Мне интересно сделать что-то очень похожее на это.   -  person FMCorz    schedule 18.08.2017


Ответы (1)


Ради потомства:

я думаю тебя не хватает

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

Если у вас есть наблюдатель внутри вашего движка, вам нужно создать для него пространство имен.

Вот как мне удалось сделать что-то подобное в одном из моих двигателей:

# 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   

И в вашей консоли рельсов:

console > ActiveRecord::Base.observers
=> [:some_observer, :another_observer, "Tool::UserObserver"]
person razvans    schedule 09.01.2018