Jeremy Bray
Jeremy Bray

Reputation: 444

Bulk add item rails 6

I have a little project management app.

In the app I have a Project, Item and Delivery Model.

class Project < ApplicationRecord
    has_many :locations, dependent: :destroy
    has_many :items, dependent: :destroy
    has_many :deliveries, dependent: :destroy
end

class Item < ApplicationRecord
  belongs_to :project
  belongs_to :location, optional: true
  has_many :delivery_items, dependent: :destroy
  has_many :deliveries, through: :delivery_items

  enum status: [:unscheduled, :scheduled, :delivered]
end

class Delivery < ApplicationRecord
  belongs_to :project
  has_many :delivery_items, dependent: :destroy
  has_many :items, through: :delivery_items

  enum status: [ :unapproved, :approved, :scheduled ]
end

I also have a delivery_item join table

class DeliveryItem < ApplicationRecord
  belongs_to :delivery
  belongs_to :item
end

I have added a new Model called location, which is a way of classifying the items into a group on the project.

class Location < ApplicationRecord
  belongs_to :project
  has_many :items
  has_many :part_numbers, through: :items

  def bulkadd(delivery)
    self.items.each do |row|
      batch << Product.new(row)
    end
  end
end

At the moment the user individually adds items to deliveries via a form on the page

<h6>Add to Delivery</h6>
<%= form_for @delivery_item, html: {class: 'form-inline'} do |form| %>

  <div class="form-group">
    <%= form.collection_select :delivery_id, @project.deliveries.all, :id, :date, placeholder: 'Add to Delivery', class: 'form-control' %>
  </div>
    <%= form.hidden_field :item_id, value: item.id %>
  
  <div class="form-group">
    <%= form.submit "Add",class: 'btn btn-primary' %>

  </div>
<% end %>

I would like to simplify the process by adding a bulk add button to each location which would add all of the associated items to the delivery selected has many items.

I know that I will need the delivery_item(delivery, item).

I just cant seem to get the final part to work in my brain

Upvotes: 0

Views: 210

Answers (1)

max
max

Reputation: 102318

When you create a has_many or has_and_belongs_to_many assocation the macro creates an others_ids setter/getter. In this case item_ids= which will automatically add/remove rows from the join table.

Its really easy to use this together with the form option helpers to create a select where the user can choose multiple records:

<%= form_for(@delivery) do |form| %>
  <div class="field">
    <%= f.label :item_ids, 'Select the items' %>
    <%= f.collection_select :item_ids, @items, :id, :name, multiple: true %>
  </div>
<% end %>

Or if you prefer checkboxes:

<%= form_for(@delivery) do |form| %>
  <div class="field">
    <%= f.label :item_ids, 'Select the items' %>
    <%= f.collection_check_boxes :item_ids, @items, :id, :name %>
  </div>
<% end %>

Replace :name with whatever attribute you want to use for the option text.

class DeliveriesController < ApplicationController
  before_action :set_delivery, only: [:show, :edit, :update, :destroy]
  # This avoids a database query in the view
  before_action :set_items, only: [:new, :edit]

  # POST /deliveries
  def create
    @delivery = Delivery.new(delivery_params)
    if @delivery.save
      redirect_to @delivery, notice: 'Delivery created'
    else
      set_items
      render :new
    end
  end

  # PUT|PATCH /deliveries/1
  def update
    if @delivery.update(delivery_params)
      redirect_to @delivery, notice: 'Delivery updated'
    else
      set_items
      render :edit
    end
  end

  private
 
  def set_delivery
    @delivery = Delivery.find(params[:id])
  end

  def set_items
    @items = Item.all
  end

  def delivery_item_params
    # Passing the hash `item_ids: []` allows an array of permitted scalar types.
    params.require(:delivery)
          .permit(:foo, :bar, :baz, item_ids: [])
  end
end

Upvotes: 1

Related Questions