I have a Sinatra app with a Project
model and a Task
model, and a project has_many
tasks.
It's a composition type of relationship, meaning a project cannot exist without tasks associated.
I create a project on /projects/new
, then redirect to /projects/:id/tasks/new
to add tasks to the project. On the latter page, I:
The problem is, if one gets interrupted during any of the step above, then no tasks will be added and the project will be saved in the database with no tasks associated. This will result in errors when I calculate total task duration, and in other situations.
I could instantiate and save both records on the same page, and that would solve the problem.
But, is there a way to split Project
and Task
creation across dedicated URLs without this resulting in childless projects?
I would advise you to not create the Project until at least one Task has been created. You can do this by saving the project details in session
and then actually creating the Project from the tasks controller, for example (pseudocode):
# projects controller
def create
session[:new_project] = <extract session params to PORO>
redirect_to new_tasks_url
end
# tasks controller
def new
@new_project_params = session[:new_project]
# use this in the view as needed
end
def create
Project.transaction do
project = Project.create(session[:new_project])
project.tasks.create(task_params)
end
end
You can see how to use session
in Sinatra here: https://sinatrarb.com/faq.html#sessions
Another option is to change your code to allow Projects with no Tasks. My hunch tells me this is what users expect; if they create a project and then don't have time to create any tasks; they would maybe assume that the project would be actually saved.
This will result in errors when I calculate total task duration, and in other situations.
It seems like this particular problem could be resolved by just defaulting total task duration to 0. But then again, I don't know the actual purpose of your application here, so maybe I'm wrong.