Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a child model in rails (belongs_to) and pre-setting the parent ID

I'm sure I'm missing something simple, but not being aware of the right terminology in Rails, I can't find what I'm looking for....

A Project model has_many Task, and a Task belongs_to a Project.

My routes.rb has

resources :projects
resources :tasks

I can create/edit/modify Projects just fine, and I can also edit Tasks... but I can't seem to work out how to create a new Task, assigning the correct Project when doing so.

My Project page (eg. /projects/2) has an Add Task link which goes to /task/new, so I'm losing the connection. I don't want to make a nested resource, because Tasks, once created, will be uniquely identifiable by their ID, and in future has_many other models as well.

Is there a quick fix here?

edit Well I've managed to solve this.... it's ugly and it's horrible and I'm not sure why it has to be that way, but it works.

My routes:

resources :projects do
  resources :tasks, :only => [:new]
end

resources :tasks, :except => [:new]

My task controller:

def new
  @project = Project.find(params[:project_id])
  @task = @project.tasks.build
end

# Process the form for creating a new task.
def create
  @project = Project.find(params[:task][:project_id])
  @task = @project.tasks.build(params[:task])
  if @task.save
    flash[:success] = 'Task created.'
    redirect_to project_path(@project)
  else
    render 'new'
  end
end

And my Task form:

<%= semantic_form_for @task do |f| %>

<%= render 'shared/form_message', :object => f.object %>

<%= f.inputs do %>
    <%= f.input :name %>
    <%= f.input :project %>
<% end %>

<ul class="formActions">
    <li class="list"><%= link_to 'Back to list', project_path(@task.project) %></li>
    <li><%= f.submit "Save" %></li>
</ul>

<% end %>

I didn't want to have to put the project box on the form, and I'm still not sure why I have to, and also why I needed to take :create out of the nested routes. It also seems quite laborous, for such a common task, but it works, so.... I guess it's all good.


1 Answers

Make sure you build your new task through your project in your new task action so that it will come with the project ID already assigned. That should make your form generator behave nicely and do the right thing.

TasksController < AplicationController
  before_filter :get_project
  …
  def new
    @task = @project.tasks.build # don't use @task = Task.new here!
  end
  …
  def get_project
    @project = Project.find(params[:project_id])
  end
end

of course it is highly recommended to use nested routes with this.

resources :projects do
  resources :tasks
end
like image 155
edgerunner Avatar answered Dec 19 '25 05:12

edgerunner