Rails:使用base58压缩uuid

使用base58压缩uuid。

写在前面

base58 ,wikipedia上面的定义是这样的:

Base58 is a group of binary-to-text encoding schemes used to represent large integers as alphanumeric text.

我的理解是它是一种将二进制转化为文本的编码方式,用于将大的整数表示成字母和数字的文本组合,其优势在于避免混淆。之前大热的bitcoin,它的address,钱包地址,用的就是base58编码方式。

在Rails中,通常会给model加上uuid作为唯一标示,生成的uuid通常比较长,而且带有’-‘符号,使用base58进行编码会显得更好一些。下面实作一下,如何在Rails中将uuid编码成base58格式。

正文

以一个project的model为例,该model含有字段:uuid,title,description

project.rb的文件内容如下:

class Project < ApplicationRecord
  validates :title, presence: true
  before_validation :generate_uuid, :on => :create

  def to_param
    self.uuid
  end

  protected
  def generate_uuid
    self.uuid ||= SecureRandom.uuid
  end

end

这里,uuid是由SecureRandom.uuid来生成的。

我们定义一下用base58压缩uuid的method,为了能在所有model中都使用这个method,我们用module来包起这个method。具体如下:

  • 在lib目录下新建my_base.rb文件:

  • my_base.rb中添加如下内容:

    module MyBase
      module Base
        ALPHABET = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ".chars
        BASE = ALPHABET.size
        def uuid_as_base58(uuid)
          int_val = uuid.gsub('-','').to_i(16)
          ''.tap do |base58_val|
            while int_val > 0
              int_val, mod = int_val.divmod(BASE)
              base58_val.prepend ALPHABET[mod]
            end
          end
        end
      end
    end
    
    class Object
      include MyBase::Base
    end
    
  • config/application.rb文件中,加入如下内容:

    config.autoload_paths += Dir["#{config.root}/lib/**"]
    

    运行时,会自动加载lib下的文件。

  • 修改project.rb的文件中有关uuid的赋值:

    require 'my_base'
    class Project < ApplicationRecord
    ......
      def generate_uuid
        self.uuid ||= uuid_as_base58(SecureRandom.uuid)
      end
    ......
    end
    
  • 新建一个project看看,会发现已经变成了base58的编码格式

大功告成!

参考

base 58

uuid to base58 in ruby