acts_as_identifier 1.0.0 → 1.1.3

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: 5eb6246b99ed8a6b043f1b86f7280676f22107154a2b885b9414058e44d8e11d
4
- data.tar.gz: e7ebde2dc53be641c11f26fffefc450568fd2775fe5382e352b16945c7965741
3
+ metadata.gz: 5949d5438578e6ba0dc781e97099ff60de4929de294a46dcb64a1b8f558fd805
4
+ data.tar.gz: e3975e906f51cc8ff890ea819658d70cf6b97b35c0748639c61acd440fbd3d97
5
5
  SHA512:
6
- metadata.gz: 4e88efefec94d938295a34dadb93b29ec350ac7680b997d36499a2f6b2e81c3244dec7142800576752b8b25056e3df1c83c5c237e80546822c1f044136f408e7
7
- data.tar.gz: 5a61dcbb7a9f9d114768a82e28cfe68c3a57834cfc93f154f007774b84554bcf68d4df9cbc3cafafa2a068ef0412d69ced5ab0178eb09c0739508a00056a44f6
6
+ metadata.gz: 1652f9572cf96245f35ad3f36bda3f71ad8e1f271d316b213734c466e7898b772a09a5dd673c24f2a570a2d6342ca48a26766f337235ad19b39922fdb054d1bd
7
+ data.tar.gz: 7d12df48ab6b85d74b1fa345491fcd1b319bb8f7623701bfcdf5f0fa17abf300880d37c5a4576d9ef8605e793993f6cfb4b79824f3817a2223209d822e8015f0
data/README.md CHANGED
@@ -2,23 +2,24 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/acts_as_identifier.svg)](https://badge.fury.io/rb/acts_as_identifier)
4
4
 
5
- Automatically generate unique secure random string for one or more columns of ActiveRecord.
5
+ Automatically generate unique fixed-length string for one or more columns of ActiveRecord based on sequence column
6
6
 
7
7
  ## Usage
8
8
 
9
- > `ActsAsIdentifier` only generate identifier `after_create_commit`
9
+ > `ActsAsIdentifier` only generate identifier `before_commit`
10
10
 
11
11
  ```ruby
12
12
  class Account < ActiveRecord::Base
13
+ include ActsAsIdentifier
13
14
  #
14
- # Note: without Rails, should include ActsAsIdentifier
15
+ # == default options
15
16
  #
16
- # def acts_as_identifier(attr = :identifier,
17
- # length: 6,
18
- # prefix: '',
19
- # id_column: :id,
20
- # chars: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.chars,
21
- # mappings: '3NjncZg82M5fe1PuSABJG9kiRQOqlVa0ybKXYDmtTxCp6Lh7rsIFUWd4vowzHE'.chars)
17
+ # attr: :identifier,
18
+ # seed: 1,
19
+ # length: 6,
20
+ # prefix: nil,
21
+ # id_column: :id,
22
+ # chars: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
22
23
  #
23
24
  acts_as_identifier
24
25
  # or customize options:
@@ -27,9 +28,9 @@ end
27
28
  # => [Account(id: integer, name: string, tenant_id: string, slug: string)]
28
29
 
29
30
  Account.create
30
- # => #<Account:0x00007fcdb90830c0 id: 1, name: nil, tenant_id: nil, slug: "s-HuF2Od">
31
+ # => #<Account:0x00007fcdb90830c0 id: 1, name: nil, tenant_id: nil, slug: "s-EPaPaP">
31
32
  Account.create
32
- # => #<Account:0x00007fcdb90830c0 id: 2, name: nil, tenant_id: nil, slug: "s-g3SIB8">
33
+ # => #<Account:0x00007fcdb90830c0 id: 2, name: nil, tenant_id: nil, slug: "s-HSo0u4">
33
34
 
34
35
  ```
35
36
 
@@ -39,6 +40,10 @@ Account.create
39
40
  bundle add acts_as_identifier
40
41
  ```
41
42
 
43
+ ## Requirements
44
+
45
+ Use gem [`Xencoder`](https://github.com/xiaohui-zhangxh/xencoder/) to encode sequence number to fixed-length string.
46
+
42
47
  ## Contributing
43
48
  Contribution directions go here.
44
49
 
@@ -46,6 +51,4 @@ Contribution directions go here.
46
51
 
47
52
  ```shell
48
53
  bundle exec rspec
49
- # or test specific range
50
- EXTRA_TEST=100000,1000000 bundle exec rspec
51
54
  ```
@@ -1,12 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'securerandom'
4
3
  require 'acts_as_identifier/version'
5
- require 'acts_as_identifier/xbase_integer'
6
- require 'acts_as_identifier/encoder'
4
+ require 'xencoder'
7
5
 
8
6
  module ActsAsIdentifier
9
- LoopTooManyTimesError = Class.new(StandardError)
10
7
 
11
8
  def self.included(base)
12
9
  base.extend ClassMethods
@@ -17,40 +14,41 @@ module ActsAsIdentifier
17
14
  # == Automatically generate unique string based on id
18
15
  #
19
16
  # @param attr [String, Symbol] column name, default: :identifier
17
+ # @param seed [Integer] Random seed, default: 1
20
18
  # @param length [Integer] length of identifier, default: 6
21
- # @params prefix [String, Symbol] add prefix to value, default: ''
19
+ # @params prefix [String, Symbol] add prefix to value, default: nil
22
20
  # @params id_column [String, Symbol] column name of id, default: :id
23
- # @params chars [Array<String>] chars
24
- # @params mappings [Array<String>] mappings must have the same characters as chars
21
+ # @params chars [String] chars for generating identifier
25
22
  def acts_as_identifier(attr = :identifier,
23
+ seed: 1,
26
24
  length: 6,
27
- prefix: '',
25
+ prefix: nil,
28
26
  id_column: :id,
29
- chars: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.chars,
30
- mappings: '3NjncZg82M5fe1PuSABJG9kiRQOqlVa0ybKXYDmtTxCp6Lh7rsIFUWd4vowzHE'.chars)
31
- raise 'chars must be an array' unless chars.is_a?(Array)
32
- raise 'mappings must be an array' unless mappings.is_a?(Array)
33
- unless (chars - mappings).empty? && (mappings - chars).empty?
34
- raise 'chars and mappings must have the same characters'
35
- end
27
+ chars: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
28
+ define_singleton_method "#{attr}_encoder" do
29
+ vname = "@#{attr}_encoder"
30
+ return instance_variable_get(vname) if instance_variable_defined?(vname)
36
31
 
37
- encoder = Encoder.new(chars: chars, mappings: mappings, length: length)
32
+ instance_variable_set(vname, Xencoder.new(chars, length: length, seed: seed))
33
+ end
38
34
 
39
35
  define_singleton_method "decode_#{attr}" do |str|
40
- encoder.decode(str[prefix.length..-1])
36
+ if prefix
37
+ return nil unless str.to_s.start_with?(prefix)
38
+ str = str[prefix.length..-1]
39
+ end
40
+ str && send("#{attr}_encoder").decode(str)
41
41
  end
42
42
 
43
43
  define_singleton_method "encode_#{attr}" do |num|
44
- "#{prefix}#{encoder.encode(num)}"
44
+ "#{prefix}#{send("#{attr}_encoder").encode(num)}"
45
45
  end
46
46
 
47
- before_commit do |record|
48
- if record.previous_changes.key?(id_column.to_s) && !record.destroyed?
49
- record.update_column attr, self.class.send("encode_#{attr}", record.send(id_column))
50
- end
47
+ define_method "acts_as_identifier__update_#{attr}" do
48
+ update_column attr, self.class.send("encode_#{attr}", send(id_column))
51
49
  end
50
+
51
+ before_commit :"acts_as_identifier__update_#{attr}", if: -> { previous_changes.key?(id_column.to_s) && !destroyed? }
52
52
  end
53
53
  end
54
54
  end
55
-
56
- require 'acts_as_identifier/railtie' if defined?(Rails)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActsAsIdentifier
4
- VERSION = '1.0.0'
4
+ VERSION = '1.1.3'
5
5
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts_as_identifier
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - xiaohui
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-06 00:00:00.000000000 Z
11
+ date: 2021-08-05 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: xencoder
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.1.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.1.0
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: rails
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,7 +52,7 @@ dependencies:
38
52
  - - ">="
39
53
  - !ruby/object:Gem::Version
40
54
  version: '0'
41
- description:
55
+ description:
42
56
  email:
43
57
  - xiaohui@tanmer.com
44
58
  executables: []
@@ -48,15 +62,12 @@ files:
48
62
  - MIT-LICENSE
49
63
  - README.md
50
64
  - lib/acts_as_identifier.rb
51
- - lib/acts_as_identifier/encoder.rb
52
- - lib/acts_as_identifier/railtie.rb
53
65
  - lib/acts_as_identifier/version.rb
54
- - lib/acts_as_identifier/xbase_integer.rb
55
66
  homepage: https://github.com/xiaohui-zhangxh/acts_as_identifier
56
67
  licenses:
57
68
  - MIT
58
69
  metadata: {}
59
- post_install_message:
70
+ post_install_message:
60
71
  rdoc_options: []
61
72
  require_paths:
62
73
  - lib
@@ -71,8 +82,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
71
82
  - !ruby/object:Gem::Version
72
83
  version: '0'
73
84
  requirements: []
74
- rubygems_version: 3.0.6
75
- signing_key:
85
+ rubygems_version: 3.0.9
86
+ signing_key:
76
87
  specification_version: 4
77
88
  summary: Auto-generate unique identifier value for Active Record
78
89
  test_files: []
@@ -1,36 +0,0 @@
1
- module ActsAsIdentifier
2
- class Encoder
3
- attr_reader :max, :base, :chars, :mappings, :length
4
-
5
- def initialize(chars:, mappings:, length:)
6
- @chars = chars.dup
7
- @mappings = mappings.dup
8
- @length = length
9
- @xbase_integer = XbaseInteger.new(chars)
10
- @base = @xbase_integer.to_i("#{chars[1]}#{chars[0] * (length - 1)}")
11
- @max = @xbase_integer.to_i(chars[-1] * length) - @base
12
- end
13
-
14
- def encode(num)
15
- str = @xbase_integer.to_x(num + base)
16
- (str.length - 1).downto(1).each do |i|
17
- idx = @mappings.index(str[i])
18
- idx2 = (@mappings.index(str[i - 1]) + idx) % @mappings.size
19
- str[i] = @chars.at(idx)
20
- str[i - 1] = @chars.at(idx2)
21
- end
22
- str
23
- end
24
-
25
- def decode(str)
26
- str = str.dup
27
- 0.upto(str.length - 2).each do |i|
28
- idx = @chars.index(str[i + 1])
29
- idx2 = (@chars.index(str[i]) - idx + @chars.size) % @chars.size
30
- str[i] = @mappings.at(idx2)
31
- str[i + 1] = @mappings.at(idx)
32
- end
33
- @xbase_integer.to_i(str) - base
34
- end
35
- end
36
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActsAsIdentifier
4
- class Railtie < ::Rails::Railtie
5
- initializer 'acts_as_identifier' do
6
- ActiveSupport.on_load(:active_record) do
7
- include ActsAsIdentifier
8
- end
9
- end
10
- end
11
- end
@@ -1,23 +0,0 @@
1
- module ActsAsIdentifier
2
- class XbaseInteger
3
- attr_reader :chars
4
- def initialize(chars)
5
- @chars = chars.dup
6
- end
7
-
8
- def to_i(str)
9
- sum = 0
10
- str.chars.reverse.each_with_index do |char, i|
11
- sum += chars.index(char) * chars.size**i
12
- end
13
- sum
14
- end
15
-
16
- def to_x(num)
17
- str = chars.at(num % chars.size)
18
- num /= chars.size
19
- str = "#{to_x(num)}#{str}" if num > 0
20
- str
21
- end
22
- end
23
- end