Реализация шаблона NullObject в Rails

Я приложение, где Post belongs_to :user Я хочу сохранить сообщения для удаленных пользователей. Это может привести к ошибкам при просмотре сообщения, автор которого был удален. Я пытался сделать это:

class Post < ActiveRecord::Base
  belongs_to :author, class_name: 'User', foreign_key: 'user_id'

  def author
    author || NullUser.new
    super
  end
end

Это вызывает ошибку "от уровня стека до глубины". Зачем? Я мог бы сделать это:

class Post < ActiveRecord::Base
  belongs_to :user

  def author
    user || NullUser.new
  end

  def author=(user)
    self.user = user
  end
end

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

2 ответа

Решение

Чтобы ответить на ваш вопрос,

1. def author
2.   author || NullUser.new
3.   super
4. end

В строке 1 вы определяете author метод. Затем в строке 2 вы снова вызываете этот авторский метод! Это продолжается, и вы получаете слишком большую ошибку на уровне стека. Правильный способ сделать это,

def author
  super || NullUser.new
end

Так что вы больше не вызываете метод author внутри себя. Вы просто вызываете суперкласс или возвращаете NullUser. Если вы получаете нулевую ошибку при звонке super, затем добавьте дополнительную нулевую проверку:

def author
  (super || NullUser.new) rescue NullUser.new
end

Оператор спасения отлавливает все ошибки и затем возвращает NullUser.new, так что вам не нужно беспокоиться о супер-выдаче ошибки.

РЕДАКТИРОВАТЬ:

Еще один способ обработки исключений супер-броска, который выглядит лучше:

def author
  (super rescue nil) || NullUser.new
end

Если вы хотите сохранить сообщения для удаленных пользователей, лучше не "удалять" их.

Альтернатива - "мягкое удаление". Просто добавьте логический столбец, скажем "удален" или "неактивен".

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

Таким образом, все было бы намного проще и понятнее.

Другой способ - "украсть" сообщения. При удалении пользователя переместите все его сообщения в специальную учетную запись пользователя, затем удалите его.

В любом случае вы не нарушите ассоциацию.

Другие вопросы по тегам