My 3 models follow a linear structure. Board has many Topics. Topic has many Posts.
My models look like this:
app/models/board.rb
class Board < ActiveRecord::Base
has_many :topics
...
end
app/models/topic.rb
class Topic < ActiveRecord::Base
belongs_to :user
belongs_to :board
has_many :posts
validates :title, presence: true, length: { maximum: 255 }
validates :user_id, presence: true
validates :board_id, presence: true
# Temporary holder for new topic content
attr_accessor :content
...
end
app/models/post.rb
class Post < ActiveRecord::Base
belongs_to :user
belongs_to :topic
validates :user_id, presence: true
validates :topic_id, presence: true
validates :content, length: { minimum: 8 }
end
app/views/topic/new.html.erb
<h1>Create new topic</h1>
Return to <%= link_to @board.title, @board %>
<div>
<%= form_for(:topic) do |f| %>
<%= render 'shared/error_messages', object: @topic %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.fields_for(:posts) do |p| %>
<%= p.label :content %>
<%= p.text_area :content %>
<% end %>
<%= f.submit "Post new topic", class: "button submit" %>
<% end %>
</div>
When I create a new Topic, part of the job of the topics_controller#create action is to also create a Post with the content provided by the user. Right now, what I end up doing is just deleting the Topic if the Post fails to save.
app/controllers/topics_controller.rb
def create
@board = Board.find(params[:id])
# Here, topic_params are just the strong parameters for Topic
@topic = @board.topics.build(topic_params.merge({user_id: current_user.id}))
# Blank post for the view
@post = Post.new
if @topic.save
post_content = {content: params[:topic][:content], user_id: current_user.id}
@post = @topic.posts.build(post_content)
if @post.save
flash[:success] = "Topic created"
redirect_to @topic
else
@topic.delete
render 'new'
end
else
render 'new'
end
end
I can't think of any other way to do this without changing the validations on the model. For @post to be valid, it must have a topic_id. So @topic has to have been successfully saved. But if @topic is valid and saves but @post does not save, then I don't want the @topic to remain the the database. It would be preferable if @topic and @post are only ever both created or neither of them are.