Ruby - 将实例变量传递给另一个类

时间:2018-02-11 20:25:25

标签: ruby

我有3个班级:发票,地址和客户(但是对于这个问题,只有发票和地址类是相关的)

这是我的发票类:

class Invoice
  attr_reader :billing_address, :shipping_address, :order

  def initialize(attributes = {})
    @billing_address = attributes.values_at(:billing_address)
    @shipping_address = attributes.values_at(:shipping_address)
    @order = attributes.values_at(:order)
  end
end

这是我的地址类:

class Address
  attr_reader :zipcode, :full_address

  def initialize(zipcode:)
    @zipcode = zipcode  

    url = 'https://viacep.com.br/ws/' + zipcode.to_s + '/json/'
    uri = URI(url)
    status = Net::HTTP.get_response(uri)
    if (status.code == "200")
      response = Net::HTTP.get(uri)
      full_address = JSON.parse(response)
      @full_address = full_address
    else
      p "Houve um erro. API indisponível. Favor tentar novamente mais tarde."
      @full_adress = nil
    end  
  end
end

这是我的客户类(不太相关,但我正在展示更好地解释问题)

class Customer
  attr_reader :name, :age, :email, :gender

  def initialize(attributes = {})
    @name = attributes.values_at(:name)
    @age = attributes.values_at(:age)
    @email = attributes.values_at(:email)
    @gender = attributes.values_at(:gender)
  end

end

如您所见,我的Invoice类有3个实例变量,而我的Address类有2个实例变量。

所以,如果我测试类似的东西:

cliente = Customer.new(name: "Lucas", age: 28, email: "abc@gmail.com", gender: "masculino")
endereco = Address.new(zipcode: 41701035)
entrega = Invoice.new(billing_address: endereco, shipping_address: endereco)

p endereco.instance_variables
  

[:@ zipcode,:@full_address]

p entrega.shipping_address.instance_variables
  

[]

我的实例变量可以通过变量“endereco”获取,这是一个Address对象,但不能通过entrega.shipping_address访问,它也是一个Address对象。

更确切地说,如果试试这个:

p entrega.shipping_address 

我得到了这个回报:

[#<Address:0x00000001323d58 @zipcode=41701035, @full_address={"cep"=>"41701-035", "logradouro"=>"Rua Parati", "complemento"=>"", "bairro"=>"Alphaville I", "localidade"=>"Salvador", "uf"=>"BA", "unidade"=>"", "ibge"=>"2927408", "gia"=>""}>]

我的完整对象正在返回,但我无法访问@full_address实例变量的内容。

如果这样做:

p entrega.shipping_address.full_address

我得到NoM​​ethodError:

solucao.rb:8:in `<main>': undefined method `full_address' for #<Array:0x000000012d25e8> (NoMethodError)

我试图理解为什么如果我拥有完整的对象,我无法访问对象内的内容。也许我试图以错误的方式访问,我不知道。

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:3)

如果你看一下错误,就说

<h1>Currect area: {{ area.name }}</h1>
<h2>Places:</h2>
<ul>
  {% for place in area.places.all %}
    <p>{{ place.name }}</p>
  {% endfor %}
</ul>

您正试图在阵列上拨打undefined method `full_address' for #<Array:0x000000012d25e8> 。所以这意味着full_address会返回一个数组(当然,它会仔细查看输出)。

如果我是你,我会调查entrega.shipping_address的实施方式。它是一个简单的shipping_address,因此它由一个实例变量支持。必须将该实例变量初始化为错误的值(它获取数组而不是地址)。仔细查看该初始化代码并尝试在IRB会话中运行它。你应该看到问题。

答案 1 :(得分:3)

values_at返回一组值(请参阅https://apidock.com/ruby/Hash/values_at 解释)

更改

@shipping_address = attributes.values_at(:shipping_address)

@shipping_address = attributes[:shipping_address]

那样@shipping_address将包含一个Address对象,而不是一个包含Address对象的数组