问题
I have an Order model.
Customers get a handful of consumer-friendly views that let them create and view their own orders, all backed by an Orders controller.
Admins get the full range of views to create, edit, view, delete and manage orders, backed by a Purchases controller.
As far as I can tell, the Purchases controller should only be speaking to the Order model, but the following error message makes me think it's looking for a non-existant Purchase model:
ActiveRecord::StatementInvalid in PurchasesController#new
NameError in PurchasesController#new
uninitialized constant Purchase
Rails.root: /Users/steven/Dropbox/testivate
Is that what the error means? If it does, how do I stop the Purchases controller from trying to find a Purchase model?
My code...
app/controllers/purchases_controller.rb:
class PurchasesController < ApplicationController
def new
@purchase = Order.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: @purchase }
end
end
def create
@purchase = Order.new(params[:purchase])
respond_to do |format|
if @purchase.save
format.html { redirect_to purchase_path(@purchase), notice: 'Purchase was successfully created.' }
format.json { render json: @purchase, status: :created, location: @purchase }
else
format.html { render action: "new" }
format.json { render json: @purchase.errors, status: :unprocessable_entity }
end
end
end
end
/config/routes.rb:
Testivate::Application.routes.draw do
resources :orders
resources :purchases
end
/app/views/purchases/new.html.haml:
.textbox
%p#notice= notice
%h1 New Purchase
= render 'form'
= link_to 'List Purchases', purchases_path
/app/views/purchases/_form.html.haml:
= simple_form_for @purchase do |f|
= f.error_notification
= f.input :name
= f.button :submit
Update: so I've just realised that 'transaction' is a reserved word in Rails so I've changed that. But is there anything else I need to fix?
*Update 2: When I completely comment out the #new view and the _form, I still get the error, so I think the problem is in my controller or routes or somewhere other than with my use of simple_form.*
回答1:
Update:
This is half of the answer. For the other half see the comments on the question.
Original answer:
Part of the problem here is that by default form_for
(which simple_form_for
is built atop) assumes certain things about what paths to use for a given record, which it derives from the class of that record. In your case, since @purchase
is actually an instance of the Order
class, those assumptions are going to screw things up for you.
If you look at the form generated by simple_form_for
, you'll see that it gives the form both an id and a class of new_order
, and that the fields in the form have names like order[name]
. To get rails to use purchase
instead of order
in the form, you have to pass it an :as
option.
From the docs for form_for:
If you have an object that needs to be represented as a different parameter, like a Person that acts as a Client:
And the example they give:
<%= form_for(@person, :as => :client) do |f| %>
...
<% end %>
In your case, you'd actually want to tell it to treat @purchase
like a "purchase":
= simple_form_for @purchase, :as => :purchase do |f|
= f.error_notification
= f.input :name
= f.button :submit
That will get the form ids, etc. right, so that you can use e.g. params[:purchase]
in your create action as you have above. But this is not enough, because the action (URL) for the form will still end up being /orders
. To change that, add an :url
option:
= simple_form_for @purchase, :as => :purchase, :url => purchases_path(@purchase) do |f|
= f.error_notification
= f.input :name
= f.button :submit
This will also solve the other question you posted.
来源:https://stackoverflow.com/questions/13676834/two-controllers-one-model-why-is-my-app-looking-for-a-second-model