store_as_int 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e3034a4265c20d3df48f06df60764ecece7e27b82e6d8b164d4832a2eedde3a9
4
+ data.tar.gz: 96f656f4ac06ed8af32d80e746a53e83b50cbe6e097a4aff52d6f7f6d267a270
5
+ SHA512:
6
+ metadata.gz: 4468dc2c227c41bf027480939ad156be1ee972e3a72edf5cff5bee5918abfcc9c9d812498251acb5f3cf903a8710b62dbd722d34ba890dc40711591a4eb86eae
7
+ data.tar.gz: '098a626684c9223e4c2c5840d5c201434393f032e82f546415450bac8fa0ddd2118506308e6a866ee57dbdf60d0262b516dbcf50e0da04c24b11fb256bed9142'
@@ -0,0 +1,117 @@
1
+ # = StoreAsInt
2
+ #
3
+ # Seamlessly Store Decimal Values as Integers!
4
+ module StoreAsInt
5
+
6
+ if defined?(Rails)
7
+ require 'store_as_int/engine'
8
+ else
9
+ require 'store_as_int/exchange_rate'
10
+ require 'store_as_int/money'
11
+ end
12
+
13
+ # Create a new ::ExchangRate
14
+ #
15
+ # === Args
16
+ # val:: value to use with the exchange rate
17
+ #
18
+ # === Examples
19
+ # er = StoreAsInt.exchange_rate(1.234567890)
20
+ # OR
21
+ # er = StoreAsInt.exchange_rate('1.234567890')
22
+ # OR
23
+ # er = StoreAsInt.exchange_rate(1234567890)
24
+ #
25
+ # er.to_s => '1.2345'
26
+ # er.to_s(true) => '%1.2345'
27
+ # er.inspect => '%1.2345'
28
+ # er.to_d => 1.234567890
29
+ # er.value => 1234567890
30
+ #
31
+ def self.exchange_rate(val)
32
+ ExchangeRate.new(val)
33
+ end
34
+
35
+ # Create a new ::Money
36
+ #
37
+ # === Args
38
+ # val:: value to use with the money
39
+ #
40
+ # === Examples
41
+ # er = StoreAsInt.money(1001.23)
42
+ # OR
43
+ # er = StoreAsInt.money("1001.23")
44
+ # OR
45
+ # er = StoreAsInt.money(100123)
46
+ #
47
+ # er.to_s => '1001.23'
48
+ # er.to_s(true) => '$1,001.23'
49
+ # er.inspect => '$1,001.23'
50
+ # er.to_d => 1001.23
51
+ # er.value => 100123
52
+ #
53
+ def self.money(val)
54
+ Money.new(val)
55
+ end
56
+
57
+ # Register a new StoreAsInt type
58
+ #
59
+ # === Args
60
+ # under_scored_class_name:: @string - method name to use when initializing
61
+ # base_value:: @integer - number to multiply and divide by when doing conversions
62
+ # number_of_decimals:: @integer - number of decimals to include in to_s method
63
+ # symbol_to_use:: @string - symbol to use in to_s method
64
+ # &block::
65
+ # @block - override to_s method with a block.
66
+ # called with arguments (self, w_sym)
67
+ # where w_sym is a boolean for whether to include symbol in the returned string
68
+ #
69
+ # === Examples
70
+ # StoreAsInt.register 'accurate_money', 10000, 2, '$'
71
+ #
72
+ # am = StoreAsInt::AccurateMoney.new(1.2345)
73
+ # am.to_s(true) => $1.23
74
+ # am.value => 12345
75
+ #
76
+ # ----------
77
+ #
78
+ # StoreAsInt.register 'custom_to_s', 100, 2, '$' do |passed, w_sym|
79
+ # "CUSTOM_STR #{passed.negative_sign}#{passed.sym}#{sprintf("%0.0#{passed.decimals}f", passed.to_d.abs)}"
80
+ # end
81
+ #
82
+ # cts = StoreAsInt.custom_to_s(-1.23)
83
+ # cts.to_s(true) => CUSTOM_STR -$1.23
84
+ # cts.to_s => CUSTOM_STR -$1.23
85
+ # cts.value => -123
86
+ #
87
+ def self.register(under_scored_class_name, base_value = 1, number_of_decimals = 0, symbol_to_use = '', &block)
88
+ const_name = under_scored_class_name.split('_').map(&:capitalize).join('')
89
+
90
+ begin
91
+ const_get(const_name)
92
+
93
+ puts "WARNING - #{const_name} Already Registered. Nothing has been done"
94
+ rescue NameError
95
+ puts " - Registering StoreAsInt::#{const_name}"
96
+
97
+ const_set const_name, Class.new(StoreAsInt::Base)
98
+
99
+ puts " - Registering local constants for StoreAsInt::#{const_name}"
100
+
101
+ const_get(const_name).const_set 'BASE', (base_value && base_value.to_i) || 1
102
+ const_get(const_name).const_set 'DECIMALS', number_of_decimals.to_i
103
+ const_get(const_name).const_set 'SYM', symbol_to_use.to_s
104
+ const_get(const_name).const_set 'STR_FORMAT', block || nil
105
+
106
+ puts " - Registering shortcut method: StoreAsInt.#{under_scored_class_name}(value)"
107
+
108
+ define_singleton_method under_scored_class_name.to_sym do |val|
109
+ const_get(const_name).new(val)
110
+ end
111
+
112
+ puts " - StoreAsInt::#{const_name} registered"
113
+ end
114
+
115
+ const_get(const_name)
116
+ end
117
+ end
@@ -0,0 +1,162 @@
1
+ require 'bigdecimal'
2
+ require 'bigdecimal/util'
3
+
4
+ module StoreAsInt
5
+ class Base
6
+
7
+ # == Constants ============================================================
8
+ BASE = 1
9
+ DECIMALS = nil
10
+ SYM = 1
11
+ STR_FORMAT = nil
12
+
13
+ # == Attributes ============================================================
14
+ attr_accessor :num
15
+
16
+ # == Extensions ===========================================================
17
+ include Comparable
18
+
19
+ # == Class Methods ========================================================
20
+ def self.===(other)
21
+ self === other || Integer === other
22
+ end
23
+
24
+ def self.<=>(other)
25
+ self <=> other || Integer <=> other
26
+ end
27
+
28
+ def self.base
29
+ self::BASE || 1
30
+ end
31
+
32
+ def self.decimals
33
+ self::DECIMALS
34
+ end
35
+
36
+ def self.sym
37
+ self::SYM || ''
38
+ end
39
+
40
+ def self.str_format
41
+ self::STR_FORMAT
42
+ end
43
+
44
+ # == Instance Methods =====================================================
45
+ def initialize(new_val = nil)
46
+ return self.num = 0 unless new_val
47
+
48
+ if new_val.is_a?(self.class)
49
+ self.num = new_val.value
50
+ elsif new_val.is_a?(Integer)
51
+ self.num = new_val
52
+ else
53
+ self.num = (new_val.to_d * self.class.base).to_i
54
+ end
55
+ end
56
+
57
+ def base
58
+ self.class.base
59
+ end
60
+
61
+ def decimals
62
+ @decimals ||= self.class.decimals
63
+ end
64
+
65
+ def base_float
66
+ base.to_f
67
+ end
68
+
69
+ def sym
70
+ @sym ||= self.class.sym
71
+ end
72
+
73
+ def sym=(new_sym)
74
+ @sym = new_sym
75
+ end
76
+
77
+ def convert(other_val)
78
+ self.class.new(other_val)
79
+ end
80
+
81
+ def <=>(compare)
82
+ value <=> convert(compare).value
83
+ end
84
+
85
+ def == (compare)
86
+ value == convert(compare).value
87
+ end
88
+
89
+ def kind_of?(klass)
90
+ self.num.kind_of?(klass)
91
+ end
92
+
93
+ def to_i
94
+ self.num.to_i
95
+ end
96
+
97
+ def to_f
98
+ to_i/base_float
99
+ end
100
+
101
+ def to_d
102
+ to_i.to_d/base
103
+ end
104
+
105
+ def cents
106
+ self
107
+ end
108
+
109
+ def value
110
+ self.num || 0
111
+ end
112
+
113
+ def as_json(*args)
114
+ self.num.as_json(*args)
115
+ end
116
+
117
+ def inspect
118
+ to_s(true)
119
+ end
120
+
121
+ def negative_sign
122
+ value < 0 ? '-' : ''
123
+ end
124
+
125
+ def coerce(other)
126
+ [other, value]
127
+ end
128
+
129
+ def to_s(w_sym = false)
130
+ begin
131
+ str_format.call(self, w_sym)
132
+ rescue
133
+ puts $!.message
134
+ puts $!.backtrace
135
+ ""
136
+ end
137
+ end
138
+
139
+ def present?
140
+ begin
141
+ value.present?
142
+ rescue NoMethodError
143
+ !value.nil? && !(value.to_s == "")
144
+ end
145
+ end
146
+
147
+ def method_missing(name, *args, &blk)
148
+ ret = value.send(name, *args, &blk)
149
+ ret.is_a?(Numeric) ? self.class.new(ret) : ret
150
+ end
151
+
152
+ private
153
+ def str_format
154
+ @str_format ||= self.class.str_format || ->(passed, w_sym) do
155
+ return nil unless w_sym || passed.present?
156
+ str = "#{passed.negative_sign}#{w_sym ? passed.sym : ''}#{passed.decimals ? sprintf("%0.0#{passed.decimals.to_i}f", passed.to_d.abs) : passed.to_i.to_s}".reverse.split('.')
157
+ str[-1] = str[-1].gsub(/(\d{3})(?=\d)/, w_sym ? '\\1,' : '\\1')
158
+ str.join('.').reverse
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,5 @@
1
+ module StoreAsInt
2
+ class Engine < ::Rails::Engine
3
+ config.autoload_paths += Dir["#{config.root}/lib/**/"]
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ require_relative './base'
2
+
3
+ class StoreAsInt::ExchangeRate < StoreAsInt::Base
4
+ BASE = 10000000000
5
+ DECIMALS = 4
6
+ SYM = '%'
7
+ end
@@ -0,0 +1,7 @@
1
+ require_relative './base'
2
+
3
+ class StoreAsInt::Money < StoreAsInt::Base
4
+ BASE = 100
5
+ DECIMALS = 2
6
+ SYM = '$'
7
+ end
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: store_as_int
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.6
5
+ platform: ruby
6
+ authors:
7
+ - Sampson Crowley
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-06-09 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Seamlessly store different types of values (such as dollars) as integers
14
+ email: sampsonsprojects@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/store_as_int.rb
20
+ - lib/store_as_int/base.rb
21
+ - lib/store_as_int/engine.rb
22
+ - lib/store_as_int/exchange_rate.rb
23
+ - lib/store_as_int/money.rb
24
+ homepage: http://rubygems.org/gems/store_as_int
25
+ licenses:
26
+ - MIT
27
+ metadata: {}
28
+ post_install_message:
29
+ rdoc_options: []
30
+ require_paths:
31
+ - lib
32
+ required_ruby_version: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: '0'
37
+ required_rubygems_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ requirements: []
43
+ rubyforge_project:
44
+ rubygems_version: 2.7.6
45
+ signing_key:
46
+ specification_version: 4
47
+ summary: Store values as integers for lossless calculations
48
+ test_files: []