Глобальная функция Rails, доступная для всех объектов

#ruby-on-rails

#ruby-on-rails

Вопрос:

Я хотел бы создать функцию, current_order_week которая была бы доступна глобально во всем моем приложении и могла бы вызываться аналогично чему-то вроде current_user . Я не хочу использовать include ее в конкретной модели / контроллере, я просто хочу, чтобы она была доступна везде.

Я изменил свою /lib папку, включив в нее lib_extensions.rb файл, и добавил в этот файл:

 class Object
    def current_order_week
    end
end
  

Я изменил свою application.rb , чтобы включить:

 config.autoload_paths << Rails.root.join('lib')
config.eager_load_paths << Rails.root.join('lib')
  

Но когда я пытаюсь вызвать current_order_week с консоли или из теста, я все еще вижу:

NameError: undefined local variable or method 'current_order_week'
for main:Object

Что еще мне нужно сделать?

Ответ №1:

Вы должны добавить эту функцию в application_helper.rb файл. Все контроллеры расширяются от ApplicationController и ApplicationController включают ApplicationHelper .

 module ApplicationHelper
  def current_order_week
  end
end
  

Это будет доступно для использования в представлениях и контроллерах

Ответ №2:

Обезьянье исправление основных классов, таких как Object , обычно не является хорошей идеей, это может помешать работе некоторых драгоценных камней и т.д. И в целом может привести к болезненной отладке в будущем.

Если вы абсолютно хотите это сделать — автозагрузка не будет загружаться Object из библиотеки, потому что она уже определена. Создайте инициализатор в config/initializers , затем он будет загружен, но он не будет перезагружаться при изменениях кода.

Но лучший способ — включить такой код в ApplicationHelper , ApplicationRecord и ApplicationController

Ответ №3:

autoload_paths и eager_load_paths не включают модули, они только require файлы, в которых определены модули. Для использования current_order_week вам необходимо указать имя модуля:

 module Foo
  def current_order_week
    .
    .
    .
  end
end

Foo.current_order_week()
  

Для использования current_order_week без добавления к нему имени модуля, вам необходимо включить Foo в свои контроллеры и модели:

 class ApplicationController < ActionController::Base
  include Foo

  def some_action
    current_order_week()
  end
end

class ApplicationRecord < ActiveRecord::Base
  include Foo
end