measured 2.8.2 → 3.1.0

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.

Potentially problematic release.


This version of measured might be problematic. Click here for more details.

Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +20 -0
  3. data/.github/workflows/ci.yml +12 -6
  4. data/.github/workflows/cla.yml +23 -0
  5. data/.github/workflows/dependabot_auto_merge.yml +93 -0
  6. data/.ruby-version +1 -0
  7. data/CHANGELOG.md +13 -0
  8. data/Gemfile +2 -0
  9. data/README.md +114 -4
  10. data/cache/weight.json +230 -0
  11. data/dev.yml +1 -2
  12. data/gemfiles/rails-7.0.gemfile +6 -0
  13. data/gemfiles/rails-7.1.gemfile +6 -0
  14. data/gemfiles/rails-edge.gemfile +6 -0
  15. data/lib/measured/measurable.rb +3 -1
  16. data/lib/measured/rails/active_record.rb +130 -0
  17. data/lib/measured/rails/validations.rb +68 -0
  18. data/lib/measured/railtie.rb +12 -0
  19. data/lib/measured/units/weight.rb +3 -2
  20. data/lib/measured/version.rb +1 -1
  21. data/lib/measured.rb +2 -0
  22. data/lib/tapioca/dsl/compilers/measured_rails.rb +110 -0
  23. data/measured.gemspec +5 -0
  24. data/test/internal/app/models/thing.rb +14 -0
  25. data/test/internal/app/models/thing_with_custom_unit_accessor.rb +18 -0
  26. data/test/internal/app/models/thing_with_custom_value_accessor.rb +19 -0
  27. data/test/internal/app/models/validated_thing.rb +45 -0
  28. data/test/internal/config/database.yml +3 -0
  29. data/test/internal/config.ru +9 -0
  30. data/test/internal/db/.gitignore +1 -0
  31. data/test/internal/db/schema.rb +99 -0
  32. data/test/internal/log/.gitignore +1 -0
  33. data/test/measurable_test.rb +4 -0
  34. data/test/rails/active_record_test.rb +433 -0
  35. data/test/rails/validation_test.rb +252 -0
  36. data/test/tapioca/dsl/compilers/measured_rails_test.rb +220 -0
  37. data/test/test_helper.rb +15 -0
  38. data/test/units/weight_test.rb +77 -2
  39. metadata +84 -10
  40. data/gemfiles/activesupport-5.2.gemfile +0 -5
  41. data/gemfiles/activesupport-6.0.gemfile +0 -5
  42. data/gemfiles/activesupport-6.1.gemfile +0 -5
data/cache/weight.json CHANGED
@@ -89,6 +89,10 @@
89
89
  "numerator": 1,
90
90
  "denominator": 1000000
91
91
  },
92
+ "q": {
93
+ "numerator": 1,
94
+ "denominator": 100000
95
+ },
92
96
  "slug": {
93
97
  "numerator": 1000,
94
98
  "denominator": 14593903
@@ -203,6 +207,10 @@
203
207
  "numerator": 1,
204
208
  "denominator": 1000000000000000000000000000000
205
209
  },
210
+ "q": {
211
+ "numerator": 1,
212
+ "denominator": 100000000000000000000000000000
213
+ },
206
214
  "slug": {
207
215
  "numerator": 1,
208
216
  "denominator": 14593903000000000000000000000
@@ -317,6 +325,10 @@
317
325
  "numerator": 1,
318
326
  "denominator": 1000000000000000000000000000
319
327
  },
328
+ "q": {
329
+ "numerator": 1,
330
+ "denominator": 100000000000000000000000000
331
+ },
320
332
  "slug": {
321
333
  "numerator": 1,
322
334
  "denominator": 14593903000000000000000000
@@ -431,6 +443,10 @@
431
443
  "numerator": 1,
432
444
  "denominator": 1000000000000000000000000
433
445
  },
446
+ "q": {
447
+ "numerator": 1,
448
+ "denominator": 100000000000000000000000
449
+ },
434
450
  "slug": {
435
451
  "numerator": 1,
436
452
  "denominator": 14593903000000000000000
@@ -545,6 +561,10 @@
545
561
  "numerator": 1,
546
562
  "denominator": 1000000000000000000000
547
563
  },
564
+ "q": {
565
+ "numerator": 1,
566
+ "denominator": 100000000000000000000
567
+ },
548
568
  "slug": {
549
569
  "numerator": 1,
550
570
  "denominator": 14593903000000000000
@@ -659,6 +679,10 @@
659
679
  "numerator": 1,
660
680
  "denominator": 1000000000000000000
661
681
  },
682
+ "q": {
683
+ "numerator": 1,
684
+ "denominator": 100000000000000000
685
+ },
662
686
  "slug": {
663
687
  "numerator": 1,
664
688
  "denominator": 14593903000000000
@@ -773,6 +797,10 @@
773
797
  "numerator": 1,
774
798
  "denominator": 1000000000000000
775
799
  },
800
+ "q": {
801
+ "numerator": 1,
802
+ "denominator": 100000000000000
803
+ },
776
804
  "slug": {
777
805
  "numerator": 1,
778
806
  "denominator": 14593903000000
@@ -887,6 +915,10 @@
887
915
  "numerator": 1,
888
916
  "denominator": 1000000000000
889
917
  },
918
+ "q": {
919
+ "numerator": 1,
920
+ "denominator": 100000000000
921
+ },
890
922
  "slug": {
891
923
  "numerator": 1,
892
924
  "denominator": 14593903000
@@ -1001,6 +1033,10 @@
1001
1033
  "numerator": 1,
1002
1034
  "denominator": 1000000000
1003
1035
  },
1036
+ "q": {
1037
+ "numerator": 1,
1038
+ "denominator": 100000000
1039
+ },
1004
1040
  "slug": {
1005
1041
  "numerator": 1,
1006
1042
  "denominator": 14593903
@@ -1115,6 +1151,10 @@
1115
1151
  "numerator": 1,
1116
1152
  "denominator": 100000000
1117
1153
  },
1154
+ "q": {
1155
+ "numerator": 1,
1156
+ "denominator": 10000000
1157
+ },
1118
1158
  "slug": {
1119
1159
  "numerator": 10,
1120
1160
  "denominator": 14593903
@@ -1229,6 +1269,10 @@
1229
1269
  "numerator": 1,
1230
1270
  "denominator": 10000000
1231
1271
  },
1272
+ "q": {
1273
+ "numerator": 1,
1274
+ "denominator": 1000000
1275
+ },
1232
1276
  "slug": {
1233
1277
  "numerator": 100,
1234
1278
  "denominator": 14593903
@@ -1343,6 +1387,10 @@
1343
1387
  "numerator": 1,
1344
1388
  "denominator": 100000
1345
1389
  },
1390
+ "q": {
1391
+ "numerator": 1,
1392
+ "denominator": 10000
1393
+ },
1346
1394
  "slug": {
1347
1395
  "numerator": 10000,
1348
1396
  "denominator": 14593903
@@ -1457,6 +1505,10 @@
1457
1505
  "numerator": 1,
1458
1506
  "denominator": 10000
1459
1507
  },
1508
+ "q": {
1509
+ "numerator": 1,
1510
+ "denominator": 1000
1511
+ },
1460
1512
  "slug": {
1461
1513
  "numerator": 100000,
1462
1514
  "denominator": 14593903
@@ -1571,6 +1623,10 @@
1571
1623
  "numerator": 1,
1572
1624
  "denominator": 1000
1573
1625
  },
1626
+ "q": {
1627
+ "numerator": 1,
1628
+ "denominator": 100
1629
+ },
1574
1630
  "slug": {
1575
1631
  "numerator": 1000000,
1576
1632
  "denominator": 14593903
@@ -1685,6 +1741,10 @@
1685
1741
  "numerator": 1,
1686
1742
  "denominator": 1
1687
1743
  },
1744
+ "q": {
1745
+ "numerator": 10,
1746
+ "denominator": 1
1747
+ },
1688
1748
  "slug": {
1689
1749
  "numerator": 1000000000,
1690
1750
  "denominator": 14593903
@@ -1799,6 +1859,10 @@
1799
1859
  "numerator": 1000,
1800
1860
  "denominator": 1
1801
1861
  },
1862
+ "q": {
1863
+ "numerator": 10000,
1864
+ "denominator": 1
1865
+ },
1802
1866
  "slug": {
1803
1867
  "numerator": 1000000000000,
1804
1868
  "denominator": 14593903
@@ -1913,6 +1977,10 @@
1913
1977
  "numerator": 1000000,
1914
1978
  "denominator": 1
1915
1979
  },
1980
+ "q": {
1981
+ "numerator": 10000000,
1982
+ "denominator": 1
1983
+ },
1916
1984
  "slug": {
1917
1985
  "numerator": 1000000000000000,
1918
1986
  "denominator": 14593903
@@ -2027,6 +2095,10 @@
2027
2095
  "numerator": 1000000000,
2028
2096
  "denominator": 1
2029
2097
  },
2098
+ "q": {
2099
+ "numerator": 10000000000,
2100
+ "denominator": 1
2101
+ },
2030
2102
  "slug": {
2031
2103
  "numerator": 1000000000000000000,
2032
2104
  "denominator": 14593903
@@ -2141,6 +2213,10 @@
2141
2213
  "numerator": 1000000000000,
2142
2214
  "denominator": 1
2143
2215
  },
2216
+ "q": {
2217
+ "numerator": 10000000000000,
2218
+ "denominator": 1
2219
+ },
2144
2220
  "slug": {
2145
2221
  "numerator": 1000000000000000000000,
2146
2222
  "denominator": 14593903
@@ -2255,6 +2331,10 @@
2255
2331
  "numerator": 1000000000000000,
2256
2332
  "denominator": 1
2257
2333
  },
2334
+ "q": {
2335
+ "numerator": 10000000000000000,
2336
+ "denominator": 1
2337
+ },
2258
2338
  "slug": {
2259
2339
  "numerator": 1000000000000000000000000,
2260
2340
  "denominator": 14593903
@@ -2369,6 +2449,10 @@
2369
2449
  "numerator": 1000000000000000000,
2370
2450
  "denominator": 1
2371
2451
  },
2452
+ "q": {
2453
+ "numerator": 10000000000000000000,
2454
+ "denominator": 1
2455
+ },
2372
2456
  "slug": {
2373
2457
  "numerator": 1000000000000000000000000000,
2374
2458
  "denominator": 14593903
@@ -2483,6 +2567,10 @@
2483
2567
  "numerator": 1,
2484
2568
  "denominator": 1000000000000000000
2485
2569
  },
2570
+ "q": {
2571
+ "numerator": 10,
2572
+ "denominator": 1
2573
+ },
2486
2574
  "slug": {
2487
2575
  "numerator": 1000000000,
2488
2576
  "denominator": 14593903
@@ -2508,6 +2596,124 @@
2508
2596
  "denominator": 45359237
2509
2597
  }
2510
2598
  },
2599
+ "q": {
2600
+ "q": {
2601
+ "numerator": 1,
2602
+ "denominator": 1
2603
+ },
2604
+ "g": {
2605
+ "numerator": 100000,
2606
+ "denominator": 1
2607
+ },
2608
+ "yg": {
2609
+ "numerator": 100000000000000000000000000000,
2610
+ "denominator": 1
2611
+ },
2612
+ "zg": {
2613
+ "numerator": 100000000000000000000000000,
2614
+ "denominator": 1
2615
+ },
2616
+ "ag": {
2617
+ "numerator": 100000000000000000000000,
2618
+ "denominator": 1
2619
+ },
2620
+ "fg": {
2621
+ "numerator": 100000000000000000000,
2622
+ "denominator": 1
2623
+ },
2624
+ "pg": {
2625
+ "numerator": 100000000000000000,
2626
+ "denominator": 1
2627
+ },
2628
+ "ng": {
2629
+ "numerator": 100000000000000,
2630
+ "denominator": 1
2631
+ },
2632
+ "μg": {
2633
+ "numerator": 100000000000,
2634
+ "denominator": 1
2635
+ },
2636
+ "mg": {
2637
+ "numerator": 100000000,
2638
+ "denominator": 1
2639
+ },
2640
+ "cg": {
2641
+ "numerator": 10000000,
2642
+ "denominator": 1
2643
+ },
2644
+ "dg": {
2645
+ "numerator": 1000000,
2646
+ "denominator": 1
2647
+ },
2648
+ "dag": {
2649
+ "numerator": 10000,
2650
+ "denominator": 1
2651
+ },
2652
+ "hg": {
2653
+ "numerator": 1000,
2654
+ "denominator": 1
2655
+ },
2656
+ "kg": {
2657
+ "numerator": 100,
2658
+ "denominator": 1
2659
+ },
2660
+ "Mg": {
2661
+ "numerator": 1,
2662
+ "denominator": 10
2663
+ },
2664
+ "Gg": {
2665
+ "numerator": 1,
2666
+ "denominator": 10000
2667
+ },
2668
+ "Tg": {
2669
+ "numerator": 1,
2670
+ "denominator": 10000000
2671
+ },
2672
+ "Pg": {
2673
+ "numerator": 1,
2674
+ "denominator": 10000000000
2675
+ },
2676
+ "Eg": {
2677
+ "numerator": 1,
2678
+ "denominator": 10000000000000
2679
+ },
2680
+ "Zg": {
2681
+ "numerator": 1,
2682
+ "denominator": 10000000000000000
2683
+ },
2684
+ "Yg": {
2685
+ "numerator": 1,
2686
+ "denominator": 10000000000000000000
2687
+ },
2688
+ "t": {
2689
+ "numerator": 1,
2690
+ "denominator": 10
2691
+ },
2692
+ "slug": {
2693
+ "numerator": 100000000,
2694
+ "denominator": 14593903
2695
+ },
2696
+ "N": {
2697
+ "numerator": 10000000000000000000,
2698
+ "denominator": 10197162129779283
2699
+ },
2700
+ "long_ton": {
2701
+ "numerator": 31250000,
2702
+ "denominator": 317514659
2703
+ },
2704
+ "short_ton": {
2705
+ "numerator": 5000000,
2706
+ "denominator": 45359237
2707
+ },
2708
+ "lb": {
2709
+ "numerator": 10000000000,
2710
+ "denominator": 45359237
2711
+ },
2712
+ "oz": {
2713
+ "numerator": 160000000000,
2714
+ "denominator": 45359237
2715
+ }
2716
+ },
2511
2717
  "slug": {
2512
2718
  "slug": {
2513
2719
  "numerator": 1,
@@ -2601,6 +2807,10 @@
2601
2807
  "numerator": 14593903,
2602
2808
  "denominator": 1000000000
2603
2809
  },
2810
+ "q": {
2811
+ "numerator": 14593903,
2812
+ "denominator": 100000000
2813
+ },
2604
2814
  "N": {
2605
2815
  "numerator": 1459390300000000000,
2606
2816
  "denominator": 10197162129779283
@@ -2715,6 +2925,10 @@
2715
2925
  "numerator": 10197162129779283,
2716
2926
  "denominator": 100000000000000000000
2717
2927
  },
2928
+ "q": {
2929
+ "numerator": 10197162129779283,
2930
+ "denominator": 10000000000000000000
2931
+ },
2718
2932
  "slug": {
2719
2933
  "numerator": 10197162129779283,
2720
2934
  "denominator": 1459390300000000000
@@ -2829,6 +3043,10 @@
2829
3043
  "numerator": 317514659,
2830
3044
  "denominator": 312500000
2831
3045
  },
3046
+ "q": {
3047
+ "numerator": 317514659,
3048
+ "denominator": 31250000
3049
+ },
2832
3050
  "slug": {
2833
3051
  "numerator": 5080234544,
2834
3052
  "denominator": 72969515
@@ -2943,6 +3161,10 @@
2943
3161
  "numerator": 45359237,
2944
3162
  "denominator": 50000000
2945
3163
  },
3164
+ "q": {
3165
+ "numerator": 45359237,
3166
+ "denominator": 5000000
3167
+ },
2946
3168
  "slug": {
2947
3169
  "numerator": 907184740,
2948
3170
  "denominator": 14593903
@@ -3057,6 +3279,10 @@
3057
3279
  "numerator": 45359237,
3058
3280
  "denominator": 100000000000
3059
3281
  },
3282
+ "q": {
3283
+ "numerator": 45359237,
3284
+ "denominator": 10000000000
3285
+ },
3060
3286
  "slug": {
3061
3287
  "numerator": 45359237,
3062
3288
  "denominator": 1459390300
@@ -3171,6 +3397,10 @@
3171
3397
  "numerator": 45359237,
3172
3398
  "denominator": 1600000000000
3173
3399
  },
3400
+ "q": {
3401
+ "numerator": 45359237,
3402
+ "denominator": 160000000000
3403
+ },
3174
3404
  "slug": {
3175
3405
  "numerator": 45359237,
3176
3406
  "denominator": 23350244800
data/dev.yml CHANGED
@@ -1,8 +1,7 @@
1
1
  name: measured
2
2
 
3
3
  up:
4
- - ruby:
5
- version: 3.0.2
4
+ - ruby
6
5
  - bundler
7
6
 
8
7
  commands:
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec path: '..'
4
+
5
+ gem 'activesupport', '~> 7.0'
6
+ gem 'activerecord', '~> 7.0'
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec path: '..'
4
+
5
+ gem 'activesupport', '~> 7.1'
6
+ gem "activerecord", '~> 7.1'
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec path: '..'
4
+
5
+ gem 'activesupport', github: 'rails/rails', branch: 'main'
6
+ gem 'activerecord', github: 'rails/rails', branch: 'main'
@@ -17,6 +17,8 @@ class Measured::Measurable < Numeric
17
17
  value
18
18
  when Integer
19
19
  Rational(value)
20
+ when String
21
+ /\d+\/\d+/.match?(value) ? Rational(value) : BigDecimal(value)
20
22
  else
21
23
  BigDecimal(value)
22
24
  end
@@ -30,7 +32,7 @@ class Measured::Measurable < Numeric
30
32
  else
31
33
  value.to_f.to_s
32
34
  end
33
- str.gsub(/\.0*\Z/, "")
35
+ /\.0*\Z/.match?(str) ? str.gsub(/\.0*\Z/, "") : str
34
36
  end.freeze
35
37
  end
36
38
 
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Measured::Rails::ActiveRecord
4
+ extend ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+ def measured(measured_class, *fields)
8
+ options = fields.extract_options!
9
+ options = {}.merge(options)
10
+
11
+ measured_class = measured_class.constantize if measured_class.is_a?(String)
12
+ unless measured_class.is_a?(Class) && measured_class.ancestors.include?(Measured::Measurable)
13
+ raise Measured::Rails::Error, "Expecting #{ measured_class } to be a subclass of Measured::Measurable"
14
+ end
15
+
16
+ options[:class] = measured_class
17
+
18
+ fields.map(&:to_sym).each do |field|
19
+ raise Measured::Rails::Error, "The field #{ field } has already been measured" if measured_fields.key?(field)
20
+
21
+ measured_fields[field] = options
22
+
23
+ unit_field_name = if options[:unit_field_name]
24
+ measured_fields[field][:unit_field_name] = options[:unit_field_name].to_s
25
+ else
26
+ "#{ field }_unit"
27
+ end
28
+
29
+ value_field_name = if options[:value_field_name]
30
+ measured_fields[field][:value_field_name] = options[:value_field_name].to_s
31
+ else
32
+ "#{ field }_value"
33
+ end
34
+
35
+ # Reader to retrieve measured object
36
+ define_method(field) do
37
+ value = public_send(value_field_name)
38
+ unit = public_send(unit_field_name)
39
+
40
+ return nil unless value && unit
41
+
42
+ instance = instance_variable_get("@measured_#{ field }") if instance_variable_defined?("@measured_#{ field }")
43
+ new_instance = begin
44
+ measured_class.new(value, unit)
45
+ rescue Measured::UnitError
46
+ nil
47
+ end
48
+
49
+ if instance == new_instance
50
+ instance
51
+ else
52
+ instance_variable_set("@measured_#{ field }", new_instance)
53
+ end
54
+ end
55
+
56
+ # Writer to assign measured object
57
+ define_method("#{ field }=") do |incoming|
58
+ if incoming.is_a?(measured_class)
59
+ instance_variable_set("@measured_#{ field }", incoming)
60
+ precision = self.column_for_attribute(value_field_name).precision
61
+ scale = self.column_for_attribute(value_field_name).scale
62
+ rounded_to_scale_value = incoming.value.round(scale)
63
+
64
+ max = self.class.measured_fields[field][:max_on_assignment]
65
+ if max && rounded_to_scale_value > max
66
+ rounded_to_scale_value = max
67
+ elsif rounded_to_scale_value.to_i.to_s.length > (precision - scale)
68
+ raise Measured::Rails::Error, "The value #{rounded_to_scale_value} being set for column '#{value_field_name}' has too many significant digits. Please ensure it has no more than #{precision - scale} significant digits."
69
+ end
70
+
71
+ public_send("#{ value_field_name }=", rounded_to_scale_value)
72
+ public_send("#{ unit_field_name }=", incoming.unit.name)
73
+ else
74
+ instance_variable_set("@measured_#{ field }", nil)
75
+ public_send("#{ value_field_name}=", nil)
76
+ public_send("#{ unit_field_name }=", nil)
77
+ end
78
+ end
79
+
80
+ # Writer to override unit assignment
81
+ redefine_method("#{ unit_field_name }=") do |incoming|
82
+ unit_name = measured_class.unit_system.unit_for(incoming).try!(:name)
83
+ write_attribute(unit_field_name, unit_name || incoming)
84
+ end
85
+ end
86
+ end
87
+
88
+ def measured_fields
89
+ @measured_fields ||= {}
90
+ end
91
+
92
+ end
93
+
94
+ module Length
95
+ extend ActiveSupport::Concern
96
+
97
+ module ClassMethods
98
+ def measured_length(*fields)
99
+ measured(Measured::Length, *fields)
100
+ end
101
+ end
102
+ end
103
+
104
+ module Volume
105
+ extend ActiveSupport::Concern
106
+
107
+ module ClassMethods
108
+ def measured_volume(*fields)
109
+ measured(Measured::Volume, *fields)
110
+ end
111
+ end
112
+ end
113
+
114
+ module Weight
115
+ extend ActiveSupport::Concern
116
+
117
+ module ClassMethods
118
+ def measured_weight(*fields)
119
+ measured(Measured::Weight, *fields)
120
+ end
121
+ end
122
+ end
123
+ end
124
+
125
+ ::ActiveRecord::Base.include(
126
+ Measured::Rails::ActiveRecord,
127
+ Measured::Rails::ActiveRecord::Length,
128
+ Measured::Rails::ActiveRecord::Volume,
129
+ Measured::Rails::ActiveRecord::Weight,
130
+ )
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_model/validations"
4
+
5
+ class MeasuredValidator < ActiveModel::EachValidator
6
+ CHECKS = {
7
+ greater_than: :>,
8
+ greater_than_or_equal_to: :>=,
9
+ equal_to: :==,
10
+ less_than: :<,
11
+ less_than_or_equal_to: :<=,
12
+ }.freeze
13
+
14
+ def validate_each(record, attribute, measurable)
15
+ measured_config = record.class.measured_fields[attribute]
16
+ unit_field_name = measured_config[:unit_field_name] || "#{ attribute }_unit"
17
+ value_field_name = measured_config[:value_field_name] || "#{ attribute }_value"
18
+
19
+ measured_class = measured_config[:class]
20
+
21
+ measurable_unit_name = record.public_send(unit_field_name)
22
+ measurable_value = record.public_send(value_field_name)
23
+
24
+ return unless measurable_unit_name.present? || measurable_value.present?
25
+
26
+ measurable_unit = measured_class.unit_system.unit_for(measurable_unit_name)
27
+ record.errors.add(attribute, message(record, "is not a valid unit")) unless measurable_unit
28
+
29
+ if options[:units] && measurable_unit.present?
30
+ valid_units = Array(options[:units]).map { |unit| measured_class.unit_system.unit_for(unit) }
31
+ record.errors.add(attribute, message(record, "is not a valid unit")) unless valid_units.include?(measurable_unit)
32
+ end
33
+
34
+ if measurable_unit && measurable_value.present?
35
+ options.slice(*CHECKS.keys).each do |option, value|
36
+ comparable_value = value_for(value, record)
37
+ comparable_value = measured_class.new(comparable_value, measurable_unit) unless comparable_value.is_a?(Measured::Measurable)
38
+ unless measurable.public_send(CHECKS[option], comparable_value)
39
+ record.errors.add(attribute, message(record, "#{measurable.to_s} must be #{CHECKS[option]} #{comparable_value}"))
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def message(record, default_message)
48
+ if options[:message].respond_to?(:call)
49
+ options[:message].call(record)
50
+ else
51
+ options[:message] || default_message
52
+ end
53
+ end
54
+
55
+ def value_for(key, record)
56
+ value = case key
57
+ when Proc
58
+ key.call(record)
59
+ when Symbol
60
+ record.send(key)
61
+ else
62
+ key
63
+ end
64
+
65
+ raise ArgumentError, ":#{ value } must be a number or a Measurable object" unless (value.is_a?(Numeric) || value.is_a?(Measured::Measurable))
66
+ value
67
+ end
68
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Measured
4
+ class Rails < ::Rails::Railtie
5
+ class Error < StandardError ; end
6
+
7
+ ActiveSupport.on_load(:active_record) do
8
+ require "measured/rails/active_record"
9
+ require "measured/rails/validations"
10
+ end
11
+ end
12
+ end
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
  Measured::Weight = Measured.build do
3
- si_unit :g, aliases: [:gram, :grams]
3
+ si_unit :g, aliases: [:gram, :grams, :gm, :gms]
4
4
 
5
- unit :t, value: "1000 kg", aliases: [:metric_ton, :metric_tons]
5
+ unit :t, value: "1000 kg", aliases: [:metric_ton, :metric_tons, :tonne, :tonnes]
6
+ unit :q, value: "100 kg", aliases: [:quintal, :quintals]
6
7
  unit :slug, value: "14.593903 kg", aliases: [:slugs]
7
8
  unit :N, value: "0.10197162129779283 kg", aliases: [:newtons, :newton]
8
9
  unit :long_ton, value: "2240 lb", aliases: [:long_tons, :weight_ton, :weight_tons, 'W/T', :imperial_ton, :imperial_tons, :displacement_ton, :displacement_tons]
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Measured
3
- VERSION = "2.8.2"
3
+ VERSION = "3.1.0"
4
4
  end