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

Rails 3.1 возвращает исходный код Javascript, когда используется кнопка возврата

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

Приложение 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);
        }
    }
}
4b9b3361

Ответ 1

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

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

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"

Ответ 2

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

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