【问题标题】:How to feed rows from one model to another?如何将行从一个模型馈送到另一个模型?
【发布时间】:2015-04-07 15:40:11
【问题描述】:

我有 4 个表格:proposal、proposal_line_items(proposal_line_items 嵌套在提案中)invoice 和 invoice_line_items。

当客户批准每个项目时,我正在尝试将在 proposal_line_items 表中创建的行输入发票。我在proposal_line_items 中使用一个复选框(1 => 批准)来确定它是否被批准。

这就是我设置发票控制器以使发票接收来自 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)

【问题讨论】:

  • 这里的问题是您与请求一起发送的proposal_id 无效。您是否验证了Proposal 确实存在,或者您没有弄乱路线?
  • 我删除了所有提案并创建了一个新提案,看看它是否修复了错误。没运气。另外我在哪里可以检查我是否搞砸了路线?我在 rails c 中尝试了 p = Proposal.last + p.proposal_line_items.where(:approved => 1) 并得到了结果。为什么这不起作用?
  • 我已经修改了路线(见上文),但找不到罪魁祸首。感谢您的帮助!
  • 看起来您的路线格式正确,但根据返回的错误,它的值似乎是nil。尝试在您的控制器中执行此操作,看看会发生什么:@approved_items = Proposal.find(params.require(:proposal_id])).proposal_line_items.where(:approved =&gt; 1)。我怀疑它会引发一个错误,指出未提供所需的参数。
  • 现在由于建议的更改,我得到了这个结果:InvoicesController#new 私有方法 `require' 中的 NoMethodError 调用了 #<0x007f8bbfa59a40>

标签: ruby-on-rails ruby activerecord models


【解决方案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 =&gt; false})

您正在为您的表单生成ProposalLineItems 的集合,但在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

但是,考虑到表单的上下文以及控制器尝试执行的操作,呈现Proposals 的集合而不是ProposalLineItems 可能更有意义。也许是这样的:

# 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"

【讨论】:

  • Eugene,对不起,我仍然收到选项 1 的错误:缺少参数或值为空:proposal_line_item 和选项 2:缺少参数或值为空:proposal
  • 您能否粘贴一些来自您提交表单时发送的请求的日志输出?
  • 我正在使用 proposal_proposal_id_invoices_new GET /proposal/proposal_id/invoices/new(.:format) proposal/proposal_id/invoices#new 作为“新发票”的 link_to 并添加到我的路线文件 get "/ proposal/proposal_id/invoices/new”,但现在当我进入 Invoices 的索引视图时,出现此错误:Invoices#index Showing /Users/davefogo/Sites/ideapp/app/views/invoices/index.html 中的 NameError。 erb where line #27 raise: undefined local variable or method `proposal_proposal_id_invoices_new' for #:0x007f7f5c666970>
猜你喜欢
  • 2023-03-09
  • 2020-11-25
  • 2020-06-15
  • 2021-12-13
  • 1970-01-01
  • 2019-09-28
  • 1970-01-01
  • 2011-08-11
  • 1970-01-01
相关资源
最近更新 更多