Возникла проблема, когда действие контроллера не проверяет обновленную базу данных в Rails - PullRequest
0 голосов
/ 15 ноября 2010

У меня есть приложение Rails, где пользователи могут следовать друг за другом. Я только что обнаружил ошибку, при которой пользователь может следовать за человеком более одного раза.

Если пользователь не следует за кем-то и открывает веб-сайт в двух разных окнах и нажимает кнопку «следовать» в обоих окнах, он следует за ним дважды.

В моем контроллере есть условие, которое, как я думал, предотвратит это, но оно не работает.

  def follow
   unless follows_arr.include?(params[:id])
    @r = current_user.relationships.build
    @r.friend_id = params[:id]
    @r.save
   end
  end

follows_arr - это массив идентификаторов пользователей, за которыми следует текущий пользователь (current_user.relationships.map {| u | u [: friend_id]}). params[:id] - это идентификатор человека, за которым пытается следовать пользователь.

По какой-то причине во второй раз, когда кто-то щелкает, следует в этой ситуации, контроллер не проверяет обновленную базу данных и создаются две одинаковые «взаимосвязи».

Я что-то здесь не так делаю? Есть ли другой способ сделать это?

Спасибо!

1 Ответ

2 голосов
/ 15 ноября 2010

«Реальный» ответ на вашу проблему заключается в том, что эти типы ограничений должны проверяться в модели, а не в контроллере (можно даже утверждать, что это следует проверять на уровне базы данных, но Rails просто не создан таким образом. 1001 *

Вы можете легко использовать метод validates_uniqueness_of в вашей модели, например ::

class Relationship < ActiveRecord::Base
   belongs_to follower
   belongs_to followed_user

  validates_uniqueness_of :followed_user, :scope => :follower
end

Что означало бы, что каждое, что followed_user должно быть уникальным для каждого последователя.

Что касается вашего исходного кода, трудно сказать, что происходит не так. Это может зависеть от того, откуда взялся follows_arr - возможно, он содержит некоторые кэшированные данные, или вы где-то кэшировали переменную самостоятельно.

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

Если вам нужно что-то сделать в контроллере, вы можете проверить так:

def follow
   ...
   if current_user.save
      # In this case everything was saved all right
   else
      # the user couldn't be saved for some reason (validation failed)
   end
 end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...