Rails has Two Default Stacks
words.steveklabnik.com
words.steveklabnik.com
One message I'd like people to understand when they're starting out with Rails is that it really is confusing, and that being confused and maybe even feeling stupid is normal! I remember hearing people talk about how easy developing Rails applications was back in 2006, but what I didn't know was it was easy relative to other web frameworks at the time. It's still hard.
By analogy, if you're an intermediate skiier and you visit a well-groomed mountain with great, powdery snow you could say "this mountain is easy to ski on". But if you're just learning to ski, and you follow everyone else up the lift to the top of a blue run, it's a terrifying experience trying to get down the slope without breaking your neck. To add insult to injury, it's discouraging to see everyone else gliding down the slope while you're shimmying down on your butt because when you try to stand you lose control, go way too fast, then crash. New skiiers need bunny hills, then green runs, then blue runs.
I still don't think there's an established "bunny hill" and "green run" track for learning Rails. Sure would like to help someone create one.
What we've found works is this:
1. Beginners need a curated stack by someone they trust. "Here, this is the stack to learn from; stop wasting time evaluating and get started."
2. Learn about the people, personalities, and community that make the tools. Understand the reasons for their creation; keep up with the conversations.
#1 from above gets beginners unstuck, while #2 will allow them to slowly evaluate different pieces of the stack over time. It's important to understand the "why", not only the "how".
For our courses, we use a mix of the two stacks. For our intro to Rails course, we use: erb, sqlite in dev and postgres in production, fat models and skinny controllers. For our intermediate course, we use haml, rspec, postgres. And finally, for our advanced course, we use "outside in" BDD with Cucumber and introduce the concept of service layers.
We've found this to be a great approach to introducing newbies to the "37 Signal stack" and growing them into the "Prime stack". The goal is to let them figure out their own preferred stack over time, and be productive no matter which stack is in front of them.
That's supposed to be what Rails itself IS, right? Isn't that the point of it being "opinionated", it's supposed to BE the curated stack from someone you trust.
If it's failing, that's a problem.
It certainly is frustrating when you're trying to get the actual Rails stack to work and can't figure out why it seems so hard and someone tells you "Oh yeah, despite the Rails documentation telling you to do it that way, nobody actually does it that way."
Personally, I find the default Rails stack is completely fine for everything I need. I'd not even heard of half of these options in the "alternative stacks" in TFA and the comments here until today. OK, I'd heard of HAML and the other unit testing frameworks, but that's it.
I don't think there's really a big issue here. People could just as easily get distracted by all the different npms in node.js, or the different technologies in the enterprise Java world.
Once you develop your own taste, then you can refine the specifics. But don't get stuck with analysis paralysis in the beginning.
Learning MiniTest/Test::Unit first I would say is a much better approach because you get to focus on the language, which is at the end of the day, the reason Rails is so special.
I read somewhere that someone decided to teach Rspec because it had "less" metaprogramming than a Test::Unit definition.
But in retrospect, it may have been really easy to begin grokking metaprogramming if we had explained that naming something:
class UserTest < TestUnit::TestCase
would end up looking for the User class because of the way it was written. (I believe Rspec does something like this as well but because it deviates from Ruby...it's harder to explain.)I still recommend Michael's tutorial to anyone new to rails, but a '37 signals' stack version would be great.
While I have more than a few complaints about Rails, rspec certainly has never been one of them.
subject { @micropost }
it { should respond_to(:content) }
I prefer writing: assert @micropost.respond_to?(:content)
I haven't looked at rspec in a while and in the rspec example I don't remember how long the subject stays in scope nor would I remember to put braces between 'it' and 'should'. In the testunit example, it's all ruby, there isn't anything more I need to know.It sounds strange, but even though the rspec example reads more like english, I find the assert more readable. Maybe it has something to do with the braces.
As a beginner, there are so many choices you have to make and so many things you have to learn. Rspec adds another item to that list. I would have preferred to learn to write tests with testunit and fixtures and then be presented with rspec, cucumber, factories, etc., a little later.
Have you used both rspec and testunit or just the former?
Well, no, it's a horrible idea, because in English those words would imply a certain syntax tree, while the actual syntax tree in your DSL is completely different, and those words have completely different roles from the ones they have in English. So you have something that superficially looks like English if you take care to arrange it just right, but in fact works in a completely different way from how you know English to work.
It's like having a picture of a sliding knob in your application, except instead of sliding it you're supposed to click it, and it's actually used as a tab switcher. And you put a denim texture on it.
@micropost.should respond_to(:content)
is perfectly valid, and IMO, much cleaner. rspec: @micropost.should respond_to(:context)
testunit: assert @micropost.respond_to?(:context)
rspec: @micropost.should be_valid
testunit: assert @micropost.valid?
rspec: @micropost.should_not be_valid
testunit: refute @micropost.valid?
The testunit It's Just Ruby examples end up looking like the syntactic sugar!For what it's worth, I would definitely not consider the rspec syntax in that Hartl snippet to be a particularly legible example. The code provided in another comment is a much better representation of good style, IMHO.
assert, in my opinion, has the distinct advantage of being immediately recognizable as a special thing while should reads kind of informal.
In fact, I used that as my first resource for learning Rails! Here are some problems I found with it:
1. It teaches you Git along with Rails. Who cares about source control at this point? Remember: This is for a newcomer to Rails that just wants to learn how to create websites using rails; don't confuse me even more.
2. It teaches you how to deploy to Heroku. Again, don't care at this point.
3. It teaches you how to deploy your code to Github. Once again, NEEDLESS INFORMATION AT THIS POINT! :P
4. Unit testing; Ugh, I'm 100 pages in and I barely have a grasp of what I'm doing, and I'm STILL barely 1 controller with 2 actions in.
---
There are other alternatives that I think are better for a newbie.
I will concede that Michael's tutorial IS GOOD, but just not good for someone brand new to ruby and rails. I find myself re-reading Rails Tutorial and The Pragprog Agile Rails book every couple of weeks, discovering new things I missed.
That's the way to learn, keep reviewing things.
Getting code to a working public server was a point of revelation for me as a new rails developer. It was hard, but rewarding.
4 can be safely skipped until you're ready for it.
What Micheal focuses on is teaching you a few things he considers essential to the Rails ecosystem - git, Heroku and RSpec ( He mention the Test::Unit alternative too). I have learnt a lot from his tutorial and this is where I point others new to Rails to go to.
Also, it is better to get acquainted with git while working on a (dummy) project than trying its commands in a vacuum where one doesn't understand its power.
1. Micheal Heartl's Rails Tutorial. 2. Pragmatic Programmers Bookshelf - Agile Rails 3.2 (4th Edition)
Both are a good start but delve far too much into unit testing with the horrific RSpec. When you're learning something new, you don't want to muddle with learning a DSL on top of things.
[0] I teach/tutor Rails programming, and my students have found this resource particularly helpful.
[0] I teach/tutor Rails, and my students have found this resource particularly helpful.
But if you care about Rails uptake, aren't those bad things?
People don't like being confused. People don't like feeling stupid. If their initial impression of a system is "this is confusing" or "this makes me feel stupid," many if not most will simply go look for an alternative that isn't confusing and doesn't make them feel stupid, even if that alternative is inferior in other ways that aren't immediately apparent to the newbie.
I agree with DHH that Rails shouldn't be dumbed down (see his Railsconf 2012 talk https://37signals.com/svn/posts/3171-keynote-by-david-from-r...). Cooking with Rails is like cooking with a real oven, not an easy bake where the end product tastes terrible. Somehow new people need to know that Rails is a real framework that can burn you if you're not careful.
I can't think of anyone though that promotes that method of building websites anymore though, even PHP proponents advocate some flavor of web framework. It just happens to be an easy entry point for using PHP, and once a new developer has built some project momentum for the first time, they're reluctant to start over with something new.
language being more popular than a framework! sure :)
bring one framework that is more popular then rails?
google trends proof: http://www.google.nl/trends/explore#q=ruby%20rails,%20symfon... (many people make searches w/o the 'ruby' search term, so rails wins by a larger margin)
some proof here that php is a lot more popular then ruby:
http://www.google.nl/trends/explore#q=ruby%20tutorial,%20rub...
and java more popular then php... and WOW FLASH!
http://www.google.nl/trends/explore#q=php%20tutorial,%20php%...
we a should all use flash, it is the most popular, more so the java!
gosh.. im trying to prove you're comparing apples with bananas and now i find out i should be coding in Adobe Flash (tm).
</joke>
anyway.. i believe php is only marginally more popular then rails, for stuff that involves "web app development". that's what rails made is for. php is used a lot for ftp-ing scripts to cheap webhosting, something is done a lot less with rails.
Something like this would be very appropriate for a Rails Guide. We already have an introductory one, an 'intermediate' and 'advanced' one would be helpful.
Why is that normal?
I can say with some certainty that when I was deciding between Django and Rails, (and, subsequently Python/Ruby) there was a clear and obvious superior choice. (Hint: not Rails)
Just my two cents.
I, too, am a bottom-up learner, but most people (in my professional experience) are not. Look at the success of Rails Girls, for example: beginners get waaay more excited and engaged by Getting Something Up There than they do learning the intricate details of HTTP.
Yes! That's why...
require sinatra
get '/hi' do
"Hello World!"
end
...is so amazing for newcomers.Even the file structure of rails is a bit too much for begineers. Everything in one file is so much simpler for trivial beginner "get excited" apps.
Introducing someone to rails, they have to learn MVC, a templating system, an ORM, and more.
Other people who get into web development aren't impressed by such things, and would rather see something like rails or WordPress which is shippable right away and then can be built on top of.
Some programmers, especially the kind to hang around on HN, would rather not work with people who don't understand the entire system they use. I often hear people say they wouldn't touch WordPress with a 10-foot pole. They are avoiding a huge part of the web development industry. This is a valid choice, but some people don't even realize they're making this choice, and I wish they would realize it so they could make sure that it's really what they want.
There's a reason for this. I've worked with people that don't understand how things work and don't really want to learn. These people cause enormous amounts of damage in any system that contains architecture beyond php in the webroot and algorithms beyond brute force.
You let one of those people on a large production database, it's game over. They will run queries that miss all the indexes. They will remove constraints because they don't understand why they exist. They will use flat files in place of a database because the database is scary and then not understand why stuff goes missing in the multi-server production environment.
These people are a liability in a project beyond small scale. They are the same people whose wordpress blogs are repeatedly hacked.
Rails is not a good starting point for beginner web developers who don't understand these software design patterns and aren't interested in learning them. If your goal is to just start making websites, like right now, then clearly something like Sinatra is a better choice.
$ rails new my_app
$ rails g scaffold post title:string body:text
is still easy to copy/paste/type from a screen, and gives you a lot more to start with.I realize there are differences in opinion, but I started programming seriously about 6 or 7 years ago, and I started with ruby/Rails.
For me the scaffolding generated too much to easily digest. And separating everything into models/controllers/views is fantastic for a production app, but almost incomprehensible for a newbie. Veteren developers still argue about whether something should go in a model/controller or some other layer, how is a newb supposed to handle it?
In addition you can build sinatra apps without even talking about hooking up a database.
If you're trying to jump in on the deep end and build an MVP, rails is probably the way to go. However, if I really wanted to teach someone to understand what they were doing without being intimated, I'd start with sinatra.
If I'm doing a 3 day engagement, we don't mention scaffolds until after they've hand-built all the code. If you're doing a 8-hour introduction, then yes, you need to use the scaffold.
This is much to the harm of components that might be a better fit for a project: I still believe that Sequel is a much better ORM for people that care about their SQL database and I frankly find it underused in the Rails world. Outside of Rails, its actually rather common, because it has a lot of merits.
I found teaching Padrino strictly better than teaching Rails (I do both), because you can teach it component by component and the missing "standard" stack is one of the reasons. Its much easier to teach it "the hard way".
[1]: Obvious, shameless plug: http://padrinorb.com , now with more development speed.
With a single file it's easy to introduce some of the key concepts that are needed to understand Rails (especially for those coming from PHP).
If you're using the default stack, the number of dependencies you have drops quite a bit.
Those three gems recently caused me a world of pain. I've been in and out of Rails development since the 1.x versions (more hobby projects than professional development), and once getting going was as simple as 'gem install rails'. Getting the asset pipeline to work changed that totally - I get the advantages of the asset pipeline, and once you get it working and all your gem dependencies sorted it is fine, but it took me a while to get there.
As a recent Java refugee, one of the things I find most painful about Rails is its dependence on native code libs. It's really a lot of work to get the dependencies sorted out, especially if you have several platforms to support (say OSX for dev, and multiple Linux flavors for staging/prod).
One thing I learned (the hard way) is to heed the advice that "rvm requirements" offers. If you install the libs that it recommends before trying to install your gems, things will go more smoothly. This may sound obvious, but when you're installing Ruby, RVM, Rails, Apache, etc, it's easy to overlook the instructions.
If someone understood how bundler worked, there is NO reason therubyracer, twitter-bootstrap-rails, libv8, or any other gem should get in the way of upgrading (say for example) from Rails 3.2.5 to 3.2.11. `bundle update rails`, then check in your new Gemfile.lock
That should change nothing but Rails and rails' own upstream dependencies (not any of the ones you mention). And indeed it did that for me on a bunch of apps. If you're going up a minor or major Rails version, then your other gems (like say twitter-bootstrap-rails, hypothetically) might not be compatible with the new rails version, and you might have some dependency hell.
But to apply a security release, when you are on a maintained minor release (3.0, 3.1 or 3.2)? If you understand how bundler works, you are HIGHLY unlikely to have any troubles.
Right, but it DID happen. Updating the Rails version updated the versions of other gems too. I know what you're saying, but the reality was different.
And "being explicit" rather than "convention over configuration" really helps people make their own choices. When people bump into the limits of Django's ORM, for example they quickly replace it with SQL Alchemy, when they do something in Flask, they already know what the pieces they are putting together do.
Rails culture seems very "top down", i.e. people start learning and doing things by learning the stack as a whole and then about the options for individual components. This leads to "elegant solutions", but tons of pains for beginners that need to "swallow it whole".
I don't know which way is better, but I've always been attracted to the Python ecosystem because I like learning things "bottom up", e.g. playing with all the different pieces and then assemble them into a whole once I'm confident I understand them.
Your choice of stack is great, and it's great you're passionate about it but if you start acting like a giant dick about it you're actually dissuading people from getting more involved, and that's not a good thing.
All of this is pretty simple once you have preferences established, but figuring out those preferences can be enough to drive you back to something that, well, has less choices. (Like the aforementioned Django, although it has its own issues with setup and documentation.)
1) Beginners need to listen to one person's opinion and trust them
2) Learning about the people and community around your tools is paramount.
#2 will allow them to advance past whichever stack #1 places them.
There are, of course, other caveats. For example, when a beginner finds an answer to their question on stack overflow, but the example code uses HAML instead of ERB, they need to have a foundation deep enough that allows them to at least recognize the code without feeling lost (or use those "lost" moments as opportunities to educated them about that feeling, which is rather normal for a beginner in anything).
Etc.
When I started the Obvious architecture, writing an example app made it concrete and makes it a lot easier to explain particular details or structures to people wanting to learn.
People love examples.
I'm still working through Michael Hartl's tutorial, but plan to work through each of these afterwards.
How many parts of Rails can you swap out before it stops being Rails?
Maybe the simplest solution here would be to call the Prime Stack something different. Even "Rails Prime" would work. Just some nomenclature that says to people "hey, just so you know, what I'm going to talk about here is different than what 37signals is talking about."
The stacks in the article aren't very different and few of the comments here seem to reflect that.
Erb vs Haml? Not much of a switching cost, especially since they can be used in the same project without sweat. One is HTML with <% %> tags, the other is a less familiar nested syntax to generate markup.
Mysql vs Postgres? For most CRUD, the same Active Record queries pretty much work, and the shortcomings are due to Active Record being underwhelming compared to its alternatives. Someone that cargo cults Mysql vs Postgres probably isn't locking their schema/queries into one or the other because staying close to Active Record doesn't really let you do that.
Minitest vs Rspec? Tests would be annoying to rewrite, but testing layer differences don't really distinguish a Rails app. Especially since you can write almost line for line equivalent code in Minitest and Rspec.
Fat models & skinny controllers vs skinny models&controllers + service layer? Here's the first real difference on the list because it actually changes the design of the system, not some ancillary component.
So,
> How many parts of Rails can you swap out before it stops being Rails?
I think we can stow this question away until there are more divergent, popular alternatives to the default stack which I'm looking forward to in time.For instance, I think we will start seeing more deliberate functional designs that decouple models from Rails (to make testing not suck, for one). And I wish Active Record alternatives were far more popular in the Rails community.
Rails is meant to be modular, it just doesn't stop being Rails.
Thanks for this article, Steve.
This is a great compliment, thank you.
I mostly left deployment out because that's not part of Rails' domain: Rack lets us not care about that when building things.
When teaching rails, I always tell people to get familiar with the defaults first then try the alternatives and make an informed decision to switch (if at all necessary).
Perhaps Michael's book fills this space, but there may be an opportunity to write an e-book on the Prime Stack, or at least fill in some things the Rails Tutorial leaves out.
I started learning testing using rspec. Now I'm starting a new job where they use test unit for testing. The transition has not been too difficult because the difference between the two are too crazy.
If you pick one route and learn the basics, you shouldn't have too much trouble switching over to the other.
However, I think that Rails is not a good start for beginners in web development. On the one hand it's guiding you very well through its strick conventions and teaching you very good structuring your app (MVC- and OO-wise) but on the other hand all those abstractions and magic make you dumber. Without a big framework like Rails you try to think yourself how to solve a problem like getting the data from A to B. With Rails instead you just have to follow the respective Rails convention and voila you are ready to go. Finally, you learn Rails design patterns and best practices (or conventions) without understanding why you are doing this. And since the default stack is by far not the recommended stack makes it even worse. Because the newbie is in the beginning too afraid to leave the default track. Giving him the option "to just remove one line" to get to his preferred stack is the wrong answer because if there's a default stack people in particular the beginners assume that this must be the right way to do stuff and spent too much time fiddling around with ERB, MySQL, CoffeeScript, etc. Instead it would be better to offer a modular approach like Express, Sinatra, Web.py. I know that I can have the same modularity with Rails too but a beginner gets another message and Rails also wasn't meant being a full stack framework where -- we remember -- "convention is always over configuration" and thus also over modularity.
And even for advanced programmers I believe that Rails' time is over: the monolithic approach is so 2005 and I realize nowadays that I just want to start quickly something without an ORM, Coffee, etc. and decide later if I add those amenities.
Maybe we are facing a new generation of web development where full stack frameworks have no space anymore and David should rethink his Rails approach.
It was the opposite for me. I had been doing java and php web dev for a few years before rails was created. The first time I used rails (before the 1.0 release), all those abstractions were a revelation. I realized, oh, I've never seen software structured this well before, and it immediately expanded my understanding of how code should be structured.
"the monolithic approach is so 2005 and I realize nowadays that I just want to start quickly something without an ORM, Coffee, etc. and decide later if I add those amenities"
Software isn't fashion. First, in rails you can start quickly and not use an ORM or coffee. I've written a whole lot of web apps in ruby over the years. Many in rails and many in sinatra. In my experience, most of the times I used sinatra I eventually wished I had just used rails because I nearly always wanted many of the rails features over time and putting all the pieces together myself was not the best use of my time. There has only been one case where a rails app I wrote should have been a sinatra app.
"First, in rails you can start quickly and not use an ORM or coffee."
But a beginner can't and even for advanced people I wouldn't call the rampup time for a Rails app "quickly" anymore, those times are gone for a long time.
"I used sinatra I eventually wished I had just used rails"
Maybe you should give Express/Node a try -- the ecosystem paired with Node's modularity makes me much faster than with Rails and maybe you realize how slow you have been Rails, before.
Could you elaborate on this, please?
This is a gist from one earlier today: https://gist.github.com/be34c0a5666db0c83629
"it should send message to owner and shave whiskers from monkey. also, make my a latte."
That DSL seems like a bit much and I don't feel comfortable letting it do black magic things behings my back.
We have a dashboard app that must integrate data from several models into a single display that allow users manipulate the parameters to each specific model independently.
- erb for view templates - postgresql for database - rspec/cucumber for testing - skinny models, controllers, and a service layer