limitable 1.0.1 → 2.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e90558c6154eec0d84bc96b53b16feb809a6dfab2135a054e5d59a6714c49cfc
4
- data.tar.gz: 5a2ac5366290ab0fe20904dd80166ca76a7d7f9aa0d1591d43a5d850312dd652
3
+ metadata.gz: fa345bff02b1a03c0ef3b2515de75383f9e1f55d2cf397fcd2660fe0a66b0746
4
+ data.tar.gz: 3f467cd6b86b8b97b1d7b9d749d0a507b943d9395c4691503cd051360d6ce557
5
5
  SHA512:
6
- metadata.gz: f575314e180d4b218aaea9a062acaaa6aa26ac5193ae9a37d699f9bf0f4ed352bdd3960de99526b7d21a8ce1f5ea2a247e80b60ce565dd899ed50a229d8fe367
7
- data.tar.gz: d08094e1249af6b703cd84c255d1e0b8fcfd23c0d7fe7c7f5c3d67fca369860ece3bcad070af83c1856ec639dabbf9a26d08bfa7aae848f62a054707f01f0bca
6
+ metadata.gz: 6f3d2b2a5ba1904d1a6537bf635cc5ba1c8c374d381ae92fab53b44895e0df3c961ecfbd5bb6dd9440622bb256c5c994cf29a73f416fbea96d0974ea16fa5d46
7
+ data.tar.gz: e14012f9cb14604324304088be9cb9cd6dc620e40b2e5233f0d2964386ebccbd4fe755e12859cd95be2a73d3d60bb5c6c3c78bb5d747aca65aa8ff26120d35ea
data/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ # [2.0.0](https://github.com/benmelz/limitable/compare/v1.1.0...v2.0.0) (2023-07-30)
2
+
3
+
4
+ * feat!: custom translations (#15) ([bacc785](https://github.com/benmelz/limitable/commit/bacc7858d7d506bba60bad2f1d39c32732136aa3)), closes [#15](https://github.com/benmelz/limitable/issues/15) [#12](https://github.com/benmelz/limitable/issues/12)
5
+
6
+
7
+ ### BREAKING CHANGES
8
+
9
+ * reword default validation error messages
10
+
11
+ # [1.1.0](https://github.com/benmelz/limitable/compare/v1.0.1...v1.1.0) (2023-07-17)
12
+
13
+
14
+ ### Features
15
+
16
+ * support for binary column limits ([#14](https://github.com/benmelz/limitable/issues/14)) ([43224d1](https://github.com/benmelz/limitable/commit/43224d1351052833246b94666b7aca76f8c89aa5)), closes [#3](https://github.com/benmelz/limitable/issues/3)
17
+
1
18
  ## [1.0.1](https://github.com/benmelz/limitable/compare/v1.0.0...v1.0.1) (2023-06-09)
2
19
 
3
20
 
data/README.md CHANGED
@@ -34,8 +34,8 @@ gem install limitable
34
34
 
35
35
  ## Usage
36
36
 
37
- Once included in a model, `Limitable` will scan `integer`, `string` and `text` columns for size limits
38
- and define byte size validations accordingly. Limits are configurable through `ActiveRecord` migrations.
37
+ Once included in a model, `Limitable` will scan `integer`, `string`, `text` and `binary` columns for size limits,
38
+ defining byte size validations accordingly. Limits are configurable through `ActiveRecord` migrations.
39
39
 
40
40
  ### Quick Start
41
41
 
@@ -59,6 +59,22 @@ class MyModel < ApplicationRecord
59
59
  end
60
60
  ```
61
61
 
62
+ ### Translations
63
+
64
+ `Limitable` ships with i18n support for its validation error messages. Each column type has its own translation key,
65
+ outlined alongside their default values in `lib/limitable/locale/en.yml`.
66
+
67
+ Each validator will pass a `limit` parameter (min/max integer for integer columns, bytes for string/text/binary),
68
+ which can be used to make the messages less ambiguous if desired.
69
+
70
+ e.g.
71
+
72
+ ```yaml
73
+ en:
74
+ limitable:
75
+ string_limit_exceeded: "may not exceed %{limit} characters"
76
+ ```
77
+
62
78
  ### SQL Adapters
63
79
 
64
80
  `Limitable` is designed to be SQL adapter agnostic, however different adapters have different default behaviors that
@@ -72,7 +88,7 @@ limits in your database migrations/schema unless you want to change them from th
72
88
  #### `pg`
73
89
 
74
90
  PostgreSQL has and reports hard limits on its integer columns, however it supports and defaults to unlimited
75
- string/text columns. If you wish for limits to be validated on those columns, they must be explicitly set in your
91
+ string/text/binary columns. If you wish for limits to be validated on those columns, they must be explicitly set in your
76
92
  database migrations/schema.
77
93
 
78
94
  #### `sqlite3`
@@ -0,0 +1,8 @@
1
+ en:
2
+ limitable:
3
+ integer_limit_exceeded:
4
+ upper: "is too large"
5
+ lower: "is too small"
6
+ string_limit_exceeded: "is too long"
7
+ text_limit_exceeded: "is too long"
8
+ binary_limit_exceeded: "is too large"
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'i18n'
4
+
5
+ module Limitable
6
+ # == Limitable::Locale
7
+ #
8
+ # Loads the default limitable custom translations into i18n.
9
+ #
10
+ module Locale
11
+ I18n.load_path << File.expand_path('locale/en.yml', __dir__)
12
+ end
13
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Limitable
4
- VERSION = '1.0.1'
4
+ VERSION = '2.0.0'
5
5
  end
data/lib/limitable.rb CHANGED
@@ -3,18 +3,19 @@
3
3
  require 'active_record'
4
4
  require 'i18n'
5
5
  require_relative 'limitable/base'
6
+ require_relative 'limitable/locale'
6
7
  require_relative 'limitable/version'
7
8
 
8
9
  # == Limitable
9
10
  #
10
11
  # Module that declares database limit validations when included in an ActiveRecord model class. Supports limit
11
- # inferences on integer, string and text columns.
12
+ # inferences on integer, string, text and binary columns.
12
13
  #
13
14
  module Limitable
14
15
  class << self
15
16
  def included(klass)
16
- safe_column_names(klass)&.each do |column_name|
17
- add_limit_validation klass, column_name
17
+ safe_column_names(klass).each do |column_name|
18
+ attach_limit_validator_if_needed klass, column_name
18
19
  end
19
20
  end
20
21
 
@@ -23,53 +24,66 @@ module Limitable
23
24
  def safe_column_names(klass)
24
25
  klass.column_names
25
26
  rescue ActiveRecord::ActiveRecordError, ArgumentError
26
- nil
27
+ []
27
28
  end
28
29
 
29
- def add_limit_validation(klass, column_name)
30
+ def attach_limit_validator_if_needed(klass, column_name)
30
31
  column = klass.column_for_attribute column_name
31
32
  limit = column.sql_type_metadata.limit
32
33
  return if limit.blank?
33
34
 
34
35
  case column.type
35
- when :integer
36
- add_integer_limit_validation klass, column_name, limit
37
- when :string, :text
38
- add_string_limit_validation klass, column_name, limit
36
+ when :integer, :string, :text, :binary
37
+ klass.validate(&send(:"build_#{column.type}_limit_validator", column_name, limit))
39
38
  end
40
39
  end
41
40
 
42
- def add_integer_limit_validation(klass, column_name, limit)
41
+ def build_integer_limit_validator(column_name, limit)
43
42
  min, max = integer_limit_range limit
44
- integer_type_normalizer = method :integer_type_normalizer
45
- klass.validate do
46
- value = integer_type_normalizer.call klass, column_name, self[column_name]
47
- next unless value.is_a?(Integer)
43
+ lambda do
44
+ value = begin
45
+ self.class.type_for_attribute(column_name).serialize self[column_name]
46
+ rescue ActiveModel::RangeError => e
47
+ e.message.match(/(?<number>\d+) is out of range/)[:number].to_i
48
+ end
49
+ next unless value.is_a? Integer
48
50
 
49
- errors.add column_name, I18n.t('errors.messages.greater_than_or_equal_to', count: min) if value < min
50
- errors.add column_name, I18n.t('errors.messages.less_than_or_equal_to', count: max) if value > max
51
+ errors.add column_name, I18n.t('limitable.integer_limit_exceeded.lower', limit: min) if value < min
52
+ errors.add column_name, I18n.t('limitable.integer_limit_exceeded.upper', limit: max) if value > max
51
53
  end
52
54
  end
53
55
 
54
- def integer_limit_range(limit)
55
- max = (1 << ((limit * 8) - 1)) - 1
56
- min = -max
57
- [min, max]
58
- end
56
+ def build_string_limit_validator(column_name, limit)
57
+ lambda do
58
+ value = self.class.type_for_attribute(column_name).serialize self[column_name]
59
+ next unless value.is_a?(String) && value.bytesize > limit
59
60
 
60
- def integer_type_normalizer(klass, column_name, value)
61
- klass.type_for_attribute(column_name).serialize value
62
- rescue ActiveModel::RangeError => e
63
- e.message.match(/(?<number>\d+) is out of range/)[:number].to_i
61
+ errors.add column_name, I18n.t('limitable.string_limit_exceeded', limit: limit)
62
+ end
64
63
  end
65
64
 
66
- def add_string_limit_validation(klass, column_name, limit)
67
- klass.validate do
68
- value = klass.type_for_attribute(column_name).serialize self[column_name]
65
+ def build_text_limit_validator(column_name, limit)
66
+ lambda do
67
+ value = self.class.type_for_attribute(column_name).serialize self[column_name]
69
68
  next unless value.is_a?(String) && value.bytesize > limit
70
69
 
71
- errors.add column_name, I18n.t('errors.messages.too_long.other', count: limit)
70
+ errors.add column_name, I18n.t('limitable.text_limit_exceeded', limit: limit)
72
71
  end
73
72
  end
73
+
74
+ def build_binary_limit_validator(column_name, limit)
75
+ lambda do
76
+ value = self.class.type_for_attribute(column_name).serialize self[column_name]
77
+ next unless value.is_a?(ActiveModel::Type::Binary::Data) && value.to_s.bytesize > limit
78
+
79
+ errors.add column_name, I18n.t('limitable.binary_limit_exceeded', limit: limit)
80
+ end
81
+ end
82
+
83
+ def integer_limit_range(limit)
84
+ max = (1 << ((limit * 8) - 1)) - 1
85
+ min = -max
86
+ [min, max]
87
+ end
74
88
  end
75
89
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: limitable
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Benjamin Melz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-09 00:00:00.000000000 Z
11
+ date: 2023-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -63,6 +63,8 @@ files:
63
63
  - README.md
64
64
  - lib/limitable.rb
65
65
  - lib/limitable/base.rb
66
+ - lib/limitable/locale.rb
67
+ - lib/limitable/locale/en.yml
66
68
  - lib/limitable/version.rb
67
69
  homepage: https://github.com/benmelz/limitable
68
70
  licenses:
@@ -70,7 +72,7 @@ licenses:
70
72
  metadata:
71
73
  homepage_uri: https://github.com/benmelz/limitable
72
74
  source_code_uri: https://github.com/benmelz/limitable
73
- changelog_uri: https://github.com/benmelz/limitable/blob/v1.0.1/CHANGELOG.md
75
+ changelog_uri: https://github.com/benmelz/limitable/blob/v2.0.0/CHANGELOG.md
74
76
  rubygems_mfa_required: 'true'
75
77
  post_install_message:
76
78
  rdoc_options: []