Reputation: 150
I have 3 classes: Invoice, Address and Customer (but for this problem, only the Invoice and Address class are relevant)
This is my Invoice class:
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
and this is my Address class:
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
And this is my Customer class (not much relevant, but i'm showing for better explanation of the problem)
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
As you can see, my Invoice class has 3 instance variables and my Address class has 2 instance variables.
So, if i test something like that:
cliente = Customer.new(name: "Lucas", age: 28, email: "[email protected]", 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
[]
My instance variables can be acessed through the variable "endereco", that is an Address object, but can't be acessed through entrega.shipping_address that is also an Address object.
To be more precise, if a try this:
p entrega.shipping_address
I get this return:
[#<Address:0x00000001323d58 @zipcode=41701035, @full_address={"cep"=>"41701-035", "logradouro"=>"Rua Parati", "complemento"=>"", "bairro"=>"Alphaville I", "localidade"=>"Salvador", "uf"=>"BA", "unidade"=>"", "ibge"=>"2927408", "gia"=>""}>]
My full object are being returned, but i can't access the content of my @full_address instance variable.
If a do this:
p entrega.shipping_address.full_address
I get a NoMethodError:
solucao.rb:8:in `<main>': undefined method `full_address' for #<Array:0x000000012d25e8> (NoMethodError)
I'm trying to understand why i can't access the content inside my object if i have the full object. Maybe i'm trying to access in the wrong way, i don't know.
Can someone help ?
Upvotes: 0
Views: 1236
Reputation: 36860
values_at
returns an array of values (see https://apidock.com/ruby/Hash/values_at
for explanation)
Change
@shipping_address = attributes.values_at(:shipping_address)
into
@shipping_address = attributes[:shipping_address]
And that way @shipping_address will contain an Address object, not an array that contains an Address object
Upvotes: 3
Reputation: 230286
If you take a look at the error, it says
undefined method `full_address' for #<Array:0x000000012d25e8>
You're trying to call full_address
on an array. So this means that entrega.shipping_address
returns you an array (which it does, of course, take a closer look at the output).
If I were you, I'd look into how shipping_address
is implemented. It's a simple attr_reader
, so it's backed by an instance variable. Must be you initialize that instance variable to a wrong value (it gets an array instead of an address). Look closely at that initialization code and try to run it in IRB session. You should see the problem.
Upvotes: 3