Skip to content

Instantly share code, notes, and snippets.

@jasoncodes
Created January 19, 2011 02:39
Show Gist options
  • Save jasoncodes/785594 to your computer and use it in GitHub Desktop.
Save jasoncodes/785594 to your computer and use it in GitHub Desktop.
Example usage of `composed_of`.
class Example < ActiveRecord::Base
composed_of :input_voltage,
:class_name => 'VoltageRange',
:mapping => [%w(input_voltage_min min), %w(input_voltage_max max)],
:allow_nil => true,
:converter => :new
composed_of :output_voltage,
:class_name => 'VoltageRange',
:mapping => [%w(output_voltage_min min), %w(output_voltage_max max)],
:allow_nil => true,
:converter => :new
end
class Example < ActiveRecord::Base
def input_voltage
VoltageRange.new(self.input_voltage_min, self.input_voltage_max)
end
def input_voltage=(*args)
range = VoltageRange.new(*args)
self.input_voltage_min = range.min
self.input_voltage_max = range.max
end
def output_voltage
VoltageRange.new(self.output_voltage_min, self.output_voltage_max)
end
def output_voltage=(*args)
range = VoltageRange.new(*args)
self.output_voltage_min = range.min
self.output_voltage_max = range.max
end
end
class VoltageRange
attr_reader :min, :max
def initialize(*args)
case args.length
when 1
if args[0].is_a? Range
@min = args[0].min
@max = args[0].max
else
from_s! args[0]
end
when 2
@min = args[0]
@max = args[1]
else
raise ArgumentError, "Expected 1 or 2 arguments (got #{args.length})"
end
end
def from_s!(value)
case value.to_s.strip.gsub(/ ?(?:V|Volts)?$/i, '')
# empty string
when ""
@min = nil
@max = nil
# 42 (min=42,max=42)
when /\A(\d+(?:\.\d+)?)\z/
@min = $1.to_f
@max = $1.to_f
# "<=5", "max 5" (min=0,max=5)
when /\A(?:<=|max) ?(\d+(?:\.\d+)?)\z/
@min = 0
@max = $1.to_f
# "$x-$y", "$x to $y" (min=$x,max=$y)
when /\A(\d+(?:\.\d+)?) ?(?:-|to) ?(\d+(?:\.\d+)?)\z/
@min = $1.to_f
@max = $2.to_f
else
raise 'Invalid voltage range: ' + value.inspect
end
end
protected :from_s!
def to_s
case
when @min.nil? && @max.nil?
nil
when @min == @max
"#{@min} V"
when @min == 0
"<= #{max} V"
else
"#{min} - #{max} V"
end
end
def include?(value)
@min.present? && @max.present? && (@min..@max).include?(value)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment