2012-07-06 48 views
0

在stackoverflow上的第一篇文章,事先道歉,任何類似noob的。功能測試不適用於嵌套參數

我在一次功能測試中遇到了一個錯誤,幾個小時後,我似乎無法弄清楚如何通過它。

總之,一個invoice_schedule其中has_manyinvoice_milestones。然後,invoice_milestones有一個屬性,estimate_percentage(一個整數)。我的型號models/invoice_schedule.rb有一個驗證,要求所有的estimate_percentages之和必須等於100.

invoice_schedule創建操作的功能測試每次都失敗。用我現在的代碼下面,它已經錯誤了。我看不出它會如何誤傳我傳遞的參數。

我還會注意到estimate has_one :invoice_schedule

任何幫助或建議表示讚賞:)

型號/ invoice_schedule.rb:

class InvoiceSchedule < ActiveRecord::Base 
    belongs_to :estimate 
    has_many :invoice_milestones, :dependent => :destroy 

    accepts_nested_attributes_for :invoice_milestones, :allow_destroy => true 

    validate :total_must_equal_one_hundred_percent 

    def total_must_equal_one_hundred_percent 
     if total_percent != 100 
      errors.add(:invoice_milestones, "Total must equal 100%") 
     end 
    end 

    def total_percent 
     invoice_milestones.to_a.sum { |item| item.estimate_percentage || 0 } 
    end 
end 

型號/ invoice_milestone.rb:

class InvoiceMilestone < ActiveRecord::Base 
    belongs_to :invoice_schedule 
    belongs_to :invoice 

    validates :estimate_percentage, :numericality => {:only_integer => true, :greater_than_or_equal_to => 0, :less_than_or_equal_to => 100} 
end 

controllers/invoice_schedules_controller.rb

def create 
    @invoice_schedule = InvoiceSchedule.new(params[:invoice_schedule]) 
    @estimate = Estimate.find_by_id(params[:estimate_id]) 

    respond_to do |format| 
     if @invoice_schedule.save 
     format.html { redirect_to invoice_schedule_path(@invoice_schedule), :flash => {:notice => 'Invoice schedule was successfully created.', :status => 'success'} } 
     format.json { render json: @invoice_schedule, status: :created, location: @invoice_schedule } 
     else 
     format.html { render action: "new" } 
     format.json { render json: @invoice_schedule.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

測試/功能/ invoice_schedules_controller_test.rb

setup do 
    @account = accounts(:lorem) 
    @estimate = estimates(:lorem_one) 
    @user = users(:lorem_vendor) 
    @request.host = "#{@account.subdomain}.myapp.local" 
    session[:user_id] = @user.id 
    @invoice_schedule = invoice_schedules(:lorem_one) 
    @invoice_milestone = invoice_milestones(:lorem_one) 
    @data_estimate = estimates(:lorem_two) 
    @data_invoice_schedule = @invoice_schedule.attributes.merge({estimate_id: @data_estimate.id}) 
    end 

    test "should create invoice_schedule" do 
    assert_difference('InvoiceSchedule.count') do 
     post :create, :invoice_schedule => { estimate_id: @data_estimate, :invoice_milestone => {estimate_percentage: 100}} 
    end 

    assert_redirected_to estimate_invoice_schedule_path(@estimate, assigns(:invoice_schedule)) 
    end 

的config/routes.rb中

require 'subdomain' 

    Accountimize::Application.routes.draw do 

     resources :invoices do 
     member do 
      get 'generateInvoiceFromMilestone' 
     end 
     end 

     resources :users 
     resources :sessions 

     get "sign_up" => "accounts#new", :as => "sign_up" 

     resources :accounts 

     resources :clients do 
     get :client_address, on: :member 
     end 

     resources :estimates do 
     resources :invoice_schedules, :shallow => true 
     end 

     resources :line_items 

     constraints(Subdomain) do 
     match '/' => 'accounts#show' 
     get "log_in" => "sessions#new", :as => "log_in" 
     get "log_out" => "sessions#destroy", :as => "log_out" 
     get "register" => "users#new", :as => "register" 
     end 
     root :to => 'site#index', :as => 'site' 
    end 

錯誤的痕跡,我得到:

InvoiceSchedulesControllerTest 
    test_should_create_invoice_schedule         ERROR 
     No route matches {:invoice_schedule=>{:estimate_id=>"706507935", :invoice_milestones_attributes=>{"0"=>{:description=>"test", :estimate_percentage=>"100"}}}, :controller=>"invoice_schedules", :action=>"create"} 
     STDERR: 
     Exception `ActionController::RoutingError' at /Users/Matt/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/actionpack-3.1.1/lib/action_dispatch/routing/route_set.rb:465:in `raise_routing_error' 
     /Users/Matt/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/actionpack-3.1.1/lib/action_dispatch/routing/route_set.rb:461:in `rescue in generate' 
     /Users/Matt/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/actionpack-3.1.1/lib/action_dispatch/routing/route_set.rb:453:in `generate' 
     /Users/Matt/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/actionpack-3.1.1/lib/action_dispatch/routing/route_set.rb:494:in `generate' 
     /Users/Matt/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/actionpack-3.1.1/lib/action_dispatch/routing/route_set.rb:490:in `generate_extras' 
     /Users/Matt/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/actionpack-3.1.1/lib/action_dispatch/routing/route_set.rb:486:in `extra_keys' 
     /Users/Matt/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/actionpack-3.1.1/lib/action_controller/test_case.rb:145:in `assign_parameters' 
     /Users/Matt/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/actionpack-3.1.1/lib/action_controller/test_case.rb:438:in `process' 
     /Users/Matt/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/actionpack-3.1.1/lib/action_controller/test_case.rb:49:in `process' 
     /Users/Matt/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/actionpack-3.1.1/lib/action_controller/test_case.rb:370:in `post' 
     test/functional/invoice_schedules_controller_test.rb:35:in `block (2 levels) in <class:InvoiceSchedulesControllerTest>' 
     /Users/Matt/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/activesupport-3.1.1/lib/active_support/testing/assertions.rb:55:in `assert_difference' 
     test/functional/invoice_schedules_controller_test.rb:30:in `block in <class:InvoiceSchedulesControllerTest>' 
     /Users/Matt/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/activesupport-3.1.1/lib/active_support/testing/setup_and_teardown.rb:35:in `block in run' 
     /Users/Matt/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/activesupport-3.1.1/lib/active_support/callbacks.rb:444:in `_run_setup_callbacks' 
     /Users/Matt/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/activesupport-3.1.1/lib/active_support/callbacks.rb:81:in `run_callbacks' 
     /Users/Matt/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/activesupport-3.1.1/lib/active_support/testing/setup_and_teardown.rb:34:in `run' 

我我嘗試了很多其他方法來完成添加invo ice_milestone添加到功能測試中新創建的invoice_schedule中,但似乎沒有任何工作適用於我。如果添加了accept_nested_attributes_for,爲什麼會收到上述路由錯誤?

回答

3

這有兩個部分。首先你需要獲得路由方面的權利。因爲你嵌套的發票排程內估計需要在頂層(未裏面params[:invoice_schedules])提供的estimate_id,即

post :create, :estimate_id => @data_estimate.id, :invoice_schedule => {...} 

的期望是那麼您控制器並沿

estimate = Estimate.find(params[:estimate_id]) 
@invoice_schedule = estimate.invoice_schedules.build params[:invoice_schedule] 
東西線

第二部分是關於嵌套屬性 - 你需要提供一個符合Rails期望的參數。第一部分是散列中的密鑰應該是:invoice_milestones_attributes。由於這是一個has_many,相應的值需要 是散列的陣列,或者散列的散列(按鍵被忽略 - 這是因爲在一個軌道參數傳遞數組和散列之間的相互作用主要是存在的),例如

post :create, :estimate_id => @data_estimate.id, 
       :invoice_schedule => { 
       :invoice_milestones_attributes => [ 
        {:estimate_percentage => 100} 
       ] 
       } 
+0

非常感謝!但是,我的測試,現在失敗,我用於測試下面一行: 後:創建:estimate_id => @ data_estimate.id,:invoice_schedules => {:invoice_milestones_attributes => {0 => {estimate_percentage:100 }}} 測試失敗,因爲total_must_equal_one_hundred_percent驗證。評論它使測試通過。 然而,去除此驗證和添加驗證,以確保一個invoice_schedule具有至少一個invoice_milestone使測試失敗,這表明invoice_milestone屬性不創建新invoice_milestone。 – mmontaruli 2012-07-09 00:47:41

+0

你可以在那裏堅持一個斷點,看看什麼是真正發生的事情,而不是試圖推斷它 – 2012-07-09 06:22:57

+0

這有助於追根溯源。非常感謝您的幫助! – mmontaruli 2012-07-09 19:27:40