It does seem strange if you think of it as “return the last evaluated thing from the function.” But that’s not the semantic; the semantic is “everything is an expression and expressions evaluate to a value.” Removing this behavior would make these languages less consistent.
(And yes, in both Ruby and Rust not literally everything is an expression, but almost everything is.)
I agree that because of common uses of things like match in Rust it makes it consistent to also do it for functions. I don't agree that the reason why it's consistent is because a function body is an expression (though of course you have more expertise than me on this one -- and Rust does actually treat scopes much more strictly than most other languages so you could argue every scope has the smell of a function call associated with it).
(And yes, in both Ruby and Rust not literally everything is an expression, but almost everything is.)