Сохранить переменную экземпляра в database Rails

#ruby-on-rails #model #controller #instance #increment

#ruby-on-rails #Модель #контроллер #экземпляр #увеличить

Вопрос:

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

Модель выглядит следующим образом

 class Waiting < ApplicationRecord
def increment
    self.number_waiting  = 1
    save!
end
def decrement
    self.number_waiting -= 1
    save!
end
def reset
    self.number_waiting = 0
    save!
end
end
  

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

 class IndexController < ApplicationController
def index
    @waiting ||= Waiting.new(number_waiting: 0)
    @waiting.increment
    @waiting.save!
end
end
  

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

 <p id="waiting_counter">
        <% @waiting.increment %>
        <%= @waiting.number_waiting %>
        <% @waiting.save! %>
    </p>
  

По какой-то причине она всегда равна 2 и никогда не меняется… Несколько часов искал решение этой простой проблемы, пожалуйста, помогите.

Комментарии:

1. Можете ли вы дать описание того, какую проблему должен решать этот код? «Когда пользователь нажимает … тогда они должны видеть… и затем …»

2. Например, это что-то вроде автоматической системы запросов?

Ответ №1:

Пошаговое руководство по вашему коду, и должно быть очевидно, почему оно всегда равно 2.

Я предполагаю, что вы переходите к IndexController#index (вероятно, через indexes_path). Это создает совершенно новый ожидающий объект, инициализированный значением 0, который в следующей строке увеличивается на 1. Затем вы сохраняете ее.

Затем (предполагая, что html взят из index.html.erb) rails отобразит html, во время которого объект @waiting увеличивается еще раз, перед отображением значения, которое теперь равно 2. Затем этот объект снова сохраняется.

Она ведет себя точно так, как должна, однако я думаю, что реальная проблема заключается в том, что у вас может быть неправильное представление о том, как работает rails. При вызове индексного действия на контроллере результатом вызова этого действия (по умолчанию) является то, что страница index.html.erb будет отображаться, в течение которого оценивается встроенный ruby. Все это происходит на стороне сервера, а затем результирующий HTML отправляется обратно клиенту. У вас нет ничего на стороне клиента, чтобы инициировать запуск приращения.

Неясно, чего вы на самом деле пытаетесь достичь здесь, и каким образом ожидается вызов приращения.

После рассмотрения вашего вопроса мне пришло в голову, что, возможно, вы ожидаете, что переменная экземпляра будет доступна для всех запросов после инициализации. Это не так — каждый запрос будет получать новый экземпляр контроллера, поэтому при каждой перезагрузке page @instance изначально будет равен нулю и приведет к созданию нового ожидающего объекта. Вместо этого вам следует захватить ожидающий объект из базы данных и затем увеличить его, например:

 def index
    @waiting = Waiting.first
    @waiting ||= Waiting.new(number_waiting: 0)
    @waiting.increment
    @waiting.save!
end
  

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

Комментарии:

1. Большое спасибо за ваш пространный ответ, вы решили мою проблему. 🙂

2. рад, что смог помочь 🙂 если это действительно решит ваш вопрос, было бы здорово, если бы вы могли принять решение 🙂