Reputation: 694
I'm working on a simple rails task list app for learning purposes, and one of the things I would like to have on the app is to be able to create a new list at the same time as I can add in the tasks within that list. I have finalized the basic CRUD actions for creating lists, and now I want to add the capability for creating tasks at the same time as the creation of lists.
I have done some of the initial associations like so:
My List model:
class List < ApplicationRecord
has_many :tasks
accepts_nested_attributes_for :tasks
end
My Task model:
class Task < ApplicationRecord
belongs_to :list
end
Also I've changed my list_params
to return the tasks aswell:
def list_params
params.require(:list).permit(:title, :public, task_attributes: [:text])
end
Now my problem is with how to write the form for my list with the possibility to add a dynamic number of tasks within it, then send those tasks over to my create
action in order to save it.
My new
action is as simple as it gets:
def new
@list = List.new
end
My current form is like so:
<%= form_with scope: :list, url: lists_path, local: true do |form| %>
<p>
<%= form.label :title %><br>
<%= form.text_field :title %>
</p>
<p>
<%= form.label :public %><br>
<%= form.check_box :public %>
</p>
<h2>Tasks</h2>
<%= form.fields_for :tasks do |task_form| %>
<p>
<%= task_form.label :text %><br>
<%= task_form.text_field :text %><br>
</p>
<% end %>
<p>
<%= form.submit %>
</p>
<% end %>
I intend to use this for testing purposes, to first create a list with one task, then one with two tasks, and then finally create some code to be able to add new fields via javascript so I can create an indefinite number of tasks. The problem I am arriving at however, is that when I submit this form, and call params
at my create
action, I can see it contains my task:
params
{\"utf8\"=>\"✓\", \"authenticity_token\"=>\"...\", \"list\"=>{\"title\"=>\"list\", \"public\"=>\"0\", \"tasks\"=>{\"text\"=>\"task\"}}, \"commit\"=>\"Save List\", \"controller\"=>\"lists\", \"action\"=>\"create\"}"
But when I try to see what's contained within my list_params
what I get omits the tasks:
list_params
{\"title\"=>\"list\", \"public\"=>\"0\"}"
And beyond that, if I add two text fields in my tasks form, say filled with "task1" and "task2", what I get in the params
is only "task2", seemingly overwriting the previous task.
So my problems are
1) Am I doing my form correctly? How should I change it so it allows for multiple tasks?
2) Why doesn't my list_params
return any data from the task?
and I guess as a bonus, is there anything else that I am missing to be able to save a list at the same time as it's tasks?
EDIT: Here's the github link for my project if anyone wants to try it: https://github.com/bpromas/task-list
Upvotes: 0
Views: 111
Reputation: 292
I created a new rails app and tried to follow the code you provided.
rails new a
rails generate scaffold List title public:boolean
rails generate scaffold Task text list:references
rails db:migrate
Then I edited the models like yours
app/models/list.rb
class List < ApplicationRecord
has_many :tasks
accepts_nested_attributes_for :tasks
end
app/models/task.rb
class Task < ApplicationRecord
belongs_to :list
end
Now I looked your code and I did not understand how you initialized the tasks to be displayed in form.fields_for. I am going to print two possibilities that I am aware.
First possibility is creating a new instance of Task in _form.html.erb
<%= form.fields_for :tasks, Task.new do |task_form| %>
<p>
<%= task_form.label :text %><br>
<%= task_form.text_field :text %>
</p>
<% end %>
Second possibility is building new instances of Task in lists_controller.rb
def new
@list = List.new
@list.tasks.build
end
My list_params method is the same
def list_params
params.require(:list).permit(:title, :public, tasks_attributes: [:text])
end
For me with all the steps above the app is working properly saving the tasks for the respective list. Check out if the console is displaying a red message like that "Unpermitted parameter: :tasks_attributes", if so there is some missing step you need to look at.
The time you make this work then to change the code to display more task fields is easy, just pass an array of new Task in _form.html.erb or create more builds in lists_controller.rb
First alternative
<%= form.fields_for :tasks, [Task.new, Task.new] do |task_form| %>
<p>
<%= task_form.label :text %><br>
<%= task_form.text_field :text %>
</p>
<% end %>
Second alternative
def new
@list = List.new
2.times { @list.tasks.build }
end
Good luck !!
Upvotes: 0
Reputation: 647
Maybe this can help you.
Take a look at this gem: https://github.com/nathanvda/cocoon
Upvotes: 1