8 comments
Thank you very much for this interesting article! Please, do not forget that there are ways to get real random numbers. I wrote a gem (https://rubygems.org/gems/realrand) for this purpose some years ago and it provides easy access to three online sources of true random numbers. You can find its documentation on Github (https://github.com/maik/RealRand).
Best,
Maik
You can pass an argument to sample for the number of elements you want back, so you can simplify this:
Array.new(number) { charset.sample }.join
to
charset.sample(number).join
You can also splat ranges, so you could create one array instead of two; e.g.
charset = [*"a".."z", *"A".."Z"]
Assuming that method is going to be called more than once, it would make sense to define it once as a constant (or possibly class variable) outside of the routine, rather than generating it each call, so more like:
CHARSET = [*"a".."z", *"A".."Z"]
def generate_code(number); CHARSET.sample(number).join
Thank you, I didn’t know that you can pass an argument to sample. And I agree that you should only generate the charset once if you are going to use the method multiple times, but I didn’t want to make the code more complex for the examples.
This is not true actually. `sample` with arguments generates sample without repetitions, so it’s totally different from the original code!
You are right! Thanks for letting us know 🙂
For reference, this is what the documentation has to say about sample:
The elements are chosen by using random and unique indices into the array in order to ensure that an element doesn’t repeat itself unless the array already contained duplicate elements.
In fact, if you do this:
charset = [*'a'..'z', *'A'..'Z'].sample(100).join.size
You only get 52 (one for each in the character set), which might not be what you want.
One of the many things I like about Ruby is how it seems every day I get a chance to learn something new about the language. I had never seen that splat do on a range before.
The other thing I learned today is that coping code that has smart quotes in it gets a syntax error.
o = [('a'..'z'), ('A'..'Z')].map { |i| i.to_a }.flatten
string = (0...50).map { o[rand(o.length)] }.join
From Stack Overflow works fine.
I used a variant in one of my scripts works awesomely well and it’s fast. That said, it’s way better to write code you and others can understand on the fly in production mode, than smart-ass long snippets copy-pasted from SO.
I think creating a method (like a black box) is the way to go.