我有4个表:提案,proposal_line_items(proposal_line_items嵌套在提案中)发票和invoice_line_items。
我正在尝试在客户审批每个项目时将在proposal_line_items表中创建的行提供给发票。我在proposal_line_items中使用了一个复选框(1 => approved)来确定它是否已获批准。
这是我设置发票控制器以使发票从proposal_line_items接收行的方式。
class InvoicesController < ActionController
def new
@approved_items = Proposal.find(params[:proposal_id]).proposal_line_items.where(:approved => 1)
end
end
当我尝试创建新发票时,我收到以下错误:
ActiveRecord::RecordNotFound in InvoicesController#new Couldn't find Proposal with 'id'= Extracted source (around line #17): 15 16 17 18 19 20
控制器操作:
# GET /invoices/new
def new
@approved Proposal.find(params[:proposal_id]).proposal_line_items.where(:approved => 1)
end
你能帮我解决这个问题吗?谢谢!
型号:
class Proposal < ActiveRecord::Base
has_many :proposal_line_items
end
class ProposalLineItem < ActiveRecord::Base
belongs_to :proposal
end
class Invoice < ActiveRecord::Base
has_many :invoice_line_items
end
class InvoiceLineItem < ActiveRecord::Base
belongs_to :invoice
end
迁移文件:
class CreateProposalLineItems < ActiveRecord::Migration
def change
create_table :proposal_line_items do |t|
t.references :proposal, index: true, foreign_key: true
t.string :name
t.integer :approved
t.timestamps null: false
end
end
end
class CreateProposals < ActiveRecord::Migration
def change
create_table :proposals do |t|
t.string :name
t.timestamps null: false
end
end
end
class CreateInvoiceLineItems < ActiveRecord::Migration
def change
create_table :invoice_line_items do |t|
t.references :invoice, index: true, foreign_key: true
t.string :name
t.integer :approved
t.timestamps null: false
end
end
end
class CreateInvoices < ActiveRecord::Migration
def change
create_table :invoices do |t|
t.string :name
t.timestamps null: false
end
end
end
的routes.rb
invoices GET /invoices(.:format) invoices#index POST /invoices(.:format) invoices#create
new_invoice GET /invoices/new(.:format) invoices#new
edit_invoice GET /invoices/:id/edit(.:format) invoices#edit
invoice GET /invoices/:id(.:format) invoices#show
PATCH /invoices/:id(.:format) invoices#update
PUT /invoices/:id(.:format) invoices#update
DELETE /invoices/:id(.:format) invoices#destroy`
proposal_proposal_line_items POST /proposals/:proposal_id/proposal_line_items(.:format) proposals/proposal_line_items#create
new_proposal_proposal_line_item GET /proposals/:proposal_id/proposal_line_items/new(.:format) proposals/proposal_line_items#new
edit_proposal_proposal_line_item GET /proposals/:proposal_id/proposal_line_items/:id/edit(.:format) proposals/proposal_line_items#edit
proposal_proposal_line_item GET /proposals/:proposal_id/proposal_line_items/:id(.:format) proposals/proposal_line_items#show
PATCH /proposals/:proposal_id/proposal_line_items/:id(.:format) proposals/proposal_line_items#update
PUT /proposals/:proposal_id/proposal_line_items/:id(.:format) proposals/proposal_line_items#update
DELETE /proposals/:proposal_id/proposal_line_items/:id(.:format) proposals/proposal_line_items#destroy
proposals GET /proposals(.:format) proposals#index
POST /proposals(.:format) proposals#create
new_proposal GET /proposals/new(.:format) proposals#new
edit_proposal GET /proposals/:id/edit(.:format) proposals#edit
proposal GET /proposals/:id(.:format) proposals#show
PATCH /proposals/:id(.:format) proposals#update
PUT /proposals/:id(.:format) proposals#update
DELETE /proposals/:id(.:format) proposals#destroy
更新
控制器
class InvoicesController < ApplicationController
before_action :set_invoice, only: [:show, :edit, :update, :destroy]
# GET /invoices
# GET /invoices.json
def index
@invoices = Invoice.all
end
# GET /invoices/1
# GET /invoices/1.json
def show
end
# GET /invoices/new
def new
@approved = Proposal.require(:proposal_id).proposal_line_items.where(:approved => 1)
end
# GET /invoices/1/edit
def edit
end
# POST /invoices
# POST /invoices.json
def create
@invoice = Invoice.new(invoice_params)
respond_to do |format|
if @invoice.save
format.html { redirect_to @invoice, notice: 'Invoice was successfully created.' }
format.json { render :show, status: :created, location: @invoice }
else
format.html { render :new }
format.json { render json: @invoice.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /invoices/1
# PATCH/PUT /invoices/1.json
def update
respond_to do |format|
if @invoice.update(invoice_params)
format.html { redirect_to @invoice, notice: 'Invoice was successfully updated.' }
format.json { render :show, status: :ok, location: @invoice }
else
format.html { render :edit }
format.json { render json: @invoice.errors, status: :unprocessable_entity }
end
end
end
# DELETE /invoices/1
# DELETE /invoices/1.json
def destroy
@invoice.destroy
respond_to do |format|
format.html { redirect_to invoices_url, notice: 'Invoice was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_invoice
@invoice = Invoice.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def invoice_params
params.require(:invoice).permit(:date, :proposal_line_item_id)
end
end
更新
新
<h1>New Invoice</h1>
<%= render 'form' %>
<%= link_to 'Back', invoices_path %>
表格
%= form_for(@invoice) do |f| %>
<% if @invoice.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@invoice.errors.count, "error") %> prohibited this invoice from being saved:</h2>
<ul>
<% @invoice.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :date %><br>
<%= f.datetime_select :date %>
</div>
<div class="field">
<%= f.label :proposal_line_item %><br>
<%= collection_select( :proposal_line_item, :proposal_line_item_id, Proposal_line_item.all, :id, :date, {}, {:multiple => false}) %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
日志输出
Started GET "/invoices/new" for ::1 at 2015-04-09 12:48:00 -0500
Processing by InvoicesController#new as HTML
Completed 400 Bad Request in 1ms
ActionController::ParameterMissing (param is missing or the value is empty: proposal_line_item):
app/controllers/invoices_controller.rb:23:in `proposal_line_item'
app/controllers/invoices_controller.rb:17:in `new'
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/actionpack-4.2.0/lib/action_dispatch/middleware/templates/rescues/_source.erb (4.6ms)
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/actionpack-4.2.0/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (1.8ms)
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/actionpack-4.2.0/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (0.6ms)
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/actionpack-4.2.0/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (16.6ms)
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/web-console-2.1.0/lib/web_console/templates/_markup.html (0.2ms)
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/web-console-2.1.0/lib/web_console/templates/style.css within layouts/inlined_string (0.2ms)
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/web-console-2.1.0/lib/web_console/templates/_inner_console_markup.html within layouts/inlined_string (0.2ms)
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/web-console-2.1.0/lib/web_console/templates/_prompt_box_markup.html within layouts/inlined_string (0.2ms)
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/web-console-2.1.0/lib/web_console/templates/console.js within layouts/javascript (11.0ms)
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/web-console-2.1.0/lib/web_console/templates/main.js within layouts/javascript (0.3ms)
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/web-console-2.1.0/lib/web_console/templates/error_page.js within layouts/javascript (0.5ms)
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/web-console-2.1.0/lib/web_console/templates/index.html (24.2ms)
Started GET "/invoices/new" for ::1 at 2015-04-09 12:48:00 -0500
Processing by InvoicesController#new as HTML
Completed 400 Bad Request in 1ms
ActionController::ParameterMissing (param is missing or the value is empty: proposal_line_item):
app/controllers/invoices_controller.rb:23:in `proposal_line_item'
app/controllers/invoices_controller.rb:17:in `new'
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/actionpack-4.2.0/lib/action_dispatch/middleware/templates/rescues/_source.erb (4.5ms)
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/actionpack-4.2.0/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (1.8ms)
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/actionpack-4.2.0/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (0.6ms)
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/actionpack-4.2.0/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (25.6ms)
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/web-console-2.1.0/lib/web_console/templates/_markup.html (0.2ms)
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/web-console-2.1.0/lib/web_console/templates/style.css within layouts/inlined_string (0.2ms)
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/web-console-2.1.0/lib/web_console/templates/_inner_console_markup.html within layouts/inlined_string (0.2ms)
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/web-console-2.1.0/lib/web_console/templates/_prompt_box_markup.html within layouts/inlined_string (0.2ms)
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/web-console-2.1.0/lib/web_console/templates/console.js within layouts/javascript (11.0ms)
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/web-console-2.1.0/lib/web_console/templates/main.js within layouts/javascript (0.2ms)
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/web-console-2.1.0/lib/web_console/templates/error_page.js within layouts/javascript (0.3ms)
Rendered /Users/davefogo/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/web-console-2.1.0/lib/web_console/templates/index.html (23.8ms)
答案 0 :(得分:1)
这里的问题是您正在向没有参数的路线发出请求。我错误地认为您在提交表单时看到此错误,在呈现表单时您会看到此错误。我建议将路由从/invoices/new
更新为/proposal/:proposal_id/invoices/new
行,然后将其用于控制器方法:
class InvoicesController < ActionController
def new
@approved_items = Proposal.find(params.require(:proposal_id)).proposal_line_items.where(:approved => 1)
end
end
然后,在我建议修改之前,您可以使用原始视图。
此行以下的所有内容均为错误
此处的问题是您尝试查询Proposal
,但您实际从表单传入控制器的项目是ProposalLineItem
在表格的这一行:
collection_select( :proposal_line_item, :proposal_line_item_id, Proposal_line_item.all, :id, :date, {}, {:multiple => false})
您正在为表单生成ProposalLineItem
个集合,但在Proposal_line_item
而不是ProposalLineItem
要查询控制器中的Proposal
,您需要执行以下两项操作之一。
选项1
将您的控制器更新为:
class InvoicesController < ActionController
def new
@approved_items = proposal ? proposal.proposal_line_items.where(approved: 1) : []
end
protected
def proposal_line_item
# The way you have your form configured, the params hash will look like this: {"proposal_line_item" => {"proposal_line_item_id" => "some_id"}}
@_proposal_line_item = ProposalLineItem.find(params.require(:proposal_line_item).require(:proposal_line_item_id))
end
def proposal
proposal_line_item.proposal
end
end
选项2
但是考虑到表单的上下文以及控制器尝试执行的操作,渲染Proposal
s而不是ProposalLineItem
s的集合可能更有意义。也许是这样的:
# in your form
collection_select( :proposal, :proposal_id, Proposal.all, :id, :name, {}, {:multiple => false})
然后在你的控制器中:
class InvoicesController < ActionController
def new
@approved_items = proposal.proposal_line_items.where(approved: 1)
end
protected
def proposal
Proposal.find(params.require(:proposal).require(:proposal_id))
end
end
显然选择权在这里,但考虑到你想做的事情,我会倾向于选择2。
另外,仅供参考,如果您想在rails控制台中测试参数内容,您需要这样做:
> params = ActionController::Parameters.new
=> {}
> params[:proposal_line_item] = {}
=> {}
> params[:proposal_line_item][:proposal_line_item_id] = "asdf"
=> "asdf"
> params.require(:proposal_line_item)
=> {"proposal_line_item_id"=>"asdf"}
> params.require(:proposal_line_item).require(:proposal_line_item_id)
=> "asdf"