为什么我的类的实例被视为数组?

时间:2014-06-20 23:00:07

标签: ruby-on-rails ruby rspec

只是一个简单的问题。我有一个看起来像这样的测试规范......

require 'user'

describe "Integration" do
  let(:user) { User.new(voucher) }

  context 'no voucher' do
    let(:voucher) { nil }
context 'no voucher' do
let(:voucher) { nil }

    it 'should bill default price all the time' do
        user.bill
        expect(user.orders[0].billed_for).to eql 6.95
        ... ...
    end
  end

  context 'vouchers' do
    describe 'default vouchers' do
      let(:voucher) { Voucher.create(:default, credit: 15) }

      it 'should not bill user if has a remaining credit' do
        user.bill
        expect(user.orders[0].billed_for).to eql 0.0
        ... ...
      end
    end

我有一个非常简单的凭证类atm

class Voucher
    attr_accessor :credit, :type

    def self.create(type, *attrs)
        @type = type
    end

    def billed_for
        Random.new.rand(0..4)
    end
end

现在奇怪的是,如果我尝试通过用户存储凭证类的变量,它会将其抛出并输出未定义的变量。对象绝对不是,当我检查它告诉我它是一个阵列的类型时!打印这个产生的东西像......     [{:credit => 15}] [{:discount => 50,:number => 3}] 为什么会这样?我在用户类中设置了错误吗?我的用户类位于

之下
require 'order'
require 'voucher'

class User
    attr_accessor :voucher, :orders

    def initialize(voucher = nil, orders =[])
        @orders = orders
        @voucher = voucher.nil? ? nil : voucher
    end

1 个答案:

答案 0 :(得分:1)

您的voucher.create方法实际上并未创建优惠券。如果您检查Voucher.create的返回结果的类,则应该看到Symbol

Voucher.create(:default).class #=> Symbol

这是因为您返回设置@type = type的结果,其中类型为:default,其类别为Symbol。我不确定阵列的来源,但是为了创建一个合适的凭证,你应该覆盖初始化方法,就像你在User类中所做的那样:

class Voucher
  def initialize(type, *attrs)
    @type = type
    # you should probably do something with attrs as well.
  end
end

现在您可以调用Voucher.new来构建初始化的凭证对象:

Voucher.new(:default).class #=> Voucher

如果你想保持相同的api,你可以按如下方式定义self.create:

class Voucher
  def self.create(type, *attrs)
    new(type, *attrs)
  end
end

Voucher.create(:default, :some, :more, :attrs).class #=> Voucher

顺便说一句,你并不需要在User类的初始化方法中检查nil,以下内容是等效的:

class User
  def initialize(voucher = nil, orders =[])
    @orders = orders
    @voucher = voucher
  end
end

查看您的测试,凭证的创建方法有两个参数,即凭证类型和属性哈希。

Voucher.create(:default, credit: 15, discount: 50)

相当于

Voucher.create(:default, { credit: 15, discount: 50 })

所以你可能想要定义凭证的初始化方法如下:

class Voucher
  def initialize(type, attrs = {})
    @type = type
    # iterate through the attributes hash and assign attributes appropriately 
  end
end

假设您已为要分配的每个属性键定义了setter,您可以执行以下操作:

def initialize(type, attrs = {})
  @type = type
  attrs.each do |key, value|
    send("#{key}=", value) 
  end
end

请参阅发送here的文档。

给出以下代码行:

Voucher.new(:default, credit: 15, discount: 50)

凭证的初始化功能会发生以下逻辑:

@type = :default
# iterate through the hash { credit: 15, discount: 50 }
self.credit=(15)   # equivalent to self.credit = 15
self.discount=(50) # equivalent to self.discount = 50

然后您将使用正确初始化的凭证对象。

可以直接修改您的创建方法。