Что такое замена 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, которое я установил?
Ответы
Ответ 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
Настройка 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/;
...