acts_as_identifier 1.0.0 → 1.1.3

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: 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