unit_measurements-rails 1.3.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf20e075bf5db7bd8a33f60eb2e14493aa4ed985defd4a3f49b020498a66ec6b
4
- data.tar.gz: df3f2e54ed849cab6b0b6e7221e57bc74c11480053136aba222f6f91b3c43410
3
+ metadata.gz: 88cfa69f2d7ec7ba60a19ac6a4519f38d928ae4cff9df64d72035e76b21cc975
4
+ data.tar.gz: 3bad903fa5c6fbc6f0404be8b85dc96a369ff3bb49a29229c8d57c4927835010
5
5
  SHA512:
6
- metadata.gz: 4a59d3f2cd7a3d7f716aa68ba88ff3c19ae29aade038c6aa1258a5eeef77c6fc44634e3c66167b8e9e499865c51b15861f0122e3cb6b226d1414daa8cb18af14
7
- data.tar.gz: 3c722fab2b67d36ae090aef75a01222e5bbecf937c9a2322c03832a4960e0304975d9a347eef5178ea94cc5ae184f5055f97436e37a5702a1ded9b5cbebd5cc2
6
+ metadata.gz: c8bdc95a6136ee7d39ea0eb55c2ba3420632e7be2511c15eb7fca96b1083687005c2c08359bb0ee2bc5508070239b0dd60f1e5c588f150efd6b224ab40f1f260
7
+ data.tar.gz: 409dc3a9e99814361e1d97953118dfae1b4971da9c16da5bac8d77c81e4cd907a9d303aa883a22b040bb19f799291df5ef74644c9f21987c9c997599bc9e0f0e
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ ## [1.5.0](https://github.com/shivam091/unit_measurements-rails/compare/v1.4.0...v1.5.0) - 2023-11-27
2
+
3
+ ### What's new
4
+
5
+ - Raise error when columns for measurement attribute don't exist in DB.
6
+
7
+ -----------
8
+
9
+ ## [1.4.0](https://github.com/shivam091/unit_measurements-rails/compare/v1.3.0...v1.4.0) - 2023-11-25
10
+
11
+ ### What's updated
12
+
13
+ - Updated RDoc and rearranged files.
14
+
15
+ -----------
16
+
1
17
  ## [1.3.0](https://github.com/shivam091/unit_measurements-rails/compare/v1.2.0...v1.3.0) - 2023-11-22
2
18
 
3
19
  ### What's new
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- unit_measurements-rails (1.3.0)
4
+ unit_measurements-rails (1.5.0)
5
5
  activemodel (>= 7)
6
6
  activerecord (>= 7)
7
7
  railties (>= 7)
@@ -163,12 +163,12 @@ GEM
163
163
  simplecov_json_formatter (~> 0.1)
164
164
  simplecov-html (0.12.3)
165
165
  simplecov_json_formatter (0.1.4)
166
- sqlite3 (1.6.8-x86_64-linux)
166
+ sqlite3 (1.6.9-x86_64-linux)
167
167
  thor (1.3.0)
168
168
  timeout (0.4.1)
169
169
  tzinfo (2.0.6)
170
170
  concurrent-ruby (~> 1.0)
171
- unit_measurements (5.11.0)
171
+ unit_measurements (5.12.0)
172
172
  activesupport (~> 7.0)
173
173
  websocket-driver (0.7.6)
174
174
  websocket-extensions (>= 0.1.0)
@@ -184,7 +184,7 @@ DEPENDENCIES
184
184
  rake (~> 13.0)
185
185
  rspec (~> 3.0)
186
186
  simplecov (~> 0.21, >= 0.21.2)
187
- sqlite3 (~> 1.6)
187
+ sqlite3 (~> 1.6.9)
188
188
  unit_measurements-rails!
189
189
 
190
190
  BUNDLED WITH
data/README.md CHANGED
@@ -13,17 +13,18 @@ A Rails adaptor that encapsulate measurements and their units in Ruby on Rails.
13
13
 
14
14
  ## Introduction
15
15
 
16
- This gem is the Rails integration for the [unit_measurements](https://github.com/shivam091/unit_measurements) gem.
17
- It provides ActiveRecord adapter for persisting and retrieving measurements with their units.
16
+ This gem is designed as a Rails integration for the [unit_measurements](https://github.com/shivam091/unit_measurements) gem.
17
+ It provides an `ActiveRecord` adapter for persisting and retrieving measurements along with their units, simplifying complex
18
+ measurement handling within your Rails applications.
18
19
 
19
20
  ## Minimum Requirements
20
21
 
21
- * Ruby 3.2+ (https://www.ruby-lang.org/en/downloads/branches/)
22
- * Rails 7.0.0+ (https://rubygems.org/gems/rails/versions)
22
+ * Ruby 3.2+ ([Download Ruby](https://www.ruby-lang.org/en/downloads/branches/))
23
+ * Rails 7.0.0+ ([RubyGems - Rails Versions](https://rubygems.org/gems/rails/versions))
23
24
 
24
25
  ## Installation
25
26
 
26
- If using bundler, first add this line to your application's Gemfile:
27
+ To use `unit_measurements-rails` in your Rails application, add the following line to your Gemfile:
27
28
 
28
29
  ```ruby
29
30
  gem "unit_measurements-rails"
@@ -41,102 +42,82 @@ Or otherwise simply install it yourself as:
41
42
 
42
43
  ### ActiveRecord
43
44
 
44
- Attribute names are expected to have the `_quantity` and `_unit` suffix, and be
45
- `DECIMAL` and `VARCHAR` types, respectively, and defaults values are accepted.
46
-
47
- Customizing the accessors used to hold quantity and unit is supported, see below
48
- for details.
45
+ This gem provides an ActiveRecord integration allowing you to declare measurement attributes with their
46
+ corresponding units in your database schema:
49
47
 
50
48
  ```ruby
51
- class CreateTableCubes < ActiveRecord::Migration[7.0]
49
+ class CreateCubes < ActiveRecord::Migration[7.0]
52
50
  def change
53
51
  create_table :cubes do |t|
54
52
  t.decimal :length_quantity, precision: 10, scale: 2
55
53
  t.string :length_unit, limit: 12
56
- t.decimal :width_quantity, precision: 10, scale: 2
57
- t.string :width_unit, limit: 12
58
- t.decimal :height_quantity, precision: 10, scale: 2
59
- t.string :height_unit, limit: 12
60
54
  t.timestamps
61
55
  end
62
56
  end
63
57
  end
64
58
  ```
65
59
 
66
- A column can be declared as a measured with its unit group class:
60
+ Next, declare an atribute as measurement using `measured` with its associated unit
61
+ group class:
67
62
 
68
63
  ```ruby
69
64
  class Cube < ActiveRecord::Base
70
- measured UnitMeasurements::Length, :height
65
+ measured UnitMeasurements::Length, :length
71
66
  end
72
67
  ```
73
68
 
74
- This will allow you to access and assign a measured attribute:
69
+ This setup allows you to access and assign measurement attributes conveniently:
75
70
 
76
71
  ```ruby
77
72
  cube = Cube.new
78
- cube.height = UnitMeasurements::Length.new(5, "ft")
79
- cube.height_quantity #=> 0.5e1
80
- cube.height_unit #=> "ft"
81
- cube.height #=> 5.0 ft
73
+ cube.length = UnitMeasurements::Length.new(5, "ft")
74
+ cube.length_quantity #=> 0.5e1
75
+ cube.length_unit #=> "ft"
76
+ cube.length #=> 5.0 ft
82
77
  ```
83
78
 
84
- Order of assignment does not matter, and each attribute can be assigned separately
85
- and with mass assignment:
79
+ You can specify multiple measurement attributes simultaneously:
86
80
 
87
81
  ```ruby
88
- params = {height_quantity: "3", height_unit: "ft"}
89
- cube = Cube.new(params)
90
- cube.height #=> 3.0 ft
91
- ```
92
-
93
- You can specify multiple measured attributes at a time:
94
-
95
- ```ruby
96
- class Land < ActiveRecord::Base
97
- measured UnitMeasurements::Area, :carpet_area, :buildup_area
82
+ class Cube < ActiveRecord::Base
83
+ measured UnitMeasurements::Length, :length, :width
98
84
  end
99
85
  ```
100
86
 
101
- You can optionally customize the model's quantity and unit accessors by specifying
102
- them in the `quantity_attribute_name` and `unit_attribute_name` option, respectively,
103
- as follows:
87
+ Attribute names are expected to have the `_quantity` and `_unit` suffix, and be
88
+ `DECIMAL` and `VARCHAR` types, respectively, and defaults values are accepted.
89
+
90
+ You can customize the model's quantity and unit accessors by specifying them in the
91
+ `quantity_attribute_name` and `unit_attribute_name` options, respectively.
104
92
 
105
93
  ```ruby
106
94
  class CubeWithCustomAccessor < ActiveRecord::Base
107
95
  measured_length :length, unit_attribute_name: :length_uom
108
96
  measured_length :width, quantity_attribute_name: :width_value
109
- measured_length :height, quantity_attribute_name: :height_value, unit_attribute_name: :height_uom
110
97
  end
111
98
  ```
112
99
 
113
- There are some simpler methods for predefined types:
100
+ For a more streamlined approach, predefined methods are available for commonly used
101
+ types like `length`, `weight`, `area`, `volume`, etc.:
114
102
 
115
103
  ```ruby
116
104
  class Package < ActiveRecord::Base
117
105
  measured_length :size
118
- measured_weight :item_weight, :package_weight
119
106
  measured_area :carpet_area
120
107
  measured_volume :total_volume
108
+ measured_weight :item_weight, :package_weight
121
109
  end
122
110
  ```
123
111
 
124
- This will allow you to access and assign a measurement object:
125
-
126
- ```ruby
127
- package = Package.new
128
- package.item_weight = UnitMeasurements::Weight.new(10, "g")
129
- package.item_weight_unit #=> "g"
130
- package.item_weight_value #=> 10
131
- ```
132
-
133
112
  ## Contributing
134
113
 
135
- 1. Fork it
136
- 2. Create your feature branch (`git checkout -b my-new-feature`)
114
+ Contributions to this project are welcomed! To contribute:
115
+
116
+ 1. Fork this repository
117
+ 2. Create a new branch (`git checkout -b my-new-feature`)
137
118
  3. Commit your changes (`git commit -am "Add some feature"`)
138
- 4. Push to the branch (`git push origin my-new-feature`)
139
- 5. Create new Pull Request
119
+ 4. Push the changes to your branch (`git push origin my-new-feature`)
120
+ 5. Create new **Pull Request**
140
121
 
141
122
  ## License
142
123
 
@@ -15,22 +15,22 @@ module UnitMeasurements
15
15
  module Rails
16
16
  # The +UnitMeasurements::Rails::ActiveRecord+ module enhances ActiveRecord
17
17
  # models by providing a convenient way to handle unit measurements. It
18
- # facilitates defining measurable attributes in models with specific unit
18
+ # facilitates defining measurement attributes in models with specific unit
19
19
  # group support.
20
20
  #
21
21
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
22
22
  # @since 1.0.0
23
23
  module ActiveRecord
24
24
  # @!scope class
25
- # Defines a _reader_ and _writer_ methods for the measured attributes in
25
+ # Defines a _reader_ and _writer_ methods for the measurement attributes in
26
26
  # the +ActiveRecord+ model.
27
27
  #
28
- # @example Defining single measured attribute:
28
+ # @example Defining single measurement attribute:
29
29
  # class Cube < ActiveRecord::Base
30
30
  # measured UnitMeasurements::Length, :height
31
31
  # end
32
32
  #
33
- # @example Defining multiple measured attributes:
33
+ # @example Defining multiple measurement attributes:
34
34
  # class Package < ActiveRecord::Base
35
35
  # measured UnitMeasurements::Weight, :item_weight, :total_weight
36
36
  # end
@@ -38,7 +38,7 @@ module UnitMeasurements
38
38
  # @param [Class|String] unit_group
39
39
  # The unit group class or its name as a string.
40
40
  # @param [Array<String|Symbol>] measured_attrs
41
- # An array of the names of measured attributes.
41
+ # An array of the names of measurement attributes.
42
42
  # @param [Hash] options A customizable set of options
43
43
  # @option options [String|Symbol] :quantity_attribute_name The name of the quantity attribute.
44
44
  # @option options [String|Symbol] :unit_attribute_name The name of the unit attribute.
@@ -46,7 +46,8 @@ module UnitMeasurements
46
46
  # @return [void]
47
47
  #
48
48
  # @raise [BaseError]
49
- # If +unit_group+ is not a subclass of +UnitMeasurements::Measurement+.
49
+ # If +unit_group+ is not a subclass of +UnitMeasurements::Measurement+ or
50
+ # the attribute has already been measured.
50
51
  #
51
52
  # @see BaseError
52
53
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
@@ -60,7 +61,7 @@ module UnitMeasurements
60
61
  options[:unit_group] = unit_group
61
62
 
62
63
  measured_attrs.map(&:to_s).each do |measured_attr|
63
- raise BaseError, "The field '#{measured_attr}' has already been measured." if measured_attributes.key?(measured_attr)
64
+ raise BaseError, "The attribute '#{measured_attr}' has already been measured." if measured_attributes.key?(measured_attr)
64
65
 
65
66
  quantity_attr = options[:quantity_attribute_name]&.to_s || "#{measured_attr}_quantity"
66
67
  unit_attr = options[:unit_attribute_name]&.to_s || "#{measured_attr}_unit"
@@ -75,12 +76,13 @@ module UnitMeasurements
75
76
  end
76
77
 
77
78
  # @!scope class
78
- # Returns a hash containing information about the measured attributes and
79
- # their options.
79
+ # Returns a hash containing information about the measurement attributes
80
+ # and their options.
80
81
  #
81
82
  # @return [Hash{String => Hash{Symbol => String|Class}}]
82
- # A hash where keys represent the names of the measured attributes, and
83
- # values are hashes containing the options for each measured attribute.
83
+ # A hash where keys represent the names of the measurement attributes,
84
+ # and values are hashes containing the options for each measurement
85
+ # attribute.
84
86
  #
85
87
  # @example
86
88
  # {
@@ -111,7 +113,7 @@ module UnitMeasurements
111
113
  # @param [Class] unit_group The unit group class to be validated.
112
114
  #
113
115
  # @raise [BaseError]
114
- # if +unit_group+ is not a subclass of +UnitMeasurements::Measurement+.
116
+ # if unit group is not a subclass of UnitMeasurements::Measurement.
115
117
  #
116
118
  # @return [void]
117
119
  #
@@ -125,9 +127,9 @@ module UnitMeasurements
125
127
 
126
128
  # @!scope class
127
129
  # @private
128
- # Defines the method to read the measured attribute.
130
+ # Defines the method to _read_ the measurement attribute.
129
131
  #
130
- # @param [String] measured_attr The name of the measured attribute.
132
+ # @param [String] measured_attr The name of the measurement attribute.
131
133
  # @param [String] quantity_attr The name of the quantity attribute.
132
134
  # @param [String] unit_attr The name of the unit attribute.
133
135
  # @param [Class] unit_group The unit group class for the measurement.
@@ -138,6 +140,8 @@ module UnitMeasurements
138
140
  # @since 1.0.0
139
141
  def define_reader_for_measured_attr(measured_attr, quantity_attr, unit_attr, unit_group)
140
142
  define_method(measured_attr) do
143
+ column_exists?(quantity_attr) && column_exists?(unit_attr)
144
+
141
145
  quantity, unit = public_send(quantity_attr), public_send(unit_attr)
142
146
 
143
147
  begin
@@ -150,9 +154,9 @@ module UnitMeasurements
150
154
 
151
155
  # @!scope class
152
156
  # @private
153
- # Defines the method to write the measured attribute.
157
+ # Defines the method to _write_ the measurement attribute.
154
158
  #
155
- # @param [String] measured_attr The name of the measured attribute.
159
+ # @param [String] measured_attr The name of the measurement attribute.
156
160
  # @param [String] quantity_attr The name of the quantity attribute.
157
161
  # @param [String] unit_attr The name of the unit attribute.
158
162
  # @param [Class] unit_group The unit group class for the measurement.
@@ -163,6 +167,8 @@ module UnitMeasurements
163
167
  # @since 1.0.0
164
168
  def define_writer_for_measured_attr(measured_attr, quantity_attr, unit_attr, unit_group)
165
169
  define_method("#{measured_attr}=") do |measurement|
170
+ column_exists?(quantity_attr) && column_exists?(unit_attr)
171
+
166
172
  if measurement.is_a?(unit_group)
167
173
  public_send("#{quantity_attr}=", measurement.quantity)
168
174
  public_send("#{unit_attr}=", measurement.unit.name)
@@ -175,7 +181,7 @@ module UnitMeasurements
175
181
 
176
182
  # @!scope class
177
183
  # @private
178
- # Redefines the writer method to set the quantity attribute.
184
+ # Redefines the _writer_ method to set the quantity attribute.
179
185
  #
180
186
  # @param quantity_attr [String] The name of the quantity attribute.
181
187
  #
@@ -185,6 +191,8 @@ module UnitMeasurements
185
191
  # @since 1.0.0
186
192
  def redefine_quantity_writer(quantity_attr)
187
193
  redefine_method("#{quantity_attr}=") do |quantity|
194
+ column_exists?(quantity_attr)
195
+
188
196
  quantity = BigDecimal(quantity, Float::DIG) if quantity.is_a?(String)
189
197
  if quantity
190
198
  db_column_props = self.column_for_attribute(quantity_attr)
@@ -199,7 +207,7 @@ module UnitMeasurements
199
207
 
200
208
  # @!scope class
201
209
  # @private
202
- # Redefines the writer method to set the unit attribute.
210
+ # Redefines the _writer_ method to set the unit attribute.
203
211
  #
204
212
  # @param unit_attr [String] The name of the unit attribute.
205
213
  # @param unit_group [Class] The unit group class for the measurement.
@@ -210,6 +218,8 @@ module UnitMeasurements
210
218
  # @since 1.0.0
211
219
  def redefine_unit_writer(unit_attr, unit_group)
212
220
  redefine_method("#{unit_attr}=") do |unit|
221
+ column_exists?(unit_attr)
222
+
213
223
  unit_name = unit_group.unit_for(unit).try!(:name)
214
224
  write_attribute(unit_attr, (unit_name || unit))
215
225
  end
@@ -33,6 +33,7 @@ module UnitMeasurements
33
33
  end
34
34
  end
35
35
 
36
+ require "unit_measurements/rails/helpers"
36
37
  require "unit_measurements/rails/active_record"
37
38
 
38
39
  require "unit_measurements/rails/railtie" if defined?(Rails)
@@ -0,0 +1,41 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # -*- frozen_string_literal: true -*-
3
+ # -*- warn_indent: true -*-
4
+
5
+ module UnitMeasurements
6
+ module Rails
7
+ # The +UnitMeasurements::Rails::Helpers+ module provides helper methods for
8
+ # handling +ActiveRecord+ models in the context of unit measurements.
9
+ #
10
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
11
+ # @since 1.5.0
12
+ module Helpers
13
+ # Checks the existence of a +column_name+ within the database table
14
+ # associated with the +ActiveRecord+ model.
15
+ #
16
+ # @param [String] column_name The name of the column to check for existence.
17
+ #
18
+ # @raise [ArgumentError]
19
+ # If the specified column does not exist in the database table.
20
+ #
21
+ # @example Check if the +height_quantity+ column exists in the database table:
22
+ # column_exists?("height_quantity")
23
+ #
24
+ # @return [void]
25
+ #
26
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
27
+ # @since 1.5.0
28
+ def column_exists?(column_name)
29
+ unless self.class.column_names.include?(column_name)
30
+ raise ArgumentError, "Column '#{column_name}' does not exist in the database for table '#{self.class.table_name}'."
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ # ActiveSupport hook to include ActiveRecord with the `UnitMeasurements::Rails::Helpers`
38
+ # module.
39
+ ActiveSupport.on_load(:active_record) do
40
+ ::ActiveRecord::Base.send(:include, UnitMeasurements::Rails::Helpers)
41
+ end
@@ -5,6 +5,6 @@
5
5
  module UnitMeasurements
6
6
  module Rails
7
7
  # Current stable version.
8
- VERSION = "1.3.0"
8
+ VERSION = "1.5.0"
9
9
  end
10
10
  end
@@ -43,7 +43,7 @@ Gem::Specification.new do |spec|
43
43
  spec.add_development_dependency "rspec", "~> 3.0"
44
44
  spec.add_development_dependency "simplecov", "~> 0.21", ">= 0.21.2"
45
45
  spec.add_development_dependency "byebug", "~> 11"
46
- spec.add_development_dependency "sqlite3", "~> 1.6"
46
+ spec.add_development_dependency "sqlite3", "~> 1.6.9"
47
47
 
48
48
  spec.required_ruby_version = ">= 3.2"
49
49
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unit_measurements-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harshal LADHE
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-11-22 00:00:00.000000000 Z
11
+ date: 2023-11-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -134,14 +134,14 @@ dependencies:
134
134
  requirements:
135
135
  - - "~>"
136
136
  - !ruby/object:Gem::Version
137
- version: '1.6'
137
+ version: 1.6.9
138
138
  type: :development
139
139
  prerelease: false
140
140
  version_requirements: !ruby/object:Gem::Requirement
141
141
  requirements:
142
142
  - - "~>"
143
143
  - !ruby/object:Gem::Version
144
- version: '1.6'
144
+ version: 1.6.9
145
145
  description: A Rails adaptor that encapsulate measurements and their units in Ruby
146
146
  on Rails.
147
147
  email:
@@ -167,6 +167,7 @@ files:
167
167
  - lib/unit_measurements-rails.rb
168
168
  - lib/unit_measurements/rails/active_record.rb
169
169
  - lib/unit_measurements/rails/base.rb
170
+ - lib/unit_measurements/rails/helpers.rb
170
171
  - lib/unit_measurements/rails/railtie.rb
171
172
  - lib/unit_measurements/rails/unit_groups/all.rb
172
173
  - lib/unit_measurements/rails/unit_groups/area.rb