Как я могу расширить ActiveRecord из приложения / модулей? - PullRequest
6 голосов
/ 09 июня 2011

У меня есть несколько различных act_as _... пользовательских методов класса, которые я хотел бы использовать в своем приложении.Я хотел бы, чтобы код этих методов был в файлах в каталоге app / modules.

Мне не удалось заставить это работать.

Например, у меня есть файл: app /modules / acts_as_lockable

module ActsAsLockable

    def acts_as_lockable
        before_create :set_lock

        include InstanceMethods
    end

    module InstanceMethods
        protected

        def set_lock
            now = Time.now.to_s
            self.lock = Digest::SHA1.hexdigest(now)
        end
    end

end

ActiveRecord::Base.extend ActsAsLockable

И в application.rb

config.autoload_paths += %W(#{config.root}/app/modules)

Когда я пытаюсь загрузить модель, которая вызывает act_as_lockable, я получаю следующую ошибку:

NameError: неопределенная локальная переменная или метод ʻ действие_as_lockable '

Я полагаю, что я не должен автоматически загружать папку модулей, поскольку ActiveRecord уже был загружен, когда я его расширяю?Есть ли другой способ сделать это?Я хотел бы иметь возможность изменять файл во время разработки, не перезагружая сервер, но это больше нужно, чем нужно.

Ответы [ 2 ]

7 голосов
/ 09 июня 2011

Я думаю, что вы думаете об этом неправильно.

Вы добавляете этот модуль в путь загрузки,

, но он будет загружаться, только если вы скажете;

require 'acts_as_lockable'

или

ActsAsLockable

Я бы посоветовал вам никогда по-настоящему не говорить ни одного из них в вашем коде.

Правильная парадигма, которую вы ищете, это"initializer".

Я предлагаю вам создать файл с именем "config / initializers / acts_as_lockable.rb"

В этом файле вы можете включить весь код,

илипросто включите require 'acts_as_lockable'

Обычно я храню подобные вещи в каталоге libs

, чтобы убедиться, что lib находится в пути загрузки

** config / application.rb **

config.autoload_paths += %W(#{config.root}/lib)

** lib / acts_as_lockable.rb **

module ActsAsLockable

  def acts_as_lockable
    before_create :set_lock

    include InstanceMethods
  end

  module InstanceMethods
    protected

    def set_lock
      now = Time.now.to_s
      self.lock = Digest::SHA1.hexdigest(now)
    end
  end

end

, затем в инициализаторе

** config / initializers / act_as_lockable.rb **

require 'acts_as_lockable'
ActiveRecord::Base.extend ActsAsLockable
0 голосов
/ 09 июня 2011

Проблема в том, что механизм автозагрузки ruby ​​- это ленивый процесс: когда в вашем коде используется константа, подобная ActsAsLockable, она ищет в файле autoload_paths файл activ_as_lockable.rb. Поскольку вы никогда не используете ActsAsLockable, файл никогда не загружается. Вы могли бы сделать (хотя и не очень красиво):

ActsAsLockable

class MyModel < ActiveRecord::Base
  acts_as_lockable

  ...
end

Я думаю, что act_as_ * должен использоваться в качестве плагинов и гемов, чтобы легко интегрировать функциональность в ваш код. Предполагается, что плагины и гемы находятся в конечном состоянии, когда вы интегрируете их в свой проект, поэтому вам не понадобится функция перезагрузки для режима разработки.

Надеюсь, это поможет.

...