Ruby – Virtual Attributes

Virtual attributes can be confusing but they help a lot in making things flexible especially when you trying to simplify things while working with Rails. Essentially, we create an attribute that is based on existing attributes. We can also define setter methods for these virtual attributes so that anyone can assign to them, mapping the value to the respective instance variables that they are based on internally.

class Book

attr_reader :isbn

attr_accessor :price

def initialize(isbn, price)

@isbn = isbn

@price = Float(price)

end

#define a virtual attribute based on the instance variable @price

def price_in_cents

Integer(price * 100 + 0.5)

end

#define a setter method for this virtual attribute

def price_in_cents=(cents)

@price = cents/100.0

end

end

#Results

book = Book.new("isbn1", 33.80)

puts "Price = #{book.price}"   #33.8

puts "Price in cents = #{book.price_in_cents}"   #3380

book.price_in_cents = 1234

puts "Price = #{book.price}"   #12.34

puts "Price in cents = #{book.price_in_cents}"   #1234

Here we used attribute methods to create a virtual instance variable. To the outside world, price_in_cents is like a normal attribute. But internally, it has no corresponding instance variable.