O
O
O Di2015-06-18 22:25:04
Ruby on Rails
O Di, 2015-06-18 22:25:04

How to create a child object when linking self reference?

There is a self-attached Task model :

class Task < ActiveRecord::Base
  has_many    :subtasks, class_name: 'Task', foreign_key: "parent_id"
  belongs_to  :parent, class_name: 'Task'
  belongs_to  :user
  belongs_to  :project
end

Scheme:
class CreateTasks < ActiveRecord::Migration
  def change
    create_table :tasks do |t|
      t.string  :title
      t.text    :description
      t.string  :priority
      t.string  :status
      t.date    :scheduled
      t.date    :deadline
      t.integer :user_id
      t.integer :project_id

      t.references  :parent, index: true
      t.timestamps null: false
    end
  end
end

There are tasks (tasks), there are subtasks (subtasks), there is a key for communication - parent_id.
What I want:
When switching to the created task (it has already been created!) - the tasks#show action (path /task/:id), in addition to its description below, be able to add a subtask (subtask).
In code, without passing params, it would probably look like this:
@task = Task.find(params[:id])
@task.subtasks.new
@task.save

But how is this done in practice? SubtasksController is created and actions are described in it?
Are non-RESTful actions added to TasksController? Or something different? :)
So far I've googled the video from RailsCasts, but I don't know if it's my case.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
O
O Di, 2015-06-21
@insiki

Answer:
The 1st controller is enough - TasksController.
We add the "accepts_nested_attributes_for" parameter to the model, which passes additional parameters when creating an object.

class Task < ActiveRecord::Base
  has_many    :subtasks, class_name: 'Task', foreign_key: "parent_id"
  belongs_to  :parent, class_name: 'Task'
  accepts_nested_attributes_for :subtasks, allow_destroy: true
  belongs_to  :user
  belongs_to  :project
end

We add additional attributes for the subtask to the controller:
def task_params
  params.require(:task).permit(:title, :description, :priority, :status, :scheduled, :deadline, subtasks_attributes: [:title])
end

The form itself for creating subtasks looks like this:
<%= simple_form_for @task do |t| %>
  <%= t.simple_fields_for :subtasks, @task.subtasks.build do |f| %>
    <div class="form-inputs">
      <%= f.input :title %> 
    </div>
    <div class="form-actions">
      <%= f.button  :submit %>
    </div>
  <% end %>
<% end %>

P
Pavel Kononenko, 2015-06-18
@premas

If you are following RailsWay, then you should have 2 controllers. And if you do resource routing, then put subtasks in tasks.
If you move away from RailsWay towards designing an API for ajax-exchange of json data, then do what is convenient for you.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question