Edgar
Edgar

Reputation: 503

Saving two different models in same controller action

I am posting to my OrdersController#create action and in that I'm trying to do two things: save an Account and an Order. The Order is being saved, but the Account is not and I don't know why not.

OrdersController

class OrdersController < ApplicationController
  before_filter :authenticate_user!
  include CurrentCart
  before_action :set_cart, only: [:new, :create]
  before_action :set_order, only: [:show, :edit, :update, :destroy]

  # other actions removed

  def create
    @order = Order.new(order_params)
    @order.add_line_items_from_cart(@cart)
    @order.email = current_user.email
    @order.address = current_user.address
    #@order.created at = @line_items.created_at
    @account = Account.where(user_id:current_user.id)
    @previous_balance = Account.previous_balance_for_user(current_user)
    @account = Account.new(
      user_id: current_user.id,
      email: current_user.email,
      debit: @cart.total_price,
      acctbal: @previous_balance - @cart.total_price
    )
    @account.save
    respond_to do |format|

      if @order.save
        Cart.destroy(session[:cart_id])
        session[:cart_id] = nil

        format.html { redirect_to store_url, notice: 'Thank you for your 
              order.' }
        format.json { render :show, status: :created, location: @order }
      else
        format.html { render :new }
        format.json { render json: @order.errors, status: 
                      :unprocessable_entity }
      end
    end
  end

  private
    def set_order
      @order = Order.find(params[:id])
    end

    def order_params
      params.require(:order).permit(:name, :address, :email, :pay_type, 
                                    :datefor)
    end
end 

Account

class Account < ActiveRecord::Base
  belongs_to :users
  belongs_to :order
  validates :depotype, :credit, presence: true
  DEPOSIT_TYPES = [ "Check", "Credit card", "Purchase order" ]
  validates :depotype, inclusion: DEPOSIT_TYPES

  def self.previous_balance_for_user(user)
    where(user_id: user.id).order(:created_at).pluck(:acctbal).last || 0.0
  end
end

Relevant log section

Started POST "/orders" for 127.0.0.1 at 2015-04-28 21:54:52 -0400
Processing by OrdersController#create as HTML
Parameters: {"utf8"=>"√",     
 "authenticity_token"=>"jYKMts1Zwgl4a0Y+ud86J3mAh0rGHuDqW0rUqSm45NQ=", 
"order"=>{"name"=>"dddd"}, "commit"=>"Place Order"}
 User Load (1.0ms)  SELECT  "users".* FROM "users"  WHERE "users"."id" = 1  
ORDER BY "users"."id" ASC LIMIT 1
Cart Load (0.0ms)  SELECT  "carts".* FROM "carts"  WHERE "carts"."id" = ?
 LIMIT 1  [["id", 3]]
 LineItem Load (0.0ms)  SELECT "line_items".* FROM "line_items"  WHERE  
"line_items"."cart_id" = ?  [["cart_id", 3]]
 (0.0ms)  SELECT "accounts"."acctbal" FROM "accounts"  WHERE  
"accounts"."user_id" = 1  ORDER BY "accounts"."created_at" ASC
Menu Load (0.0ms)  SELECT  "menus".* FROM "menus"  WHERE "menus"."id" = ?  
 LIMIT 1  [["id", 1]]
(0.0ms)  begin transaction
(0.0ms)  rollback transaction
(0.0ms)  begin transaction
 SQL (0.0ms)  INSERT INTO "orders" ("address", "created_at", "email",  
 "name", "updated_at") VALUES (?, ?, ?, ?, ?)  [["address", "3494 dsfsdf dr.
  valdosta, GA 31504"], ["created_at", "2015-04-29 01:54:52.414099"],
 ["email", "[email protected]"], ["name", "dddd"], ["updated_at", "2015-04-
  29 01:54:52.414099"]]
 SQL (1.0ms)  UPDATE "line_items" SET "cart_id" = ?, "order_id" = ?,  
 "updated_at" = ? WHERE "line_items"."id" = 3  [["cart_id", nil], 
 ["order_id", 3], ["updated_at", "2015-04-29 01:54:52.417100"]]
(93.0ms)  commit transaction
Cart Load (0.0ms)  SELECT  "carts".* FROM "carts"  WHERE "carts"."id" = ? 
LIMIT 1  [["id", 3]]
(0.0ms)  begin transaction
LineItem Load (0.0ms)  SELECT "line_items".* FROM "line_items"  WHERE
"line_items"."cart_id" = ?  [["cart_id", 3]]
SQL (0.0ms)  DELETE FROM "carts" WHERE "carts"."id" = ?  [["id", 3]]
(83.0ms)  commit transaction
 Redirected to http://localhost:3000/
 Completed 302 Found in 238ms (ActiveRecord: 178.0ms)


 Started GET "/" for 127.0.0.1 at 2015-04-28 21:54:52 -0400
 Processing by StoreController#index as HTML
(0.0ms)  begin transaction
 SQL (1.0ms)  INSERT INTO "carts" ("created_at", "updated_at") VALUES (?, ?)  
 [["created_at", "2015-04-29 01:54:52.632112"], ["updated_at", "2015-04-
 29 01:54:52.632112"]]
(76.0ms)  commit transaction
 Rendered store/index.html.erb within layouts/application (5.0ms)
 User Load (0.0ms)  SELECT  "users".* FROM "users"  WHERE "users"."id" = 1  
 ORDER BY "users"."id" ASC LIMIT 1
 Completed 200 OK in 1109ms (Views: 1028.1ms | ActiveRecord: 77.0ms)

What am I doing wrong here?

Upvotes: 1

Views: 327

Answers (1)

smathy
smathy

Reputation: 27961

Very obviously your @account.save is failing because of a validation error. Your validations in Account are:

validates :depotype, :credit, presence: true
validates :depotype, inclusion: DEPOSIT_TYPES

...and yet you don't provide either :depotype nor :credit in your controller code.

The big mistake here though is that you don't check the return from @account.save in your controller code, if it returns false (which I'm sure it is) then your code ignores that and proceeds as if nothing is wrong.

You should almost always check the return when .saveing a model.

Another option, especially when you're providing all the data for the model in your code (ie. you're not getting that data from the user), is to use the .save! method (with the !) which will raise an exception if there's a validation error. Then you can correct that.

Upvotes: 1

Related Questions