2012-12-19 68 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

相关问题