.join(" ")?

In the below program,

def translate(words)
  words.split(" ").map do |word|
    vowel = first_vowel(word)
    word = word.slice(vowel..-1) + word[0,vowel] + "ay"
  end.join(" ")


why is there a .join right after the first block?

split() takes a string and returns an array
map() takes an array, modifies each item and returns a new array
join() turns the array back into a string putting a space between each item

It is a little odd to see methods directly after a block but it can be done because the block returns a value that can have methods called on it.
It’s more common to see this done with simple blocks on one line.

words.map{ |word| word + "ay" }.join(" ")

is that the best way

When the blocks have more than one line of code it’s standard to use do and end.
Something like this may be more readable.

def translate(words)
  words = words.split(" ").map do |word|
    vowel = first_vowel(word)
    word.slice(vowel..-1) + word[0,vowel] + "ay"

  words.join(" ")