I am creating a forum software. I want to implement closing topic functionality. Closing a topic will prevent anyone from creating posts for the closed topic.
My current implementation
- TOPIC has many posts
- When a TOPIC is created, by default, a POST is also created for that TOPIC. Basically TOPIC has a
titleand derives body of content from POST’scontent.
class AddClosedToTopic < ActiveRecord::Migration
def change
add_column :topics, :closed, :boolean, default: false
end
end
- TOPIC has a column called
closed. Ifclosedis true, the topic is closed. By default, it’s set to false. - Whenever a user tries to create a post, I use the validation below to check if the topic is closed or not.
class Post < ActiveRecord::Base
. . .
validate :cannot_create_replies_to_closed_topic
# custom validation methods
def cannot_create_replies_to_closed_topic
topic = Topic.find_by_id(topic_id)
if topic.closed?
errors.add(:content, "can't be created for a topic that is closed")
end
end
end
Problem
This way works perfectly fine for a TOPIC that’s becomes closed some time after it’s created. However, when I create a new TOPIC, it becomes problematic.
Since in the POST validation, I do topic = Topic.find_by_id(topic_id), new topic that is currently being created won’t be in the database. So it throws NoMethodError.
NoMethodError in TopicsController#create
undefined method `closed?' for nil:NilClass
app/models/post.rb:16:in `cannot_create_replies_to_closed_topic'
app/controllers/topics_controller.rb:21:in `create'
Possible solution?
I think I have some method that can refer to the current topic being created somehow in the POST validation, I think this problem can be solved.
How can I do this? Or do you guys have other methods to solve this problem?
You could try something like an
after_createcallback in your Topic model to only create the post AFTER your topic is created, and set the topic_id in that method.Something like this:
This should solve your problem. You may have to modify some of your code to ensure that it creates the topic first, and then it should create the initial post after that. You may also want to modify your
cannot_create_replies_to_closed_topicmethod to ensure the initial post can be created.Hope this points you in the right direction!