Create several related database records in the same view

2

I have two models in Rails, one is Worker and the other Assistance. A worker can have many assistances and each assistance is of a single worker.

I need to create a view where all the workers appear in each one and next to each worker I see the option to mark a boolean checkbox of the Assistance model, all in the same view and that when pressing save all the assistances of the workers are created at the same time.

What I have achieved is using nested resources and adding from the show view of each worker their attendance for that day, but I have not achieved what I asked previously. I do not know whether to create a new view, how to send the controller's data to the view, etc., I'm waiting for your help.

These are the corresponding models:

class Worker < ActiveRecord::Base
  belongs_to :report
  has_many :assistances, dependent: :destroy
  belongs_to :equip
end

class Assistance < ActiveRecord::Base
  belongs_to :worker
  validates :fecha,uniqueness: { scope: [:worker_id] } 
end

create_table "workers", force: :cascade do |t|
  t.string   "nombre"
  t.integer  "rut"
  t.text     "direccion"
  t.string   "telefono"
  t.string   "email"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
  t.integer  "equip_id"
end


create_table "assistances", force: :cascade do |t|
  t.integer  "worker_id"
  t.boolean  "asistio"
  t.boolean  "excepcion"
  t.date     "fecha"
  t.integer  "horas"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end
    
asked by Alvaro Andres Ponce Norambuena 04.01.2017 в 02:52
source

2 answers

1

This is a summary of what I think you want to do:

You want to be able to create many assists at the same time.

As I understand, that's all, because in the view you mean you will not create the workers. You just want to be able to list them to choose which of them you create a new assistance.

For this you want a page where all workers are listed next to a checkbox , and a "Create Assists" button so you can create assistance for the workers you marked with the checkbox.

Solution:

You can use the generic Rails to create the form:

<%= form_tag create_multiple_asistencias_path, method: :post do %>
  <table class="table">
    <tr>
      <th></th>
      <th>Trabajador</th>
    </tr>
    <% @trabajadores.each do |trabajador| %>
      <tr>
        <td><%= check_box_tag "trabajadores_ids[]", trabajador.id %></td>
        <td><%= trabajador.full_name %></td>
      </tr>
    <% end %>
  </table>
  <%= submit_tag "Crear Asistencias" %>
<% end %>

The brackets [] are fundamental, together with trabajadores_ids so that Rails knows that it is an array of values. That form assumes that there is a create_multiple method (and its path) in the #asistencias driver. We created them:

# En Routes.rb
# Versión usando Helper de rutas
resources :asistencias do
  collection do
    post 'create_multiple"
  end
end
# Opción básica
post "create_multiple", to: "asistencias#create_multiple"

The controller:

class AsistenciasController < ...
  ...
  def create_multiple
    @trabajadores = Trabajadores.find(params[:trabajadores_ids])
    @trabajadores.each do |trabajador|
      trabajador.asistencias.create(asistio: true)
    end
    redirect_to donde_quieras_path
  end

I think nothing escapes me and with that it should work.

Bonus: As above if it fails to create any assistance (for some validation for example), the application, would not warn us. For this we can do the following:

@trabajadores = Trabajadores.find(params[:trabajadores_ids])
@trabajadores.reject! do |trabajador|
  trabajador.asistencias.create(asistio: true)
end
if @trabajadores.empty?
  flash[:success] = "Se crearon todas las asistencias"
else
  flash[:danger] = "Fallaron las asistencias de #{@trabajadores.pluck(:full_name}"
end
redirect_to donde_quieras_path

Clarification of the bonus: The reject! method eliminates from @trabajadores all those from the true block (those that are saved correctly). That's why they remain in @trabajadores , only those that gave false in the block (they were not created).

    
answered by 08.03.2017 в 23:05
0

If you are slightly separated from the Rails conventions, it should not be difficult for you to generate an appropriate structure to read in the controller and send to your models.

Each of the checkboxes can have a style name of asistencia[worker_id] . The goal is to send a hash to the controller like the following: asistencia => { worker_id_1: true, worker_id_2: false, (...) } .

So you could generate a loop that reads this hash and update the assistance of each worker.

    
answered by 11.01.2017 в 11:57