Search code examples
ruby-on-railsarraysvalidationnomethoderror

Rails ArgumentError in OrdersController#new validation


Second question on here, I'd really like to solve this one myself but I just don't know where to start to debug it.

So here is my error in the browser (which occurs when I go to check out and enter my details in order/_form.html.erb)

ArgumentError in OrdersController#new

You need to supply at least one validation

Rails.root: C:/Users/Ruby/rails_practice/depot4 Application Trace | Framework Trace | Full Trace

app/models/payment_type.rb:6:in <class:PaymentType>' app/models/payment_type.rb:1:in' app/models/order.rb:7:in <class:Order>' app/models/order.rb:1:in' app/controllers/orders_controller.rb:1:in `'

And here is my def new in OrdersController:

def new
  @cart = current_cart
  if @cart.line_items.empty?
    redirect_to store_url, :notice => "Your cart is empty"
    return
  end

  @hide_checkout_button = true
  @order = Order.new

  respond_to do |format|
    format.html # new.html.erb
    format.json { render json: @order }
  end
end

The thing is that I haven't touch def new, I've been working on def create, which is here:

def create
  @order = Order.new(params[:order])
  @order.add_line_items_from_cart(current_cart)
  @cart = current_cart
  @hide_checkout_button = true
  pay_type = PaymentType.find( :conditions => ['pay_type = ?', @order.pay_type] )
  @order.payment_type_id = pay_type.id

  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 json: @order, status: :created, location: @order }
    else
      format.html { render action: "new" }
      format.json { render json: @order.errors, status: :unprocessable_entity }
    end
  end
end

What I am trying to do there is create an order which is which belongs_to a payment_type and has_many line_items which belongs_to a cart.

Incidentally, I am also trying to hide_checkout_button with an instance variable when I am on the order page.

The Orders table has a foreign key to the PaymentTypes table and I am trying to find the correct id from this PaymentTypes table for the payment_type submitted by the user.

If I comment out these two lines:

pay_type = PaymentType.find( :conditions => ['pay_type = ?', @order.pay_type] )
@order.payment_type_id = pay_type.id

Sometimes I get a different error:

NoMethodError in OrdersController#new

undefined method `key?' for nil:NilClass

I think this is to do with incorrect caching in the browser but I'm not sure what the connection is.

I will update with the rest after I post this first


Part deux

I know that this is about validation, but I can't see what I am doing wrong... order.rb:

class Order < ActiveRecord::Base
  attr_accessible :address, :email, :name, :pay_type, :payment_type_id, :cart_id, 
  :product_id

  has_many :line_items, :dependent => :destroy
  belongs_to :payment_type

  PAYMENT_TYPES = PaymentType.pluck(:pay_type)

  validates :name, :address, :email, :pay_type, :presence => true
  validates :pay_type, :inclusion => PAYMENT_TYPES

And then you've got the other side of that belongs_to in payment_type.rb

class PaymentType < ActiveRecord::Base
  attr_accessible :pay_type

  has_many :orders

  validates ***:pay_type,*** :uniqueness
end

I know that I am totally just confusing things but I have one fail in the functionals tests and one error that has something to do with updating an order but I don't know what yet. I am going to work on them to see if by solving them I inadvertently solve this weird error.

If anyone can give me tips on hacking and debugging in rails that would be great. I would love to be able to solve this without typing all of this in here.

I don't think the server trace gives any more information than the browser window in this case but if you need it, or anything else please ask.

UPDATE:

So my problem is that I know how to solve it with a global variable in payment_type.rb, but this means that I have one column of payment types in the Orders table and another of names and payment_type_ids in another column, which is the foreign key.

Since I have the foreign key I shouldn't need a specific column for payment_types in the Orders table. I should just be able to see the value from the PaymentType table in the Orders view.

How do you do this without a Global variable?

UPDATE deux:

Ok, so I never posted this before (from orders_form.html.erb):

26:   <div class="field">
27:     <%= f.label :pay_type %><br />
28:     <%= f.select :pay_type, PaymentType::PAYMENT_TYPES,
29:                      :prompt => 'Select a payment method' %>
30:   </div>
31:   <div class="actions">

So I've tried to select for :pay_type in Orders but given options from :pay_type in PaymentTypes.

I can't imagine that matters does it? Seems to be where my problem lies, but can't be sure.


Solution

  • I think the syntax of your validate inclusion of is wrong. It should be something like:

    validates :pay_type, :inclusion => { :in => PAYMENT_TYPES }