1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
class Customer < ActiveRecord::Base
cattr_accessor :gps_conversion_was_run
composed_of :address, mapping: [ %w(address_street street), %w(address_city city), %w(address_country country) ], allow_nil: true
composed_of :balance, class_name: "Money", mapping: %w(balance amount), converter: Proc.new(&:to_money)
composed_of :gps_location, allow_nil: true
composed_of :non_blank_gps_location, class_name: "GpsLocation", allow_nil: true, mapping: %w(gps_location gps_location),
converter: lambda { |gps| self.gps_conversion_was_run = true; gps.blank? ? nil : GpsLocation.new(gps) }
composed_of :fullname, mapping: %w(name to_s), constructor: Proc.new { |name| Fullname.parse(name) }, converter: :parse
composed_of :fullname_no_converter, mapping: %w(name to_s), class_name: "Fullname"
end
class Address
attr_reader :street, :city, :country
def initialize(street, city, country)
@street, @city, @country = street, city, country
end
def close_to?(other_address)
city == other_address.city && country == other_address.country
end
def ==(other)
other.is_a?(self.class) && other.street == street && other.city == city && other.country == country
end
end
class Money
attr_reader :amount, :currency
EXCHANGE_RATES = { "USD_TO_DKK" => 6, "DKK_TO_USD" => 0.6 }
def initialize(amount, currency = "USD")
@amount, @currency = amount, currency
end
def exchange_to(other_currency)
Money.new((amount * EXCHANGE_RATES["#{currency}_TO_#{other_currency}"]).floor, other_currency)
end
end
class GpsLocation
attr_reader :gps_location
def initialize(gps_location)
@gps_location = gps_location
end
def latitude
gps_location.split("x").first
end
def longitude
gps_location.split("x").last
end
def ==(other)
self.latitude == other.latitude && self.longitude == other.longitude
end
end
class Fullname
attr_reader :first, :last
def self.parse(str)
return nil unless str
if str.is_a?(Hash)
new(str[:first], str[:last])
else
new(*str.to_s.split)
end
end
def initialize(first, last = nil)
@first, @last = first, last
end
def to_s
"#{first} #{last.upcase}"
end
end
|