Rails 3.1 возвращает необработанный код Javascript при использовании кнопки назад - PullRequest
19 голосов
/ 12 октября 2011

Моя основная цель

Приложение Rails, которое может загружать новый контент через Ajax, используя HTML5 для поддержания истории истории браузера.У меня супер базовая версия приложения , работающая на Heroku.Я также настроил общедоступный репозиторий GitHub , чтобы весь код, упомянутый ниже, можно было рассмотреть более подробно.

Проблема

Я успешно реализовал базовыйприложение, использующее API истории браузера HTML5 (в какой-то момент я также сделал версию, используя плагин History.js jQuery).Все работает как надо, пока пользователь не нажмет на ссылку, не являющуюся Ajax, а затем нажмет кнопку «Назад».Например, если пользователь щелкнул элемент 2, приложение успешно загрузит новый контент и изменит состояние браузера.Если они нажимают кнопку «Назад», он также корректно перезагружает предыдущее содержимое и изменяет состояние браузера обратно, чтобы соответствовать.Но если пользователь затем просматривает другую веб-страницу (любую другую страницу в Интернете), а затем нажимает кнопку «Назад» своего браузера, приложение Rails отображает необработанный javascript вместо исходной страницы.

Все работает до последнего шага,когда контроллер начинает возвращать необработанный javascript из show.js.erb вместо show.html.erb.Я попытался изменить несколько настроек в контроллере, но я не могу понять, что конкретно вызывает это.Я точно знаю, что если я удалю вызов history.pushState из show.js.erb, проблема прекратится (хотя, очевидно, я теряю всю функциональность истории браузера, которую я искал в первую очередь).

Любые идеи?

Бонус: мучительная деталь

Вот как все это работает (я думаю!).

Пользователь нажимает на ссылку, которая выглядит под капотом:

<%= link_to number_to_human(volume.number), volume_path(volume), :remote => true %>

Это отправляет запрос javascript на контроллер, который выглядит следующим образом:

def show
  @volume = Volume.find(params[:id])

  respond_to do |format|
    format.html # show.html.erb
    format.js # show.js.erb
    format.json { render json: @volume }
  end
end

Это передает запрос в show.js.erb, который выглядит следующим образом:

var stateObject = {"html": "<%= escape_javascript render(@volume) %>"};
history.pushState(stateObject,'',"<%= escape_javascript volume_path(@volume) %>");
$('#volumes').fadeTo(0, 0);
$('#volumes').html(stateObject.html).fadeTo('slow', 1.0);

, который затем заменяет содержимое тега div на исходной странице и использует pushState для создания объекта состояния и измененияURL страницы.

Затем пользователь может нажать кнопку «Назад» и JavaScript, прикрепленный к событию window.onpopstate в show.html.erb, перезагрузит соответствующий контент:

    if(history.pushState) {
    window.onpopstate = function(event) {  
        if (event.state != null) {
            $('#volumes').html(event.state.html);
        }
    }
}

Ответы [ 2 ]

18 голосов
/ 24 января 2012

Я очень новичок в RoR, поэтому я не уверен, что мой ответ будет лучшим, но я столкнулся с той же проблемой и сумел ее исправить. Итак, вот мои два цента.

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

response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate"
response.headers["Pragma"] = "no-cache"
response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT"
12 голосов
/ 18 сентября 2012

То, что сказал Джун выше, определенно сработало.Я просто добавил дополнительную проверку, чтобы увидеть, был ли запрос от ajax, прежде чем я добавил заголовкиСпасибо Джун!

if request.xhr?
    response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate"
    response.headers["Pragma"] = "no-cache"
    response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT"
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...