【问题标题】:passing params to post :create request ruby-on-rails-3.1, Rspec, factory-girl将参数传递给 post :create request ruby​​-on-rails-3.1, Rspec, factory-girl
【发布时间】:2011-10-25 18:53:53
【问题描述】:

我正在尝试编写一个控制器规范,用于创建带有采购行项目的采购。使用我赋予它的所有属性,购买创建得很好,但未创建购买行项目。这是我的代码:

factories.rb

FactoryGirl.define do
  factory :purchase do |f| 
    f.sequence(:po_number) { |n| "0000-00#{n}" }
    f.sequence(:ship_to) { |n| "Test Corp#{n}"}
    f.sequence(:ship_via) {|n| "Test Delivery#{n}" }
    f.sequence(:terms) {|n| "My terms#{n}" }
    f.sequence(:qa_requirements) {|n| "Requirment#{n}" }
    f.sequence(:justification) {|n| "Justification#{n}" }
    f.become_part_of_delivered_product true
    f.immediately_delivered_to_stc_client false
    f.remain_for_contract_at_stc_as_gov_prop false
    f.consumed_in_job_requirements true
    f.used_in_repair_of_gov_prop false
    f.is_gov_prop_in_possession_of_stc false
    f.sequence(:required) {|n| "2011-10-0#{n}" }
    f.prd_number_id { |n| n.association(:prd_number).id }
    # f.order_for_id { |o| o.association(:user) }
    f.submitted_by_id { |s| s.association(:submitted_by).id }
    # f.ordered_for_date { Time.now.to_s }
    f.submitted_by_date { Time.now.to_s }
    f.quality_system_classification_id { |q| q.association(:quality_system_classification).id }
    f.after_create { |c| Factory(:purchase_line_item, purchase: c) }
  end

  factory :purchase_line_item do |f| 
    f.sequence(:item_description) {|n| "Desc#{n}" }
    f.unit_price "100.00"
    f.qty "40"
    f.sequence(:charge_number) {|n| "000-00#{n}" }
  end 
 end

PurchaseLineItem.rb

belongs_to :purchase
validates_presence_of :item_description,
                      :unit_price,
                      :qty,
                      :charge_number

Purchase.rb

  belongs_to :authorized_signers
  belongs_to :vendor
  belongs_to :purchase_type
  belongs_to :quality_system_classfication
  belongs_to :order_by, :class_name => "User", :foreign_key => "order_by_id"
  belongs_to :submitted_by, :class_name => "User", :foreign_key => "submitted_by_id"
  belongs_to :approved_by, :class_name => "User", :foreign_key => "approved_by_id"
  belongs_to :purchased_by, :class_name => "User", :foreign_key => "purchased_by_id"

  has_many :purchase_line_items
  has_many :audits

  accepts_nested_attributes_for :purchase_line_items, :allow_destroy => true

  validates_presence_of :required,
                        :ship_to,
                        :ship_via,
                        :terms,
                        :quality_system_classification_id,
                        :prd_number_id

采购总监

load_and_authorize_resource

def new
    @purchase = Purchase.new
    1.times { @purchase.purchase_line_items.build }
end

def create
  @purchase = Purchase.new(params[:purchase])
  @purchase.without_auditing do
    if @purchase.save
      flash[:notice] = "Successfully created purchase."
      redirect_to @purchase
    else
      render action: 'new'
    end
  end
end

PurchaseController 规范

require 'spec_helper'

describe PurchasesController do

  login_user

  describe "POST create" do
    before(:each) do
      @ability.can :create, Purchase
    end

    it "should pass the params to purchase" do
      purchase = Factory(:purchase)
      post :create, purchase: purchase.attributes.except("id")
      assigns(:purchase).po_number.should == purchase.po_number     
    end

    it "should pass the params to purchase_line_items" do
      purchase = Factory(:purchase)   
      post :create,   purchase: purchase.attributes, purchase_line_items_attributes: purchase.purchase_line_items.first.attributes 
      assigns(:purchase).purchase_line_items.first.unit_price.should == purchase.unit_price
    end
  end
end

提前致谢

【问题讨论】:

    标签: ruby-on-rails-3.1 rspec2 factory-bot


    【解决方案1】:

    在 Rails 4 下,这种通用性对我不起作用:

    post :create, purchase: { attributes: p, purchase_line_items_attributes: [pl] } 
    

    以下是我发现可以满足帖子的通用样式:create ...updated for Rails 4。注意:valid_session 可能无法完全按照我的存根工作,但你明白了 DRY 的想法;)

    describe PurchasesController do
      def valid_session
        controller.stub!(:authorize).and_return(User)
      end
    
      describe 'POST :create' do
        before do
          purchase = FactoryGirl.build(:purchase).attributes
          purchase_line_item = { purchase_line_items_attributes: { "#{rand(903814893)}" =>  FactoryGirl.build(:purchase_line_item).attributes } }
          @valid_attributes = purchase.merge(purchase_line_item)
        end
    
        context "with valid params" do
          before(:each) do
            post :create, { purchase: @valid_attributes }, valid_session
          end
    
          it "assigns a newly created purchase as @purchase" do
            assigns(:purchase).should be_a(Purchase)
          end
    
          it "saves a newly created purchase" do
            assigns(:purchase).should be_persisted
          end
    
          it "redirects to the created purchase" do
            response.should redirect_to(Purchase.last)
          end
    
        end
    
        context "with invalid params" do
          before do
            Purchase.any_instance.stub(:save).and_return(false)
            post :create, { purchase: @valid_attributes }, valid_session
          end
    
          it "assigns a newly created but unsaved purchase as @purchase" do
            assigns(:purchase).should be_a_new(Purchase)
          end
    
          it "re-renders the :new template" do
            response.should render_template("new")
          end
    
          it "returns http success" do
            response.should be_success
          end
    
        end
    
      end
    
    
    end
    

    在 Rails 4 中,如果您设置要使用的控制器:

    params.require(:purchase).permit(...)
    

    并从模型中删除attr_accessible,那么您不必担心使用attributes.except(...) 进行过滤。

    【讨论】:

    • 感谢更新!我发布的规范对我来说是一种虚拟规范,用于弄清楚如何将参数传递给实际测试。您的回答绝对是测试控制器的更好方法。
    • @eric-wanchic 谢谢!您的valid_session 模式是一个非常有用且优雅的解决方案,用于测试具有 cancan 权限的 Rails 4 控制器。
    • 这行得通。我们也可以通过parameters = ActionController::Parameters.new手动创建参数,然后执行API中包含的所有操作。我们必须 .require(:purchase).permit! 并将参数作为 2 个单独的对象传递,例如。 def purchase_params params.require(:purchase).permit(...) end 然后是其他参数。 api.rubyonrails.org/classes/ActionController/…
    【解决方案2】:

    想通了。我改变了一些东西,但问题是语法。在 PurchasesController 规范中,我将代码更改为:

    describe PurchasesController do
      login_user
      render_views
    
      before(:each) do
        @purchase = Factory(:purchase)
      end
    
      describe "POST create" do
        before(:each) do
          @ability.can :create, Purchase
        end
    
        it "should pass the params to purchase" do
          i = @purchase.id
          p = @purchase.attributes.except('id', 'created_at', 'updated_at')
          pl = @purchase.purchase_line_items.first.attributes.except('id', 'purchase_id', 'created_at', 'updated_at')
          post :create, purchase: { attributes: p, purchase_line_items_attributes: [pl] }
          assigns(:purchase).attributes.except('id', 'created_at', 'updated_at').should == p
          assigns(:purchase).purchase_line_items.first.attributes.except('id', 'purchase_id', 'created_at', 'updated_at').should == pl
        end
      end
    end
    

    需要更改的语法:

    post :create, purchase: purchase.attributes, purchase_line_items_attributes: purchase.purchase_line_items.first.attributes
    

    到:

    post :create, purchase: { attributes: p, purchase_line_items_attributes: [pl] }   
    

    现在一切正常!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-12
      • 2015-10-21
      • 1970-01-01
      • 1970-01-01
      • 2013-03-24
      • 2015-01-14
      相关资源
      最近更新 更多