How to iterate over a collection of objects, one at a time, without using a multi-stage form?

I have a set of objects. What I would like to do is iterate over the entire collection, but show each object on the page / view on its own and allow the user to interact with each object individually. Ideally, I would prefer not to use a multi-part form if I can avoid it, for the reasons stated at the end of my question.

I am trying to implement screens such as the images below.

Screen 1 Screen 2

Basically, the application user is sent to a location to reconcile the inventory (of each product) at that location. This is what the screens show. For each product, they must update inventory.

Summary and requirements are as follows:

  • A location has_many inventory_items.
  • A user a reconciliation, .
  • A reconciliation habtm inventory_items && belongs_to :location.
  • An inventory_item habtm reconciliations && belongs_to :location.
  • , inventory_items .
  • inventory_items.
  • inventory_items , .... .

, :

# == Schema Information
#
# Table name: reconciliations
#
#  id          :integer          not null, primary key
#  location_id :integer
#  created_at  :datetime         not null
#  updated_at  :datetime         not null
#

class Reconciliation < ApplicationRecord
  belongs_to :location
  has_and_belongs_to_many :inventory_items
end

# == Schema Information
#
# Table name: locations
#
#  id         :integer          not null, primary key
#  name       :string
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

class Location < ApplicationRecord
  has_and_belongs_to_many :products
  has_many :inventory_items, inverse_of: :location
  accepts_nested_attributes_for :inventory_items
  has_many :reconciliations
end

# == Schema Information
#
# Table name: inventory_items
#
#  id                    :integer          not null, primary key
#  product_id            :integer
#  location_id           :integer
#  quantity_left         :integer
#  quantity_delivered    :integer
#  quantity_on_hand      :integer
#  date_of_last_delivery :datetime
#  created_at            :datetime         not null
#  updated_at            :datetime         not null
#

class InventoryItem < ApplicationRecord
  belongs_to :product
  belongs_to :location, inverse_of: :inventory_items
  has_and_belongs_to_many :reconciliations
end

inventory_items_reconciliations Join Table:

  create_table "inventory_items_reconciliations", id: false, force: :cascade do |t|
    t.bigint "inventory_item_id", null: false
    t.bigint "reconciliation_id", null: false
    t.index ["inventory_item_id", "reconciliation_id"], name: "index_inventory_item_id_reconciliation_id_join"
    t.index ["reconciliation_id", "inventory_item_id"], name: "index_reconciliation_id_inventory_item_id_join"
  end

routes.rb:

  resources :locations, shallow: true do
    resources :inventory_items
    resources :reconciliations
  end

ReconciliationsController#New:

  def new
    @location = Location.find(params[:location_id])
    @reconciliation = @location.reconciliations.new
    @inventory_items = @location.inventory_items
    @num_of_inventory_items = @inventory_items.coun
  end

app/views/reconciliations/new.html.erb:

<% @inventory_items.each do |inventory_item| %>
  <%= render 'form', reconciliation: @reconciliation, inventory_item: inventory_item %>
<% end %>

app/views/reconciliations/_form.html.erb:

<%= simple_form_for @reconciliation, url: :location_reconciliations do |f| %>
  <%= f.error_notification %>

  <strong>Name</strong>: <%= inventory_item.product.name %> <br />
  <strong>Quantity Left:</strong> <%= inventory_item.quantity_left %> <br />
  <strong>Quantity Delivered:</strong> <%= inventory_item.quantity_delivered %> <br />

  <div class="form-actions">
    <%= f.button :submit, "Update", class: "btn btn-primary" %>
  </div>
<% end %>

, , location.inventory_items , , , 1.

, :

  • inventory_items , .
  • .
  • (.. "" ), , inventory_item reconciled, (.. ).
  • , inventory_items , reconciliation , inventory_item reconiliation cycle.

Wicked Gem, , . , inventory_item , .

.

, ?

+4
3

... . , . , -, .

, display="none" selectionOnChange onFormSubmit , , - .

+1

. ( ). , . , . , ... , ( ). . .

ReconciliationsController

def new
  @location = Location.find(params[:location_id])
  # Start reconciliation (without items)
  @reconciliation = @location.reconciliations.new
end

def create
  @location = Location.find(params[:location_id])
  # Create an empty reconciliation (params do not include items)
  @reconciliation = @location.reconciliations.new(reconciliation_params)

  @inventory_items = @location.inventory_items

  # Add items from location (this may require some changes depending on how you defined your models
  # If it does not work, you can create all inventory items in a loop
  # for each @inventory_items
  @reconciliation.inventory_items = @inventory_items

  if @reconciliation.save
    #Start editing reconciliation, from first item
    redirect_to edit_reconciliation_path(@reconciliation, item: 0)
  else
    redirect_to 'new'
  end

end

def edit
  @reconciliation = Reconciliation.find(params[:id])
  @inventory_items = @reconciliation.inventory_items.order(:id)
  @inventory_item = @inventory_items[params[:item]]
  @item = params[:item].to_i + 1
  @item = -1 if @inventory_items[@item].nil? # End condition.
end

def update
  @reconciliation = Reconciliation.find(params[:id])
  @reconciliation.update_attributes(reconciliation_params)
  if params[:item] != -1
    redirect_to edit_reconciliation_path(@reconciliation, item: item)
  else
    redirect_to root_path
  end
end

//

<%= simple_form_for @reconciliation do |f| %>
  .... fields for the reconciliation.
  .... Don't include the form for inventory_items
  .... So that you create an empty reconciliation
  <%= hidden_field :location_id %>
  <%= f.submit "Start reconciliation %>
<% end %>

//

<%= simple_form_for @reconciliation do |f| %>
  .... fields for the reconciliation.
  .... Include the form for only 1 inventory_item

  <%= f.simple_fields_for @inventory_item do |ff| %>

    <%= @inventory_item.product.name %> <br />
    </strong> <%= @inventory_item.quantity_left %> <br />
    </strong> <%= @inventory_item.quantity_delivered %> <br />
    ... Fields to change data
    <%= hidden_field :item %>

  <% end %>

  <%= f.submit (@item == -1 ? "Finish" : "Next") %>
<% end %>
+1

?

i) " , . .

ii) [ ]. , .

user has_many items

warehouse has_many accounts

accounts has_many items

warehouse has_many items, throught: :accounts

item _to warehouse

class Product
   has_many :items
   accepts_nested_attributes_for :items
end

class Item
   belongs_to :product
end

class Account
   has_many :products
   has_many :warehouses, through: :products
end

class Warehouse 
   has_many :products
   has_many :accounts, through: :products
end

routes.rb

resources :warehouses do 
    resources :products
    resources :accounts
end

resources :accounts do 
    resources :products
    resources :warehouses
end

resources :products do 
    resources :items
end

account reconciled.

. Product.

enter image description here

form_for @product do |f|
   <!-- your fields: account_id and number of items--> 
   f.fields_for :items do |item|
     <!-- your item -->
   end
   f.submit
end

Controller #

def update
    warehouse = Warehouse.find(params[:warehouse_id])
    @product = warehouse.products.first
    # needs to be refactored
    if @product.update && @product.is_the_last_one
       redirect_to :your_choosen_root
    elsif @product.update 
       redirect_to edit_product_path(@product.next)
    else
       render :edit
    end
end

, , , .

( 22:55):)

+1

Source: https://habr.com/ru/post/1695274/


All Articles