Moosa
Moosa

Reputation: 3216

Rails - Updating records using Best in Place

I'm building a marketplace app where I'm trying to use the Best in Place gem to allow sellers to add a tracking number for each of their orders.

I get a NoMethodError which I'm not able to resolve.

NoMethodError in Orders#sales
undefined method `tracking' for nil:NilClass

The error points to the best in place line below in the view page. This view page is based on the method Sales (in the controller below) where I filter for orders for that particular seller.

Here is my routes.rb with order routing. Since orders need not be edited or destroyed, I didn't create an edit or delete route.

  resources :listings do
     resources :orders, only: [:new, :create, :update]
     collection { post :import }
  end

Here is a snippet from my orders controller

class OrdersController < ApplicationController
  before_action :set_order, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_user! 
  before_action :check_user, only: [:edit, :update]

def sales
  @orders = Order.all.where(seller: current_user).order("created_at DESC")
end

def update
   @order.update_attributes(params[:order])
end

def check_user
  if current_user.id != @seller && current_user.name != "admin admin"
    redirect_to root_url, alert: "Sorry, you are not the seller of this listing"
  end
end

Here is my view page:

<table class="table table-striped table-bordered">
  <tr>
    <th class="col-md-2">Image</th>
    <th class="col-md-2">Item</th>
    <th class="col-md-1">Price</th>
    <th class="col-md-2">Customer</th>
    <th class="col-md-2">Date Sold</th>
    <th class="col-md-2">Shipment Tracking #</th>
    <th class="col-md-1">Carrier (UPS, USPS, etc.)</th>
 </tr>

<% @orders.each do |order| %>
   <tr>
    <td><%= image_tag order.listing.image.url(:thumb) %></td>
    <td><%= order.listing.name %></td>
    <td><%= number_to_currency(order.listing.price) %></td>
    <td><%= order.buyer.name %></td>
    <td><%= order.created_at.strftime("%B %-d, %Y") %></td>
    <td><%= best_in_place @order, :tracking, :type => :input %> </td>
    <td><%= best_in_place @order, :carrier, :type => :input %></td>
  </tr>
 <% end %>
</table>

Been stuck on this for a while. Appreciate any help on this.

Upvotes: 1

Views: 761

Answers (2)

Moosa
Moosa

Reputation: 3216

I figured it out. The problem was that since I was using best_in_place in a non-Activerecord environment (as part of a table with a list of orders), I needed to pass the order id explicitly. I found this in the best_in_place documentation https://github.com/bernat/best_in_place#non-active-record-environments

I created a custom route for the update action

put 'orderupdate' => "orders#update"

Then in my do loop in the view, I used the custom path for the route above and passed the order id to that route.

  <% @orders.each do |order| %>
<tr>
  <td><%= order.id %></td>
  <td><%= image_tag order.listing.image.url(:thumb) %></td>
  <td><%= order.listing.name %></td>
  <td><%= number_to_currency(order.listing.price) %></td>
  <td><%= order.buyer.name %></td>
  <td><%= order.created_at.strftime("%B %-d, %Y") %></td>
  <td><%= best_in_place order, :tracking, :type => :input, :url => orderupdate_path(id: order.id) %> </td>
  <td><%= best_in_place order, :carrier, :type => :input, :url => orderupdate_path(id: order.id) %> </td>
</tr>
<% end %>

Here is the update method in my controller:

  def update
    @order = Order.find(params[:id])
    respond_to do |format|
       if @order.update(order_params)
         format.html { redirect_to sales_url, notice: 'Order updated.' }
         format.json { head :no_content }
       else
         format.html { render action: 'edit' }
         format.json { render json: @order.errors, status: :unprocessable_entity }
      end
    end
  end

Hope this helps someone!

Upvotes: 1

cadair
cadair

Reputation: 96

I think the problem is that you are calling @order inside your .each method.

Try:

<%= best in place order, :tracking, :type => :input %>

You will need to change the next line in your view as well.

Upvotes: 2

Related Questions