読者です 読者をやめる 読者になる 読者になる

コピペコードで快適生活

明日使えるソースを自分のために

Rubyで短縮URL用の文字列生成

短縮URL機能を自前で作らないといけないんだけど、その文字列の生成アルゴリズムをどうするかなーってところで、
Flickrの短縮URL用にRubyでbase58実装 | EasyRamble
こちらで紹介されているソースをほぼそのまま利用させてもらいました。

ただ今回は、ひとつ文字をずらしたら隣接IDの情報が見えてしまう的なことを避けたいので、diff引数で隣接が特定されにくくなるような小細工を仕込んでます。

#
# 短縮URL作成用に使う
#
module Base58
  class Base58Exception < Exception; end

  BASE58_ALPHABET = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"

  def self.encode(row_id, diff = 1)
    id = row_id.to_i * diff
    base = BASE58_ALPHABET.size

    encoded_str = ""
    while id > 0
      mod = id % base
      encoded_str = BASE58_ALPHABET[mod] + encoded_str
      id = id / base
    end

    return encoded_str
  end

  def self.decode(encoded_str, diff = 1)
    encoded_str = encoded_str.to_s
    base = BASE58_ALPHABET.size

    decoded = 0
    multi = 1
    while encoded_str.size > 0
      c = encoded_str.slice!(-1)
      decoded = decoded + BASE58_ALPHABET.index(c) * multi
      multi = multi * base
    end

    if decoded % diff != 0
      raise Base58Exception.new("decode error")
    end

    return decoded / diff
  end
end


使い方はこんな感じで。

require 'base58'

# エンコード
Base58.encode(123) # => "38"

# デコード
Base58.decode("38") # => 123

# 文字列ずらすと隣が分かる
Base58.decode("37") # => 122

# エンコード(diff指定)
Base58.encode(123, 256) # => "amU"

# デコード(diff指定)
Base58.decode("amU", 256) # => 123

# 文字列ずらしても隣は分からない。
Base58.decode("amT", 256)
Base58::Base58Exception: decode error
from /home/kinosuke/my_app/lib/util/base58.rb:36:in `decode'