Реализация шаблона 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
Если вы хотите сохранить сообщения для удаленных пользователей, лучше не "удалять" их.
Альтернатива - "мягкое удаление". Просто добавьте логический столбец, скажем "удален" или "неактивен".
Итак, когда вы собираетесь удалить пользователя, проверьте, есть ли у него сообщения. Если ничего, трудно удалить его. Если есть, мягкое удаление.
Таким образом, все было бы намного проще и понятнее.
Другой способ - "украсть" сообщения. При удалении пользователя переместите все его сообщения в специальную учетную запись пользователя, затем удалите его.
В любом случае вы не нарушите ассоциацию.