Подтвердить что ты не робот

Что такое замена ActionController:: Base.relative_url_root?

Я переношу приложение 2.x rails на rails3; мы будем называть это foo-app. Foo-app - это один раздел приложения с большим количеством рельсов и живет в main_rails_app.com/foo-app. Ранее мы только установили следующее в нашей конфигурации для создания foo-app, чтобы гарантировать, что наши маршруты foo-app работают правильно:

ActionController::Base.relative_url_root = "/foo-app"

Однако с rails3 я теперь получаю:

DEPRECATION WARNING: ActionController::Base.relative_url_root is ineffective. Please stop using it.

С тех пор я изменил запись конфигурации на следующее:

config.action_controller.relative_url_root = "/foo-app"

В основном это работает, что все вызовы внешних ресурсов (javascript/css/images) будут использовать /foo -app. Однако ни один из моих маршрутов не изменится соответствующим образом или иначе, foo-app root_path дает мне "/", когда я ожидаю "/foo-app".

Два вопроса:

  • Что такое замена для ActionController:: Base.relative_url_root
  • Если это config.action_controller.relative_url_root, то почему мои маршруты не отражают значение relative_url_root, которое я установил?
4b9b3361

Ответ 1

Вы должны иметь возможность обрабатывать все это в файле routes.rb. Оберните все ваши текущие маршруты в объеме; например.

scope "/context_root" do
   resources :controller
   resources :another_controller
   match 'welcome/', :to => "welcome#index"
   root :to => "welcome#index"
end

Затем вы можете проверить свою маршрутизацию через rake routes, чтобы они отображали ваши маршруты соответственно, включая ваш корень контекста (relative_url_root)

Ответ 2

Если вы развертываете через Passenger, используйте директиву RackBaseURI: http://www.modrails.com/documentation/Users%20guide%20Apache.html#RackBaseURI

В противном случае вы можете обернуть оператор run в config.ru следующим блоком:

map ActionController::Base.config.relative_url_root || "/" do
  run FooApp::Application
end

Тогда вам нужно только установить переменную среды RAILS_RELATIVE_URL_ROOT в "/foo-app". Это применимо даже к маршрутам, установленным в драгоценных камнях или плагинах.

Предупреждение: не смешивайте эти два решения.

Ответ 3

Мне кажется, что я должен слишком усложнять это и/или что-то пропустить, но эта проблема несколько раз разочаровала меня, и вот мои заметки.

Резюме

Для динамических и статических маршрутов существует две отдельные проблемы с двумя точками:

  • как получить маршрутизацию для правильного соответствия входящему URL-адресу
    • для маршрутов
    • для статических файлов
  • как создавать URL-адреса, которые включают relative_root
    • через помощников URL.
    • для статических активов

Один из способов решения всех четырех вопросов:

  • Настройте Nginx для разделения фрагмента relative_root
    • Это разрешает сопоставление маршрутов; просто пишите маршруты, ожидающие URL-адреса в /, как разработка
    • Также статические файлы подаются как в разработке
  • Установить переменную окружения RAILS_RELATIVE_URL_ROOT
    • Это решает генерируемые статические помощники актива
  • Использовать промежуточное программное обеспечение ScriptName ниже (изменить его, чтобы использовать значение из среды)
    • Это решает сгенерированные помощники URL-адресов, например. users_path

Обтекание приложения Rails в Rack:: URLMap в config.ru(ответ Кристофа)

# config.ru
map '/relative_root' do
  run Myapp::Application
end
  • требуется, чтобы входящий URL-адрес содержал relative_url_root (Nginx может быть настроен для удаления или сохранения этого, см. ниже).
  • Стойка добавляет relative_url_root в Rack env SCRIPT_NAME rack/urlmap.rb: 62
  • Rails добавляет текущий запрос SCRIPT_NAME к параметрам url_for metal/url_for.rb: 41
  • Rails 'url_for добавляет имя script при создании путей routing/url_for.rb: 133

Таким образом, он охватывает URL-адреса, сгенерированные помощниками URL-адресов, например. данный UserController, users_path будет иметь префикс относительного корня url.

Установите SCRIPT_NAME в промежуточное ПО

# config.ru
class ScriptName
  def initialize(app, name)
    @app = app
    @name = name
  end

  def call(env)
    env['SCRIPT_NAME'] += @name
    @app.call(env)
  end
end

use ScriptName, '/relative_root'
run Rails.application
  • Имеет такой же эффект, как и выше, но
  • Требуется, чтобы входящий URL-адрес не содержал relative_url_root

Настройка RAILS_RELATIVE_URL_ROOT

  • значение сохраняется в app.config.relative_url_root configuration.rb: 41
  • который, в свою очередь, влияет на пути активов asset_url_helper.rb: 137
  • но что он, насколько я вижу
  • особенно не влияет на помощников URL.

Настройка config.action_controller.relative_url_root

  • ?? Может повлиять на компиляцию активов?
  • Переопределяет RAILS_RELATIVE_URL_ROOT env var?

Явное определение всех маршрутов в /relative_root (ответ на rizzah)

# config/routes.rb
Myapp::Application.routes.draw do
  scope '/relative_root' do
    ...
  end
end
  • Помощники URL будут генерировать правильные URL-адреса.
  • Входящий URL-адрес должен содержать относительный корень URL-адреса (чувствительный к конфигурации Nginx, см. ниже), иначе исключения "нет соответствия маршрутам"
  • URL-адреса, запрашивающие статические активы, например. /relative_root/images/logo.png приведет к исключениям "без соответствия маршрутов". Это может и не быть проблемой, если nginx все равно служит статическим активам.

Конфигурация Nginx

Для такой конфигурации:

upstream myapp {
  server localhost:3000;
}

server {
  ...
  location /relative_root {
    proxy_pass http://myapp/;
  }
}

Nginx вычеркнет /relative_root, и приложение Rails не увидит его. Если вам нужно приложение Rails, так что см. Его, одним из способов является изменение строки proxy_pass:

...
    proxy_pass http://myapp/relative_root/;
...