use ruby-units for unit parsing (closes foodcoops/foodsoft#200)

Conflicts:
	Gemfile
	Gemfile.lock
This commit is contained in:
wvengen 2013-12-06 18:14:32 +01:00
parent 48e9a3e4f5
commit c25d4d3f4f
5 changed files with 48 additions and 23 deletions

View file

@ -39,6 +39,7 @@ gem "rails-settings-cached", "0.3.1"
gem 'resque'
gem 'whenever', require: false # For defining cronjobs, see config/schedule.rb
gem 'protected_attributes'
gem 'ruby-units'
# we use the git version of acts_as_versioned, and need to include it in this Gemfile
gem 'acts_as_versioned', git: 'git://github.com/technoweenie/acts_as_versioned.git'

View file

@ -281,6 +281,7 @@ GEM
rspec-rerun (0.1.3)
rspec (>= 2.11.0)
ruby-prof (0.14.2)
ruby-units (1.4.4)
rubyzip (1.1.0)
sass (3.2.14)
sass-rails (4.0.1)
@ -421,6 +422,7 @@ DEPENDENCIES
rspec-rails
rspec-rerun
ruby-prof
ruby-units
sass-rails (~> 4.0.0)
select2-rails
selenium-webdriver

View file

@ -117,6 +117,7 @@ class Article < ActiveRecord::Base
# returns nil if units are eqal
def convert_units
if unit != shared_article.unit
# legacy, used by foodcoops in Germany
if shared_article.unit == "KI" and unit == "ST" # 'KI' means a box, with a different amount of items in it
# try to match the size out of its name, e.g. "banana 10-12 St" => 10
new_unit_quantity = /[0-9\-\s]+(St)/.match(shared_article.name).to_s.to_i
@ -126,13 +127,13 @@ class Article < ActiveRecord::Base
else
false
end
else # get factors for fc and supplier
fc_unit_factor = FoodsoftConfig[:units][self.unit]
supplier_unit_factor = FoodsoftConfig[:units][self.shared_article.unit]
if fc_unit_factor and supplier_unit_factor
convertion_factor = fc_unit_factor / supplier_unit_factor
new_price = BigDecimal((convertion_factor * shared_article.price).to_s).round(2)
new_unit_quantity = ( 1 / convertion_factor) * shared_article.unit_quantity
else # use ruby-units to convert
fc_unit = (::Unit.new(unit) rescue nil)
supplier_unit = (::Unit.new(shared_article.unit) rescue nil)
if fc_unit and supplier_unit and fc_unit =~ supplier_unit
conversion_factor = (fc_unit.convert_to(supplier_unit.units) / supplier_unit).scalar
new_price = shared_article.price * conversion_factor
new_unit_quantity = shared_article.unit_quantity / conversion_factor
[new_price, new_unit_quantity]
else
false

View file

@ -91,22 +91,6 @@ default: &defaults
encoding: utf8
socket: /opt/lampp/var/mysql/mysql.sock
# auto-units-conversion
# this is used for automatic article-synchronization to handle different units
# e.g. when foodcoop-unit should be 500g and supplier-unit is 1kg
units:
KG: 1
1kg: 1
500g: 0.5
400g: 0.4
300g: 0.3
250g: 0.25
200g: 0.2
150g: 0.15
125g: 0.125
100g: 0.1
50g: 0.05
development:
<<: *defaults

View file

@ -0,0 +1,37 @@
# add some more units
if defined? RubyUnits
RubyUnits::Unit.redefine!('liter') do |unit|
unit.aliases += %w{ltr}
end
RubyUnits::Unit.redefine!('kilogram') do |unit|
unit.aliases += %w{KG}
end
RubyUnits::Unit.redefine!('gram') do |unit|
unit.aliases += %w{gr}
end
RubyUnits::Unit.define('piece') do |unit|
unit.definition = RubyUnits::Unit.new('1 each')
unit.aliases = %w{pc pcs piece pieces} # locale: en
unit.aliases += %w{st stuk stuks} # locale: nl
unit.kind = :counting
end
# we use pc for piece, not parsec
RubyUnits::Unit.redefine!('parsec') do |unit|
unit.aliases = unit.aliases.reject {|u| u=='pc'}
unit.display_name = 'parsec'
end
# workaround for ruby-units' require mathn warning: "zero and implicit precision is deprecated."
# default precision of 8 which same as all database definitions in db/migrate/20131213002332_*.rb
class Rational
alias orig_to_d to_d
def to_d(precision=8)
orig_to_d(precision)
end
end
end