class KeyServer
@generated_keys = Hash.new
def generate_key
key = SecureRandom.urlsafe_base64
while(purged_keys.include?(key))
key = SecureRandom.urlsafe_base64
end
#add new key to hashes that maintain records
@generated_keys.merge!({key => Time.now})
@all_keys.merge!(@generated_keys) { |key, v1, v2| v1 }
return key
end
我在这里使用生成的密钥:(我需要一个随机对来选择并分配给用户)
def get_available_key
if(generated_keys.empty?)
return "404. No keys available"
else
new_key = @generated_keys.to_a.sample(1)
@generated_keys.delete(new_key[0][0].to_s)
@blocked_keys.merge!({new_key[0][0].to_s => Time.now})
end
end
这是我在Sinatra
api = KeyServer.new
get '/block_key' do
api.get_available_key
end
我尝试了此question中提到的解决方案,但当我将其作为Sinatra
服务器的一部分运行时,我获得了Internal Server Error: No implicit conversion from Array to String
如何使这项工作?任何其他从Hash
获得随机对的方法都是受欢迎的。
答案 0 :(得分:1)
hash.to_a.sample
求值为一个双元素数组,其中第一个元素是某个键,第二个元素是相应的值。
当您致电删除时,您应使用hash.delete(new_key[0])
代替hash.delete(new_key[0][0].to_s)
。
答案 1 :(得分:1)
要从Hash
获取一个随机元素作为Hash
返回,您可以简单地修补Hash
来执行此操作
class Hash
def sample(n)
Hash[to_a.sample(n)]
end
end
然后像
一样打电话h = {a: 1, b: 2, c: 3}
h.sample(1)
#=> {b: 2}
h.sample(2)
#=> {:b=>2, :a=>1}
注意:我在Ruby 2.X中使用Hash::[]
用于兼容性目的,您可以使用to_h
代替。
除此之外,我认为您的代码可能会出现一些问题,而且它们的返回值也是如此。
如果我要重构你的代码,那么就不需要上面的示例代码了,我会改用类似
的东西。def get_available_key
if(generated_keys.empty?)
{"error" => "404. No keys available"}
else
new_key = @generated_keys.keys.sample(1)
@generated_keys.delete(new_key)
@blocked_keys.merge!({new_key => Time.now})[new_key]
end
end
这样它总是会响应Hash
对象进行处理,而且根本不用担心多维数组。
我还会将初始代码更改为更像
def create_new_key
key = SecureRandom.urlsafe_base64
purged_keys.include?(key) ? create_new_key : key
end
def generate_key
key = create_new_key
#add new key to hashes that maintain records
@generated_keys.merge!({key => Time.now})
@all_keys.merge!(@generated_keys) { |key, v1, v2| v1 }
key
end
def add_to_key_chain(length)
@generated_keys ||= {}
length.times do
create_new_key
end
end
虽然我不知道purged_keys
方法是什么样的。