DataTable i usuwanie rekordu

Witajcie!

Moje pytanie skierowane jest do tych, którzy używają DataTable w swoich railsowych apkach.

Mam dotychczas takie siermiężne rozwiązanie dotyczące usuwania rekordów z tabeli. Tj.: ostatnia kolumna “Akcje” i w niej

<%= link_to 'Delete', company_path(company.id), method: :delete, data: { confirm: "Na pewno usunąć?" } %>

lub coś na kształt tego powyżej i kontrolerze coś zbliżonego do:

 def destroy
    @company = Company.find(params[:id])   
    if @company.destroy
      redirect_to companies_url, notice: 'OK'
    else 
      flash[:alert] = 'Nie udało się usunąć'
      render :index
    end      
  end

To oczywiście działa, ale …“przeładowuje” stronę.
Chciałbym teraz to usuwanie wierszy zrobić “profi” :wink: :smile: tzn z wykorzystaniem “fnDeleteRow”. Znalazłem w necie naście różnych przykładów (bardziej i mniej egzotycznych :wink: ) i przyznaję się, że już mam mętlik w głowie.

Jak należy to poprawnie, zgodnie z duchem RoR, oprogramować?

  1. Przycisk widoczny w tabeli ma wyzwolić akcję w kontrolerze, tutaj ma być usunięty rekord z bazy i dodatkowo wywołać funkcję JS, która usunie wiersz z obiektu DataTable?
  2. Czy też może przycisk ma wyzwolić funkcję JS, a ta ma wywołać ajaxem akcję w kontrolerze usuwającą rekord z bazy i jeżeli nie ma błędu, to usunąć wiersz z obiektu DataTable?

A może jeszcze inaczej to winno być zrobione?
Podpowiedzcie proszę.

P.S.
Dane do oTable = DataTabe( {

})
pobieram wykorzystując ajax przy ustawionym serverSide: true

Cześć,

A gdyby tak zrobić cos takiego:

<%= link_to 'Delete', company_path(company.id), method: :delete, data: { confirm: "Na pewno usunąć?" }, remote: true %>

Tutaj chodzi głównie o remote: :true poczytaj

tutaj masz js w zwykłym js i coffee

Pytaj, jeśli coś nie działa.

PZDR!

Albo nie zrozumiałeś mojego pytania albo opowiadasz się za jakimś rozwiązaniem i ja nie rozumiem Ciebie.

Jak należy to poprawnie, zgodnie z duchem RoR, oprogramować?

  1. Przycisk widoczny w tabeli ma wyzwolić akcję w kontrolerze, tutaj ma być usunięty rekord z bazy i dodatkowo wywołać funkcję JS, która usunie wiersz z obiektu DataTable?
  2. Czy też może przycisk ma wyzwolić funkcję JS, a ta ma wywołać ajaxem akcję w kontrolerze usuwającą rekord z bazy i jeżeli nie ma błędu, to usunąć wiersz z obiektu DataTable?

A może jeszcze inaczej to winno być zrobione?

Rozwiń proszę swoją wypowiedź

A zadaj sobie pytanie co by się stało gdyby równocześnie wywołać metodę w kontrolerze, wraz z funkcją w js? Co jeśli rekord nie zostanie usunięty w bazie? Zostanie tylko usunięty w HTML, użytkownik po odświeżeniu dostanie znów ten rekord, i może tego nie zauważyć… To można rozwiązać na kilka sposobów, możesz wywołać również metode w kontrolerze która po usunięciu rekordu wywoła funkcję w js (foo.js.erb, link), ale najprostszym rozwiązaniem jest tutaj właśnie wywołać funkcję w js(AJAX) i jeżeli response sukces to usuwasz z html. Napisałem Ci gotowy przykład oparty o remote(gotowe nagłówki, csrf). Podsumowując pierwszy przykład odpada… No chyba że się mylę? Bo jestem juniorem… :smiley:

Czyli Twoja odpowiedź w pierwszym poście winna brzmieć:

“Rób wg metody z pkt 2)”

Tak?

Podsumowując pierwszy przykład odpada…

Jest punkt >2? Bo ja nie widzę :open_mouth:

A może jeszcze inaczej to winno być zrobione?
Podpowiedzcie proszę.

Chciałeś coś inaczej to odpowiedziałem. Coś nie tak?

Posty innych użytkowników powinno czytać ze zrozumieniem, i z szacunkiem że ktoś poświęcił twojemu problemowi troszeczkę swojego cennego czasu(nie chodzi o $)… A swoje posty sprzed 24h powinno się pamiętać!

A gdybyś poczytał dokumentację którą Ci wysłałem, i przeanalizowałbyś to co tam jest zamieszczone to łatwo domyślić się(już po samym js) które rozwiązanie jest lepsze…

Myślę że pomogłem choć troszeczkę.

PZDR!

Widzę jakieś nieporozumienie więc…

Najpierw niemerytoryczna część.

  • Tak, wdzięczny jestem za sugestie i za poświęcanie mi czasu.

  • Dwa, co do czytania ze zrozumieniem:

    Jest punkt >2? Bo ja nie widzę

Zatem trzeci raz to wkleję i tym razem dam odstęp między punktem 1 i 2

Jak należy to poprawnie, zgodnie z duchem RoR, oprogramować?

  1. Przycisk widoczny w tabeli ma wyzwolić akcję w kontrolerze, tutaj ma być usunięty rekord z bazy i dodatkowo wywołać funkcję JS, która usunie wiersz z obiektu DataTable?
  1. Czy też może przycisk ma wyzwolić funkcję JS, a ta ma wywołać ajaxem akcję w kontrolerze usuwającą rekord z bazy i jeżeli nie ma błędu, to usunąć wiersz z obiektu DataTable?

Czy teraz wyraźnie widać, że to są dwie drogi, a nie jedna droga z punktem 1 i punktem 2?
Czy teraz widać, że to co opisałeś, to punkt 2?

Sądzę, że można operację usuwania z tej tabeli zrobić na kilka sposobów ale mnie interesowało , by to było zgodne z duchem RoR.

Ja mam aktualnie tak jak to napisałeś:

<%= link_to 'Delete', company_path(company.id), method: :delete, data: { confirm: "Na pewno usunąć?" }, remote: true %>

a w kontrolerze:

  def destroy
    @company = Company.find(params[:id])   
     respond_to do |format|
      if @company.destroy
        format.html { redirect_to companies_url, success: "Skasowano blabla " }
        format.js
      end
    end
  end

a w pliku destroy.js

$(function() {
	var row = $(this).closest('tr');
	var nRow = row[0];
	$('.dataTable').dataTable().fnDeleteRow(nRow);

  return true;
});

Czyli :

Krok A) w kontrolerze usuwam rekord z bazy danych i jeżeli zostanie on poprawnie usunięty, to:
Krok B) wywołuję funkcję w JS, która usuwa rekord z tabeli (obiektu DataTable).

Moje pytanie jest natury akademickiej:

Jak należy to poprawnie, zgodnie z duchem RoR, oprogramować?

i nie bardzo zrozumiałem Twoją wypowiedź, zatem skąd te nerwy?

P.S.
“. A swoje posty sprzed 24h powinno się pamiętać!” - Zostawiamy bez komentarza i zrzucamy na późną godzinę i zmęczenie :wink: :smile:

Skoro napisałem że:

Podsumowując pierwszy przykład odpada...
Jest punkt >2? Bo ja nie widzę

To chyba można się domyślić że pozostaje wybrać 2 punkt? :smiley:

Dobra pozostawmy to już bo dużo by pisać, nie o to chodzi tutaj :wink:

Wracając do problemu, rozumiem że pytasz jak w js usunąć rekord który właśnie został usunięty w kontrolerze?

A nie wydaje się Tobie, że ja zrealizowałem to właśnie wg punktu 1?

Nie mam w “link_to …” nigdzie zdefiniowanego id=“moja_funkcja_JS” czyli przekazuję akcję do kontrolera. Tutaj najpierw usuwam rekord, a później, gdy się powiedzie, przekazuję do JS, by “odmalować ekran”.

Nie wiem, czy to co zrobiłem, to popelina, więc pytam, jaki sposób jest zgodny z duchem RoR.

  • Nie bardzo. Mój kontroler już usuwa ten rekord z bazy, a moja funkcja usuwa go z obiektu DataTable.

…I mam nadzieję, że tak jest poprawnie.

Przycisk widoczny w tabeli ma wyzwolić akcję w kontrolerze, tutaj ma być usunięty rekord z bazy i dodatkowo wywołać funkcję JS, która usunie wiersz z obiektu DataTable?

Gdyby brzmiało to tak:

Przycisk widoczny w tabeli ma wyzwolić akcję w kontrolerze, tutaj ma być usunięty rekord z bazy a później wywołać funkcję JS, która usunie wiersz z obiektu DataTable? 

To bym to inaczej zinterpretował :slight_smile: Hmm chyba czas iść spać, bo już mi się plącze…
Ja sobie to tak zinterpretowałem że ten przycisk odpala 2 funkcje naraz :wink:

Te dwa rozwiązania są ok - zgodne z RoR, ale to rozwiązanie które masz jest bardziej “profesjonalne” :wink:

PZDR!

Masz rację. :smile:
Powinienem napisać “…a później funkcję …” :smile:

I dzięki za konsultacje :smile:

Jest jeszcze 3ci wariant, będący odmianą 2go, czyli:

  • funkcja w JS ktora wola AJAX-owy delete,
  • i która usuwa rekord ‘na stronie’ OD RAZU, zakładając ‘optymistycznie’, że operacja się powiedzie
  • jeśli z jakiegoś powodu się nie powiedzie, przywraca rekord z powrotem (na poziomie UI)

Plusem jest to, że efekt jest ‘natychmiastowy’. I działa to tak, jak ‘optimistic locking’ vs ‘pessimistic locking’ czyli zamiast czekać na ‘zielone światło’, próbujemy wykonać operację, cofając ją w przypadku wystąpienia błędu.

2 Likes

Bardzo ciekawy pomysł.