From Python to Ruby: week one of utter irritation with Rails
gist.github.com
gist.github.com
It might be a bit easier for your brain if you think of specs not as "Ruby-language scripts", but as "RSpec-language scripts", a language which is a superset of Ruby.
RSpec is a DSL — domain-specific language — on top of Ruby. It purposely pollutes the top-level namespace with shorthand methods so that you don't have to qualify them. Yes, the range of what is available is essentially something you will need to hunt down in the documentation. And yes, the available shorthands are also dependent on what RSpec extensions you have installed; things like WebMock extend the namespace with its own methods.
After the confusion settles I think you will find that the reduced syntax is very helpful. It removes boilerplate to a large extent. In a more verbose test framework such as Test::Unit, developers always move common boilerplate (eg., test setup, common mocks) into test-wide helpers. RSpec just sets the table in a way that also reduces common test boilerplate.
For example, surely `describe Foo` is better than `class FooTest < Test::Unit::TestCase` — even if you don't understand what `describe` really does or where it comes from. You don't need to if you accept it's RSpec syntax.
And surely you will agree that this:
get "/"
last_response.status.should eq 200
...more concisely expresses the intent of the test than this: request = Net::HTTP.get('localhost', '/')
response = http.request request
assert_equal response.code, 200
I personally quite like writing assertions as infix-style expressions (`x.should y`) rather than assertions (`assert_equal`). One reason is the wonderful flexibility in choosing what goes on the left and right sides: lambda {
client.connect!
}.should_not raise_error(Client::ConnectionError)
Or: stub = stub_request(:get, '/template').with({
query: hash_including(name: 'signup'),
headers: {
'Content-Type' => 'application/json'
}
})
get "/signup"
stub.should have_been_requestedA lot of my frustration with Ruby tutorials is that a large pack of them are geared for someone who has never, ever coded before. Syntactically, Ruby isn't that bad. I tried a few courses in Ruby and eventually just switched them off for being too slow.
Part of my issue with Ruby (currently) is that the language can be so flagrantly violated with a gem. I am sure that Python could receive similar treatment... but it would be difficult to pull off, and the community would rip it apart for not being "Pythonic." There's not as strong of a "Ruby-ic" approach to doing things as there is with Python, from my first interactions with the language.
One of the take-aways from this is that within the Python community, "Pythonic" means "keep close to the language as envisioned by GVR", and within the Ruby community, "Ruby-ic" means "the closer you can get it to English and still keep the code executing, the better."
I personally dislike RSpec, but that's a minority opinion. I dislike the general aim to make everything look as natural as possible, because that approach hides too much complexity, a lot of which leaks often in unpredictable ways. Nevertheless, when it comes to pumping out websites, Ruby is my language of choice, and my efficiency in Rails smokes my efficiency in everything else out of the water.
I'll probably still have some frustrations, but knowing that gems are written to look natural by design rather than by accident will likely keep me from throwing my computer at the wall. Two completely different communities operating here.