我需要在Ruby中为变量创建一个签名字符串,其中变量可以是数字、字符串、哈希或array.哈希值和数组元素也可以是这些类型中的任何一种.

该字符串将用于比较数据库中的值(本例中为Mongo).

我的第一个 idea 是创建一个JSON编码值的MD5哈希,如下所示:(body是上面提到的变量)

def createsig(body)    
  Digest::MD5.hexdigest(JSON.generate(body))
end

这几乎是可行的,但是JSON.generate不会每次以相同的顺序对哈希的键进行编码,因此createsig({:a=>'a',:b=>'b'})并不总是等于createsig({:b=>'b',:a=>'a'}).

创建签名字符串以满足此需求的最佳方法是什么?

注意:对于我们当中的细节,我知道你不能用数字或字符串来表示.在这种情况下,我会直接打MD5.hexdigest().

推荐答案

我很快编写了以下代码,没有时间在工作中真正测试它,但它应该可以完成这项工作.如果你发现任何问题,请告诉我,我会看一看.

这应该会正确地将数组和散列展平并排序,并且需要使用一些看起来非常奇怪的字符串才能出现任何冲突.

def createsig(body)
  Digest::MD5.hexdigest( sigflat body )
end

def sigflat(body)
  if body.class == Hash
    arr = []
    body.each do |key, value|
      arr << "#{sigflat key}=>#{sigflat value}"
    end
    body = arr
  end
  if body.class == Array
    str = ''
    body.map! do |value|
      sigflat value
    end.sort!.each do |value|
      str << value
    end
  end
  if body.class != String
    body = body.to_s << body.class.to_s
  end
  body
end

> sigflat({:a => {:b => 'b', :c => 'c'}, :d => 'd'}) == sigflat({:d => 'd', :a => {:c => 'c', :b => 'b'}})
=> true

Ruby相关问答推荐

R10K模块在try 安装gem r10k时获得错误的Ruby版本

如何在 Ruby 中正确编写代码?以便它产生正确的输出?

Ruby 中的内联注释

使用 Bundler 时,为什么要关心 RVM 的 Gemset 功能?

哈希或其他对象的内存大小?

ruby:对两个或多个数组的对应成员求和

截断、事务和删除数据库策略的区别

VCRProxy:在 Capybara 内使用 VCR 记录 PhantomJS ajax 调用

如何将消息附加到 RSpec 判断?

Vagrant - 如何拥有特定于主机平台的配置步骤

无法正确自动生成 Ruby DevKit 配置文件

ruby datetime 中有 add_days 吗?

在 RSpec 测试期间 suppress 控制台输出

如何获取符号链接的目标?

Ruby中的file.open、open和IO.foreach,有什么区别?

在命名包含多个单词的Ruby 时,是否应该使用破折号或下划线?

Ruby NOT Rails 中有复数函数吗?

如何在 Ruby 的 IRB 中启用自动完成

Ruby 将 CSV 文件读取为 UTF-8 和/或将 ASCII-8Bit 编码转换为 UTF-8

JavaScript Array:获取项目的范围