Statically typed languages have vastly improved since Ruby and Rails came on the scene. Your fizzBuzz example can be done in a type-safe way in a variety of languages: C#, Kotlin, Dart, Swift, Nim(?).
proc fizzBuzz(i: int): string =
if i mod 15 == 0: "FizzBuzz"
elif i mod 3 == 0: "Fizz"
elif i mod 5 == 0: "Buzz"
else: $i
for i in 1..100: echo i.fizzBuzz 42.fizzBuzz
can return 'Fizz' because you can make 42 a method of the Integer object because Ruby is like Smalltalk. Most languages won't let you do that, and if they do, they make it difficult.I'm not saying that's what you want to do. But Ruby on Rails uses that technique to modify the MethodMissing method of its objects. This makes it practical to implement the behaviors that make Ruby on Rails productive for many users.
Yes modifying objects might be a footgun. But if you want the architecture of Ruby on Rails, using another language might be a worse footgun. Or not, it's your code.