Skip to content

Commit

Permalink
Merge pull request #272 from wvengen/feature-unit_conversion
Browse files Browse the repository at this point in the history
use ruby-units for unit parsing
  • Loading branch information
wvengen committed Mar 15, 2014
2 parents e38fa0d + d45c87f commit 181dd63
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 23 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -421,6 +422,7 @@ DEPENDENCIES
rspec-rails
rspec-rerun
ruby-prof
ruby-units
sass-rails (~> 4.0.0)
select2-rails
selenium-webdriver
Expand Down
15 changes: 8 additions & 7 deletions app/models/article.rb
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ def shared_article
# 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
Expand All @@ -126,13 +127,13 @@ def convert_units
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
Expand Down
16 changes: 0 additions & 16 deletions config/app_config.yml.SAMPLE
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
37 changes: 37 additions & 0 deletions config/initializers/ruby_units.rb
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 181dd63

Please sign in to comment.