Reputation: 805
I have a projects app that allows all Users on a team to create Tasks, I'd like a User to be able to add users to a Task (for example if multiple people were in a meeting). Essentially the new task form would have all the usernames of those on the team and the user could check a box by each name for anyone else who participated in the task.
Initially, I thought the best way to do this might be a has_many through:
relationship where I had:
Tasks:
class Task < ApplicationRecord
has_many :user_tasks
has_many :users, through: :user_tasks
Users:
class User < ApplicationRecord
has_many :user_tasks
has_many :tasks, through: :user_tasks
And User_Tasks:
class UserTask < ApplicationRecord
belongs_to :user
belongs_to :task
end
The idea was that when a new task is created any user_ids tagged in the task would create new entries in User_Tasks. But I am not 100% sure how to do that in the Task create action and I'm starting to wonder if this is over complicating things?
Is there a simpler way to do this? If not what is the best way to structure a create
action around this has_many through:
association?
Upvotes: 0
Views: 1483
Reputation: 102026
Its actually much simpler than you think. ActiveRecord creates an _ids
setter and getter for has_many
associations. The setter will automatically add/delete records in the join table. For example:
@task = Task.create!(user_ids: [1,2,3])
@task.user_ids # => [1,2,3]
Would create a task and three rows in the join table.
You can use this in forms with the collection helpers:
<%= form_for(@task) do |f| %>
...
<%= f.collection_checkboxes(:user_ids, User.all, :id, :name) %>
...
<% end %>
Here I am just guessing that your users have a name attribute (used for the text of the checkbox). You can use whatever collection you want instead of User.all
.
To whitelist the user_ids param (which is an array) use a hash option with an array as the value:
def task_params
params.require(:task).permit(:foo, :bar, user_ids: [])
end
This permits an array of permitted scalar types.
Upvotes: 1
Reputation: 1524
I think you're pretty much spot on with your associations. UserTask table is being automatically updated by Rails every time you add an object to the collection (either collection of tasks assigned to user or users assigned to a task). So with your current setup you should be able to do:
user = User.first
task = Task.first
user.tasks << task
which would also automatically create a record in UserTask
table.
That way you should be able to pull off in Task create action something like this:
task.users << User.find([1,2])
Upvotes: 1