Rob Sobers
Rob Sobers

Reputation: 21125

How do I create multiple new records in a single controller action?

I have a student profile page. There's a form on that page which allows you to create new Note record with for that student. Works well.

enter image description here

I want to add a new field above the "Note" text field labeled "Who?" which allows you to enter additional students, thereby logging notes in bulk:

enter image description here

I'm not quite sure how to structure my form and controller action to achieve this bulk creation of new Note records associated with each student listed.

I'm thinking of taking this approach:

POST to the same action (/notes#create) and detect the presence of the array field student_ids in the params and then do something like this:

params[:student_ids].each do |s|
  note_params[:event_attributes][:student_id] = s
  note = Note.new(note_params)
  note.save
end

But I'd have to modify note_params so that it contains the proper student_id reference on each iteration.

Currently, on the singular form, note_params looks like this:

=> {
           "content" => "test",
  "event_attributes" => {
           "student_id" => "2",
               "user_id" => "1",
          "is_milestone" => "0",
    "happened_at_string" => ""
  }
}

Is there a better/cleaner/easier way to do this without having to loop through each id and manually modify the params?

Upvotes: 1

Views: 1814

Answers (2)

Richard Peck
Richard Peck

Reputation: 76774

I think you'd be better creating some sort of join table for this functionality.

This way, you can create one note, and then "copy" it by simply duplicating the join records. The downside is that one note may be accessible to multiple people, but that's okay:

#app/models/student.rb
class Student < ActiveRecord::Base
   has_many :created_notes, class_name: "Note", foreign_key: :user_id
   has_and_belongs_to_many :notes
end

#app/models/note.rb
class Note < ActiveRecord::Base
   belongs_to :user #-> to know who made it
   has_and_belongs_to :users
end

Then you can use your notes#create method as follows:

#app/controllers/notes_controller.rb
class NotesController < ApplicationController
   def new
      @note  = current_user.created_notes.new
      @users = User.where.not(id: current_user.id)
   end

   def create
      @note = current_user.created_notes.new note_params
      @note.save
   end

   private

   def note_params
      params.require(:note).permit(:body, :user_ids)
   end
end

Thus, you'll be able to use the collection_select (or similar) functionality to define user_ids for your note:

#app/views/notes/new.html.erb
<%= form_for @note do |f| %>
   <%= f.collection_select :user_ids, @users, :id, :name %>
   <%= f.submit %>
<% end %>

Upvotes: 1

Barna Kovacs
Barna Kovacs

Reputation: 1276

You don't need to modify params that way.

params.fetch(:student_ids, []).each do |student_id|
  student = Student.find(student_id)
  note = student.notes.new(note_params)
  note.save
end

Upvotes: 1

Related Questions