Vigenère cipher in Ruby
The code is rather clear, so consider the following to be nitpicks.



I'd say that you are generating a new key stream from the key. I'd certainly not reuse the key variable.



The first i = 0 before the loop seems spurious.

Using i as a counter is well understood, and I'd not worry overly much on the style of it. You are probably the only one who cares if it is really Ruby-esk; developers down the line will understand it.

What I wonder though is that you run your loop length times, but there is a break that seems to trigger before that. That's not all too clear to me.

I wonder what happens if you supply it an "empty" key string. Some guard statements may be in order.



Same for the curly braces. It's clear as it is, choose whatever you want. Personally I slightly favor the braces.



You could consider creating a mod function, however since % is already the modulus, which will never return a negative value if the right value is positive, it seems to me that removing the + 26 is probably the only thing you need to change (during decryption).

Instead of using 26 as unexplained magic value, you should get the size of the LETTERS range instead. That way you can also expand your ciphertext later.



I've got no opinion on the private_class_method as I'm not a Ruby developer (I'm specialized in knowing many languages / constructs and of course applied crypto).