Частичное не обновляется при первом клике - PullRequest
0 голосов
/ 19 ноября 2010

У меня проблемы с удаленно выполняемым действием и партиалом, который не обновляется при первом нажатии на ссылку.

Внутри представления (частичное имя books) я создаю ссылку:

link_to "⊗", read_book_path(book), :remote => true

read_book_path определено в rout.rb Существует также условие, которое отображает другой текст при чтении этой книги.

Внутри моего контроллера я определил новое действие:

def read
  @books = Book.all
  @book = Book.find(params[:id])
  @book.read = !@book.read
  @book.save
  respond_to do |format|
    format.html { redirect_to(books_url) }
    format.js {render :layout => false, :locals => { :book => @book } }
  end
end

Это означает, что мне нужен файл read.js.erb, содержимое этого файла:

$("#books").empty().html("<%= escape_javascript( render(:partial => "books") ) %>");

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

Изменение ссылки на :remote => false также работает, но страница перезагружается (как и ожидалось).

Я попытался отладить его с помощью Safari и инструментов разработчика, и я вижу ответ сервера при первом нажатии на ссылку. Там что-то не так, HTML, сгенерированный <%= escape_javascript( render(:partial => "books") ) %>, содержит неправильный HTML со старым содержанием партиала. Только второй или третий щелчок показывает обновленный HTML.

Я интегрировал jquery-ujs - по этой ли причине частичное не обновляется в первый раз или я что-то упустил?

Это действительно дало мне головную боль, вы можете мне помочь?

Edit: Если это поможет: я создал слушателя в application.js для ajax:before и ajax:complete. Первый показывает небольшой счетчик, второй скрывает его. Когда я нажимаю на ссылку, вертушка отображается, но она не скрывается.

1 Ответ

1 голос
/ 19 ноября 2010

Похоже, у вас проблема с заказом, которая вызывает проблемы.Вы записываете полный набор книг в переменную @books, а затем изменяете отдельную копию одной книги.Это изменение не будет распространено обратно.

# Load and modify the one book by flipping the flag
@book = Book.find(params[:id])
@book.read = !@book.read
@book.save

# Load all books
@books = Book.all

Как примечание, это крайне неэффективный способ ведения дел, поэтому я надеюсь, что вы не работаете с большим объемом данных.Возможно, вам будет проще это сделать, просто переключив одно поле простым UPDATE запросом:

Book.update_all({ :read => true }, { :id => params[:id] })

Я не уверен, почему вы звоните $(...).empty().html(...) вместо простого $(...).html(...)поскольку метод html() должен заменить оптовый HTML без необходимости предварительно очищать его.

Одна вещь, которая может помочь, - это использование .js.rjs, где эквивалент будет:

page[:books].replace_html(:partial => 'books')

С помощью простого JavaScript, RJS позволяет вам избавиться от большого количества рутинной работы.Вы также можете использовать JS в RJS для случаев, когда нет эквивалента:

page << '$("#books").empty()'
page[:books].replace_html(:partial => 'books')

Чтобы сделать это более дружественным к Rails, вы можете назвать свой частичный _book, что сделает локальные переменные избыточными.У каждого частичного есть переменная по умолчанию с именем, совпадающим с именем шаблона:

render(:partial => 'book', :collection => @books)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...