2012-12-19 69 views
0

我正在嘗試創建一個預留模型,其中涉及使用ActiveMerchant在創建時處理付款。Rspec factory_girl ActiveMerchant未定義的方法'credit_card ='

支付處理的初始設置涉及ActiveMerchant Railscast。付款在應用程序內正常工作。 (http://railscasts.com/episodes/145-integrating-active-merchant

我試圖創建Reservation工廠內和它自己內部的credit_card對象「:valid_credit_card」工廠...

基本的測試只是試圖驗證預訂可以被創建。 測試結果:

1) Reservation should have a valid factory 
Failure/Error: @current_reservation = Factory.create(:reservation) 
NoMethodError: 
undefined method `credit_card=' for #<Reservation:0xb5f6173c> 
# ./spec/models/reservation_spec.rb:11 

通過reservation_sets

Factory.define :reservation do |f| 
    f.association :user 
    f.rooms { |a| [a.association(:room)] } 
    f.arrival Time.now + 2.weeks 
    f.nights 2 
    f.phone "555-123-1234" 
    f.credit_card :valid_credit_card 
end 

Factory.define :valid_credit_card, :class => ActiveMerchant::Billing::CreditCard do |f| 
    expiration_date = Time.zone.now + 1.year 
    f.type "visa" 
    f.number "4111111111111111" 
    f.verification_value "333" 
    f.month expiration_date.strftime("%m") 
    f.year expiration_date.strftime("%y") 
    f.first_name "Bob" 
    f.last_name "Smith" 
end 

而且規格/型號/ reservation_spec.rb的belongs_to的用戶和的has_many預訂房間。使用@credit_card Factory.build導致關於「保存」credit_card的錯誤。

如果我刪除行f.credit_card:valid_credit_card我得到即使:monthattr_accessor上市:month 的NoMethodError。在應用程序內創建預定確實有效。

1) Reservation should have a valid factory 
    Failure/Error: @current_reservation = Factory.create(:reservation) 
    NoMethodError: 
     undefined method `month' for nil:NilClass 

describe Reservation do 
    before :each do 
    @smith = Factory.create(:user) 
    @room = Factory.create(:room) 
    #@credit_card = Factory.build(:valid_credit_card) 
    end 
    it "should have a valid factory" do 
    @current_reservation = Factory.create(:reservation) 
    @current_reservation.should be_valid 
    end 
end 

什麼是我忽略/做錯了......?

預訂模型摘錄

class Reservation < ActiveRecord::Base 
    # relationships 
    belongs_to :user 
    has_many :reservation_sets, 
     :dependent => :destroy 
    has_many :rooms, 
      :through => :reservation_sets 
    has_many :transactions, 
      :class_name => 'ReservationTransaction', 
      :dependent => :destroy 

    attr_accessor :card_number, :card_verification, :card_expires_on, :card_type, :ip_address, :rtype, :month, :year 
    # other standard validations 
    validate :validate_card, :on => :create 

    # other reservation methods... 
    # gets paid upon reservation creation 
    def pay_deposit 
    # Generate active merchant object 

    ReservationTransaction.gateway = 
     ActiveMerchant::Billing::AuthorizeNetGateway.new({ 
     :login => rooms[0].user.gateway_login, 
     :password => rooms[0].user.gateway_password 
     }) 

    response = ReservationTransaction.gateway.purchase(deposit_price_in_cents, credit_card, purchase_options) 
    t = transactions.create!(:action => "purchase", :amount => deposit_price_in_cents, :response => response) 
    if response.success? 
     update_attribute(:reserved_at, Time.now) 
     # update state 
     payment_captured! 
    else 
     transaction_declined! 
     errors.add :base, response.message 
    end 
    t.card_number = credit_card.display_number 
    t.save! 
    response.success? 
    end 

    def validate_card 
    unless credit_card.valid? 
     credit_card.errors.full_messages.each do |message| 
     errors.add :base, message #_to_base message 
     end 
    end 
    end 

    def credit_card 
    @credit_card ||= ActiveMerchant::Billing::CreditCard.new(
     :type    => card_type, 
     :number    => card_number, 
     :verification_value => card_verification, 
     :month    => card_expires_on.month, 
     :year    => card_expires_on.year, 
     :first_name   => first_name, 
     :last_name   => last_name 
    ) 
    end 

及從預約控制器

def create 
    @reservation = Reservation.new(params[:reservation]) 
    @reservation.arrival = session[:arrival] 
    @reservation.nights = session[:nights] 
    @reservation.number_kids = session[:number_kids] 
    @reservation.number_adults = session[:number_adults] 
    session[:creating_reservation] = 1 
    @reservation.user_id = @reservation.rooms[0].user_id 
    session[:owner] = @reservation.user_id 
    @rooms = Room.all 
    @reservation.ip_address = request.remote_ip   

    # get room owner... 
    @owner = User.find(@reservation.user_id) 
    respond_to do |format| 
     if @reservation.save 
     if @reservation.pay_deposit 
      #set cc... 
      @reservation.transactions[0].card_number = @reservation.send(:credit_card).display_number 
      ReservationMailer.reservation_created(@reservation).deliver 
      ReservationMailer.reservation_notice(@reservation).deliver 
      session[:arrival] = nil 
      session[:reservation_id] = @reservation.id 
      if @owner 
      thanks_path = "#{@owner.permalink}/reservations/#{@reservation.id}" 
      else 
      thanks_path = @reservation 
      end 
      format.html { redirect_to @reservation, :notice => 'Reservation was successfully created.' } 
      format.json { render :json => @reservation, :status => :created, :location => @reservation } 
      # also trigger email sending or wherever that is 
      # receipt email and order notification 
      # 
     else 
      # set flash or show message problem w/ transaction 

      format.html { render :action => "new" } 
     end 
     else 
     format.html { render :action => "new" } 
     format.json { render :json => @reservation.errors, :status => :unprocessable_entity } 
     end 
    end 
    end 
+0

你的預訂模型是什麼樣的? – Joe

+0

增加了預訂模型和創建動作的一些部分。我知道這需要重構一些......也許這是問題的一部分......感謝您檢查它。 – b2tech

回答

0

它看起來像你想分配credit_card一個價值創造的動作,但你真的沒有一個class accessor 。所以你試圖打電話的地方f.credit_card :valid_credit_card是不行的。

我想從你的工廠中刪除f.credit_card :valid_credit_card並考慮使用rspec stubs,那麼你可以做這樣的事情在你的RSpec的測試如下:

mock_cc = ActiveMerchant::Billing::CreditCard.new(
     :type    => card_type, 
     :number    => card_number, 
     :verification_value => card_verification, 
     :month    => card_expires_on.month, 
     :year    => card_expires_on.year, 
     :first_name   => first_name, 
     :last_name   => last_name 
    ) 

Reservation.stub(:credit_card).and_return(mock_cc) 

這將使它所以當你的模型稱爲credit_card它會返回一個嘲弄的對象。

+0

謝謝,這有助於我指出正確的方向。除了添加'attr:credit_card'這行代碼之外,當我設置'f.card_expires_on'時,我正試圖設置'f.month'和'f.year'。現在通過測試。 – b2tech

相關問題