Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial export from project.

  • Loading branch information...
commit 5efb01a9142cc0b1cc34685a8bb025c8afb52cd7 0 parents
@Manfred Manfred authored
1  .gitignore
@@ -0,0 +1 @@
+rdoc
18 LICENSE
@@ -0,0 +1,18 @@
+Copyright (c) 2008 Manfred Stienstra, Fingertips <manfred@fngtps.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
4 README
@@ -0,0 +1,4 @@
+Conversions
+-----------
+
+A plugin to convert units.
22 Rakefile
@@ -0,0 +1,22 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the conversions plugin.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = true
+end
+
+desc 'Generate documentation for conversions plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'Array Paginator'
+ rdoc.options << '--line-numbers' << '--inline-source' << '--charset' << 'utf-8'
+ rdoc.rdoc_files.include('README')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
0  TODO
No changes.
1  init.rb
@@ -0,0 +1 @@
+require 'conversions'
29 lib/conversions.rb
@@ -0,0 +1,29 @@
+module Conversions
+ CONVERSION = {
+ :miles => {
+ :kilometres => 1.609344
+ },
+ :kilograms => {
+ :grams => 1000.0,
+ :pounds => 2.20462262,
+ :short_tons => 0.00110231131,
+ :tons => 0.00110231131
+ },
+ :tons => {
+ :pounds => 2000.0
+ },
+ :gallons => {
+ :litres => 3.7854118
+ },
+ :cubic_feet => {
+ :cubic_meters => 0.0283168466
+ }
+ }
+end
+
+require 'conversions/unit'
+require 'conversions/ext'
+require 'conversions/active_record_accessors'
+
+Numeric.send :include, Conversions::Ext
+ActiveRecord::Base.send :extend, Conversions::ActiveRecordAccessors
39 lib/conversions/active_record_accessors.rb
@@ -0,0 +1,39 @@
+module Conversions #:nodoc:
+ # Implements new accessor classmethods to define conversion accessors on active record classes.
+ module ActiveRecordAccessors
+ # Adds conversion methods to the model for a certain attribute.
+ #
+ # Options:
+ #
+ # * <tt>:internal</tt>: The unit of the internal value
+ # * <tt>:external</tt>: The unit of desired external value
+ # * <tt>:scale</tt>: If a scale is given, the external value is automatically rounded on the specified scale.
+ #
+ #
+ # Examples:
+ #
+ # class Flight
+ # attr_accessor :distance
+ # conversion_accessor :distance, :internal => :kilometers, :external => :miles, :scale => 2
+ #
+ # def initialize(distance)
+ # distance = distance
+ # end
+ # end
+ #
+ # flight = Flight.new(1200)
+ # flight.distance_in_miles #=> 745.65, rounded down to two decimals as specified in :scale
+ def conversion_accessor(attribute, options={})
+ if options[:internal].nil? or options[:external].nil?
+ raise ArgumentError, "Please specify both :external and :internal metrics."
+ end
+ define_method "#{attribute}_in_#{options[:external]}" do
+ v = send(attribute)
+ v ? v.send(options[:internal]).to(options[:external], options[:scale]) : nil
+ end
+ define_method "#{attribute}_in_#{options[:external]}=" do |v|
+ send("#{attribute}=", v.to_f.send(options[:external]).to(options[:internal]))
+ end
+ end
+ end
+end
10 lib/conversions/ext.rb
@@ -0,0 +1,10 @@
+module Conversions #:nodoc:
+ # Defines all the conversion methods (miles, kilometers, etc…)
+ module Ext
+ Unit.conversion.each do |method, _|
+ define_method method do
+ Unit.new self, method
+ end unless respond_to? method
+ end
+ end
+end
45 lib/conversions/unit.rb
@@ -0,0 +1,45 @@
+module Conversions #:nodoc
+ # Proxy class to contain the unit as well as reference the base value
+ class Unit
+ # Create a new Unit instance.
+ #
+ # * _value_: The value to convert from (ie. 4.92)
+ # * _from_: The unit to convert from (ie. :miles)
+ def initialize(value, from)
+ @value = value
+ @from = from
+ end
+
+ # Convert to a certain other unit.
+ #
+ # * _to_: The unit to convert to (ie. :kilometers)
+ # * _scale_: The number of digits behind the decimal point to you want to keep (Optional)
+ def to(to, scale=nil)
+ value = @value * self.class.exchange_rate(@from, to)
+ scale.nil? ? value : (value * (10 ** scale)).round / (10 ** scale).to_f
+ end
+
+ def self.exchange_rate(f, t) #:nodoc:
+ from = conversion[f]
+ raise ArgumentError, "Can't convert from `#{f}', unknown unit" if from.nil?
+ value = from[t]
+ raise ArgumentError, "Can't convert from `#{f}' to `#{t}', unknown unit" if value.nil?
+ value
+ end
+
+ def self.conversion #:nodoc:
+ if !defined? @@conversion
+ @@conversion = {}
+ CONVERSION.each do |from, conversion|
+ conversion.each do |to, value|
+ @@conversion[from] ||= {}
+ @@conversion[from][to] = value
+ @@conversion[to] ||= {}
+ @@conversion[to][from] = 1.0 / value
+ end
+ end
+ end
+ @@conversion
+ end
+ end
+end
30 test/accessor_test.rb
@@ -0,0 +1,30 @@
+require File.dirname(__FILE__) + '/test_helper'
+
+class Flight
+ extend Conversions::ActiveRecordAccessors
+ attr_accessor :distance, :fuel_consumption
+ conversion_accessor :distance, :internal => :kilometres, :external => :miles
+ conversion_accessor :fuel_consumption, :internal => :litres, :external => :gallons, :scale => 2
+end
+
+class AccessorTest < Test::Unit::TestCase
+
+ def setup
+ @flight = Flight.new
+ end
+
+ def test_include
+ assert @flight.respond_to?(:distance)
+ assert @flight.respond_to?(:distance_in_miles)
+ end
+
+ def test_conversion
+ @flight.distance = 1200
+ assert_in_delta 745.645430684801, @flight.distance_in_miles, DELTA
+ end
+
+ def test_conversion_with_scale
+ @flight.fuel_consumption = 3400
+ assert_equal 898.18, @flight.fuel_consumption_in_gallons, DELTA
+ end
+end
13 test/ext_test.rb
@@ -0,0 +1,13 @@
+require File.dirname(__FILE__) + '/test_helper'
+
+class ExtTest < Test::Unit::TestCase
+
+ def test_conversions
+ assert_in_delta 1.609344, 1.miles.to(:kilometres), DELTA
+ assert_in_delta 1.609344, 1.0.miles.to(:kilometres), DELTA
+ assert_in_delta 0.45359237, 1.pounds.to(:kilograms), DELTA
+ assert_in_delta 0.00110231131092439, 1.kilograms.to(:tons), DELTA
+ assert_in_delta 2.20462262184878, 1.kilograms.to(:pounds), DELTA
+ assert_in_delta 1, ( 1.kilograms.to(:pounds) * 1.pounds.to(:kilograms) ), DELTA
+ end
+end
11 test/test_helper.rb
@@ -0,0 +1,11 @@
+require 'test/unit'
+
+if not defined?(ActiveRecord)
+ require 'rubygems'
+ require 'active_record'
+end
+
+$:.unshift File.dirname(__FILE__) + '/../lib'
+require 'conversions'
+
+DELTA = 0.0000001
28 test/unit_test.rb
@@ -0,0 +1,28 @@
+require File.dirname(__FILE__) + '/test_helper'
+
+class UnitTest < Test::Unit::TestCase
+
+ def test_exchange_rate
+ assert_in_delta 1.609344, Conversions::Unit.exchange_rate(:miles, :kilometres), DELTA
+ assert_in_delta 0.621371192237334, Conversions::Unit.exchange_rate(:kilometres, :miles), DELTA
+ assert_raises(ArgumentError) { Conversions::Unit.exchange_rate(:unknown, :miles) }
+ assert_raises(ArgumentError) { Conversions::Unit.exchange_rate(:miles, :unknown) }
+ assert_raises(ArgumentError) { Conversions::Unit.exchange_rate(:nil, :miles) }
+ assert_raises(ArgumentError) { Conversions::Unit.exchange_rate(:miles, :nil) }
+ assert_raises(ArgumentError) { Conversions::Unit.exchange_rate(:nil, :nil) }
+ end
+
+ def test_to
+ unit = Conversions::Unit.new(10.0, :miles)
+ assert_in_delta 16.09344, unit.to(:kilometres), DELTA
+
+ unit = Conversions::Unit.new(10.0, :miles)
+ assert_equal 16.09, unit.to(:kilometres, 2), DELTA
+
+ unit = Conversions::Unit.new(10.0, :kilograms)
+ assert_in_delta 22.0462262184878, unit.to(:pounds), DELTA
+
+ unit = Conversions::Unit.new(10.0, :kilograms)
+ assert_equal 22.05, unit.to(:pounds, 2), DELTA
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.