

From Python to Ruby: week one of utter irritation with Rails - josephmosby
https://gist.github.com/4227884/

======
lobster_johnson
(I commented on your gist but I'll comment here as well for completeness.)

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_requested

------
YuriNiyazov
You are going about this all wrong. If you are still struggling with ruby the
language, you shouldn't be learning at the same time one of the most
opinionated DSLs around (rspec), because it will confuse the hell out of a
beginner rubyist

~~~
josephmosby
I agree with you that RSpec is confusing as hell - thus the blog post.

A 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.

~~~
YuriNiyazov
In the Ruby webdev community, RSpec and Devise are considered to be the most
Ruby-ic gems around. The idea, much as with Lisp, is to transform the language
into something that describes the problem at hand as naturally as possible.
RSpec is considered to be a fine example of a language designed for writing
software specifications, and it _still_ happens to be valid Ruby.

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.

~~~
josephmosby
Your second paragraph was huge for me. I think that's a critical learning
point for someone making the jump from Python to Ruby.

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.

~~~
YuriNiyazov
I happen to think that people that say "ruby and python are really similar
languages, I don't understand what the arguing is about" almost willfully
ignore the fact that in modern (aka Lego) programming, a language doesn't
exist on its own, but it is surrounded by a huge community, and in case of
Ruby vs Python, the communities couldn't be more different.

------
haar
You don't have to use the rspec controller matches if it's outside of what
you're used to/how you understand it. You can use response.status.should ==
200.

~~~
josephmosby
Thanks for the feedback. It looks like there were plenty of approaches to
doing easy unit tests... which is part of why I kept scratching my head with
"why the hell did they do that..."

