2016-01-22 4 views
2

Я испытываю непоследовательное поведение при использовании регулярной маршрутизации и AJAX в приложении Rails. У меня есть ссылка, функция которой заключается в том, чтобы разрушить связь has_many :through. Когда AJAX не используется, проблем нет. Когда используется AJAX (т. Е. Remote: true), ссылка разрушает связь, а также объект владельца.Rails: Непостоянное поведение с link_to (..., remote: true) при использовании отношений has_many

Вот подробности:

У меня есть простое приложение с моделями Reader, Book и Favorite. Читатель has_many книги через избранное, а также книгу has_many читателей через избранные. Когда я использую ссылку «Удалить из избранного», книга также уничтожается при использовании AJAX. Эта проблема не возникает, если у меня нет пульта: true. Вот лог-сервер:

Started DELETE "/favorites/5" for ::1 at 2016-01-22 08:06:03 -0800 
Processing by FavoritesController#destroy as JS 
    Parameters: {"id"=>"5"} 
    Favorite Load (0.2ms) SELECT "favorites".* FROM "favorites" WHERE  "favorites"."id" = ? LIMIT 1 [["id", 5]] 
    Book Load (0.1ms) SELECT "books".* FROM "books" WHERE "books"."id"  = ? LIMIT 1 [["id", 5]] 
    (0.1ms) begin transaction 
    SQL (0.3ms) DELETE FROM "favorites" WHERE "favorites"."id" = ?  [["id", 5]] 
    (1.9ms) commit transaction 
Redirected to http://localhost:3000/books/5 
Completed 302 Found in 5ms (ActiveRecord: 2.5ms) 


Started DELETE "/books/5" for ::1 at 2016-01-22 08:06:03 -0800 
Processing by BooksController#destroy as JS 
    Parameters: {"id"=>"5"} 
    Book Load (0.1ms) SELECT "books".* FROM "books" WHERE "books"."id"  = ? LIMIT 1 [["id", 5]] 
    (0.1ms) begin transaction 
    Favorite Load (0.2ms) SELECT "favorites".* FROM "favorites" WHERE  "favorites"."book_id" = ? [["book_id", 5]] 
    SQL (0.2ms) DELETE FROM "books" WHERE "books"."id" = ? [["id", 5]] 
    (0.9ms) commit transaction 
Redirected to http://localhost:3000/books 
Completed 302 Found in 7ms (ActiveRecord: 1.5ms) 

Вот что я считаю соответствующий код:

book.rb

class Book < ActiveRecord::Base 
    has_many :favorites, class_name: "Favorite", 
        foreign_key: "book_id", 
        dependent: :destroy 
    has_many :readers, through: :favorites 
end 

reader.rb

class Reader < ActiveRecord::Base 
    has_many :favorites, class_name: "Favorite", 
        foreign_key: "reader_id", 
        dependent: :destroy 
    has_many :books, through: :favorites 
    def add_favorite(book) 
    return if Favorite.exists?(book_id:book.id,reader_id:self.id) 
    favorites.create(book_id: book.id, reader_id: self.id) 
    self.reload 
    end 
end 

любимый. rb

class Favorite < ActiveRecord::Base 
end 

У меня есть ссылка «link_to» в представлении книг/шоу, в котором говорится «Добавить в избранное», если нет отношений с книгоиздателем и «Удалить из избранного», если есть связь с книжным читателем. Правильная ссылка генерируется в вспомогательном модуле.

books_helper.rb

module BooksHelper 
    def favorites_link_for(reader, book) 
    if reader && Favorite.exists?(book_id: book.id, reader_id: reader.id) 
     link_to("Remove From Favorites", Favorite.find_by(book_id: book.id, reader_id: reader.id), :method => 'delete', remote: true) 

    elsif reader && !Favorite.exists?(book_id: book.id, reader_id: reader.id) 
     link_to("Add To Favorites", favorites_path(book_id: book.id, reader_id: reader.id), :method => 'post', remote: true) 
    end 
    end 
end 

Единственный контроллер интерес favorites_controller.rb:

class FavoritesController < ApplicationController 
    def create 
    reader = Reader.find(params[:reader_id]) 
    @book = Book.find(params[:book_id]) 
    reader.add_favorite(Book.find(params[:book_id])) 
    redirect_to @book 
    end 

    def destroy 
    debugger 
    fav = Favorite.find(params[:id]) 
    @book = Book.find(fav.book_id) 
    fav.destroy 
    redirect_to @book 
    end 
end 

И единственный вид интерес книги/шоу:

<p id="notice"><%= notice %></p> 

<p> 
    <strong>Name:</strong> 
    <%= @book.name %> 
    <%= favorites_link_for(Reader.last, @book) %> 
</p> 

<%= link_to 'Edit', edit_book_path(@book) %> | 
<%= link_to 'Back', books_path %> 

полный код доступен здесь: https://github.com/JenDobson/rails-with-remote-issue/tree/broken Версия Rails - 4.2.2.

ответ

0

Проблема была вызвана наличием линии redirect_to @book в FavoritesController # destroy. Когда я удалил эту строку, все отлично работало. Эта строка должна была быть изменена в любом случае, чтобы разрешить разные ответы на страницы в html и js, хотя я до сих пор не понимаю, почему redirect_to @book заставляет книгу записывать в JS, но не под HTML. Я рад принять ответ от любого, кто может еще просветить меня по этому поводу.

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

class FavoritesController < ApplicationController 
def create 
    @reader = Reader.find(params[:reader_id]) 
    @book = Book.find(params[:book_id]) 
    @reader.add_favorite(Book.find(params[:book_id])) 
    respond_to do |format| 
     format.html { redirect_to @book } 
     format.js 
    end 
end 

def destroy 
    fav = Favorite.find(params[:id]) 
    @book = Book.find(fav.book_id) 
    @reader = Reader.find(fav.reader_id) 
    fav.destroy 
    respond_to do |format| 
     format.html { redirect_to @book } 
     format.js 
    end 
    end 
end 

код на GitHub было исправлено: https://github.com/JenDobson/rails-with-remote-issue/tree/master