Rails Cheat Sheet
fly.io
fly.io
Out of those, I’d at least add the RuboCop [1] linter and the BetterSpecs [2] guidelines to this list. Both eliminated bikeshedding in the team and freed up brainpower to solve actual problems: the first one helps you learn intricacies of Ruby bit by bit right in the IDE and the latter one pushes you to write test in a specific style that’s easy to maintain and trust.
Factories are almost 100% responsible for excruciatingly slow test runs, since you have to rebuild the world every single test. Fixtures work perfectly fine and only need to be created once at the beginning of your test run.
For that matter, rspec itself is also a thoroughly unnecessary cargo-culted dependency when Ruby and Rails already bundle perfectly-serviceable, simple test frameworks.
You're generally trading speed for correctness in my experience. There is a time and place, of course, for this tradeoff, but we know how to parallelize specs and make test, in general, faster. Correctness is a whole different story.
If you're using FactoryBot for example, you can use `build(:taco)` to instantiate a Taco without persisting it to the DB. If you use `create(:taco)` instead, then yes, the Taco will be saved to the DB, as well as all its associations (if any). This can of course bloat up your test execution time if you're doing this kind of instantiation + persistence on every test.
FactoryBot docs generally use `build` in their examples, as this should be the default build strategy used for most tests, while `create` should only be used on cases where you actually need to interact with the DB.
I think people developing professionally and working with large code bases, reach pretty fast all the limitations of minitest. IMO, Minitest is great to test small libs, but as soon as you need to refactor a lot of specs or use other stuff like Factories, then rspec is the tool. No cargo-culted. It is just the best and more complete option.
The number of cases where applications sanely used features of rspec that couldn’t have been done equivalently and just as easily (and significantly less confusingly) with minitest-based tests are few and far between. And these are easily outnumbered 20:1 by insanely bad test suites that abuse rspec and thoroughly mock everything in their tests, resulting in tests that a) are so brittle they fail on any non-trivial refactor, and b) couldn’t possibly preemptively catch buggy behavior.
I have quite literally never worked on a Rails application that used minitest and which was forced to abandon it due to unmet needs.
I've worked with some devs who were not old battle-scarred greybeards who jumped on EVERY rspec feature because they were there and in a misguided attempt to DRY their test code well beyond reasonable limits.
So I feel you here.
But FactoryBot does allow fixture-like speeds with in-memory .build()'ing. Too few people use it, and too few have succumbed to a preponderance of tests being full-on integration style.
Ruby (and Rails, and rspec) all IMO require a lot more good guidance and wisdom on what NOT to use than other ecosystems I've used.
The "magic" (convention over configuration, autoloading, metaprogramming, etc) makes it difficult to know what methods are available to use. I end up over-relying on the official docs, which are of inconsistent quality. One example: api.rubyonrails.org lacks code examples, doesn't usually state what a given method returns, and many entries are outright blank.
Editor integration could help, but feels lackluster. With TypeScript in VS Code, hints come up as I write. I can hover anything to see its type, methods, and source code. With Rails, I can poorly approximate this behavior with a collection of half-functional community extensions, or I can buy and use the slow, bloated RubyMine IDE.
Rails enabled me to build my product, but my experience doesn't match the love I hear from other devs. I wish I knew how to make it click.
The Rails Guides [1] are quite good (and much better than the API docs, even for the same topics). The "Getting Started" guide, in particular, was my first intro to Rails, and it's what convinced me to go all in — I built my entire prototype by just following along the guide, seeing what they were doing with their toy app, and then trying to whatever similar thing I needed in my app.
Coming from Python, the magic was distasteful to me, too. Rails adds a ton more magic on top — so, eventually, when I set aside Rails and just spent time with Ruby (writing scripts or what not), I realized I loved Ruby the language much more than Rails the framework (and all its baggage).
Stripping Rails down to its API-only mode (though it was a bit rough around the edges last I tried) got me closer to the Ruby of it all. Sinatra turned out to be a delightful little framework (though sadly I never got a chance to use it much). And, even though I've now moved on from Rails, I still like Ruby as a go-to scripting language — it makes it fun and easy to throw together a quick shell script or some data analysis, and it's very friendly to a functional programming style.
I guess what I'm saying is: You're not alone. Many people in the Rails community agree that there's a ton of hidden magic, sometimes too much [2]. But underneath it all is a delightful programming language.
[1]: https://guides.rubyonrails.org/
[2]: The docs for the Rails routing layer, Journey, are my favorite example of this: https://github.com/rails/journey#label-SYNOPSIS-3A
I also wrote stupid code first in my own version, and copied + pasted to chatGPT, asked it to improve it, or rewrite in ruby on rails style. And wow!! The rewrote version even went with explanation.
Beside that, you can use Rails console to test.
However, many times ruby libraries will use dynamic programming and method_missing to define methods on the fly… this makes it really hard to figure out what methods are actually available.
For that reason, I try to never use method missing to define core functionality in ruby, and hate when other gems do it.
E.g.
def method_missing(name, \*args)
if name =~ /^has_/
has(name, *args)
end
super
end
def respond_to(name)
if name =~ /^has_/
return true
end
super
endThis won’t work even with respond_to being defined
some_object.methods - {}.methods # or some other "parent" class/object
This does set subtraction to remove all the "core" object methods from your some_object methods, so you can see just what's unique about that object. For example, comparing one of my services with a parent Service class it inherits from: irb(main):017:0> PaypalService.methods - Service.methods
=> [:capture_invoice_funds, :months_price, :client, :create_prepay_invoice, :order_info]
instead of listing out the 187 methods that PaypalService has that it inherits from Service and every other parent object up the line, which is usually a surprisingly long ancestor list in any Ruby on Rails class (even POROs!).There are a TON of useful methods like this that I'd recommend getting familiar with, which makes exploration and discovery of code incredibly fast and efficient. You can find them all with the same trick: by using `methods` on any method. :)
irb(main):043:0> PaypalService.method(:months_price).methods - {}.methods
=>
[:<<,
:>>,
:arity,
:curry,
:source_location,
:call,
:parameters,
:original_name,
:owner,
:receiver,
:super_method,
:name,
:unbind,
:comment,
:source]
Some of the more relevant ones: irb(main):037:0> PaypalService.method(:months_price).arity
=> 1
irb(main):038:0> puts PaypalService.method(:months_price).parameters
req
n_months
irb(main):039:0> puts PaypalService.method(:months_price).source
def self.months_price(n_months)
case n_months
when 1
9.00
when 3
24.00
when 6
48.00
when 12
84.00
else
raise "Invalid month prepay: #{n_months}"
end
endIf you haven’t tried it in a while, it’s quite good on Apple’s arm chips. Doesn’t feel slow at all, and the battery hit is negligible.
The whole just fire up an interactive session or rails console is probably the last thing I want to do but probably the only way to diagnose or figure out how things are truly working. What monkey patches are in the mix, what libs override methods I set, etc.
For me, Ruby is one of those programming languages that obviously takes a different programming approach and mindset that I don’t have. I don’t think Ruby is bad but I know it isn’t the tool that fits my skill set.
When deciding on the language to learn, I really really wanted to go with Ruby and then transition to Rails. But it seems like educational materials are currently lacking, most of the tutorials on YouTube are outdated.
When investing in eco-system, I never looked at the availability of jobs. But when comparing say JS/TS vs Ruby, there is clearly a viable route to learn it as a beginner.
The downside is that there is a lot of trash and low quality materials as well as inhibited complexity - but after some time its not such a problem to sift through the noise.
Unfortunately they slept on front-end for too long but seeing a resurgence with a few startups.
I think Mastodon is actually using it.
What alternatives would you propose? Usually when people are surprised by this, digging in reveals that they don’t really know what “client-side rendering” means.
Rails 3 was released in 2010
Rails 7 was released in 2022
Considering the speed of change in JS and CSS in 12 years I am pretty haply with only 3 big changes.
Twitter started with rails and constantly went down. Rails was blamed for the downtime, perhaps unfairly.
Many startups took advantage in creating apps fast with RoR.
Now that (especially with TypeScript) JS is good enough, browsers and JS engines improved a lot, I start to see less advantages in not using js/ts both for client and server.
There are certainly new compelling projects like Sorbet to add type checking, and the ecosystem itself is very mature, it's just that the average codebase is not going to live up the experience you might have with a brand new one.
Where, for example, in 2015 any SaaS or API would provide a gem (lib) to interact with it, today it's no longer the case. Modern PSPs, storage, search engines, etc almost all lack an official gem. Often lack even a third party one.
And where back in 2015 there were popular systems in Ruby outside of rails, all those are crumbling and/or gone. Jekyll is no longer the go-to static site manager, Chef and Puppet no longer the obvious devops tools. And Ruby is completely absent from emerging technology (AI, blockchain, WASM, data science, etc).
I'm afraid Ruby is becoming a legacy language and Rails' will be a legacy framework soon. Where the bulk of the Ruby jobs are to keep old stuff running and maintained. Afraid, because I'm still primarily Ruby developer.
And secondly because we're now at that pendulum swing, where people realize that "write once run everywhere" has severe downsides, easily overcome by writing software in a language or framework that fits the usecases best.
The latter is easily seen in the common practice of splitting out the UI in webdev. And in using microservices. Rails stubbornly goes against this common practice (which isn't a value call, just an observation) and as such, places itself outside of what we commonly are used to .
The former is seen in e.g. typing or type hints being added everywhere, languages getting support for functional programming, generics, interfaces, class inheritance etc.
Sure, jekyll is no longer the new hotness, but I don't see a market shift towards a single tool. There's just the usual fragmentation. Hugo, next, none of them is consensual.
Ruby was one of the primary targets of wasi. It compiles to WASM since 3.2 officially, but work started more than a year ago. Ruby in the browser is possible.
Sure, not everyone is targeting Ruby. But I don't see new products targeting new stuff either. Seems that there are less oficial SDKs nowadays, usually targeting the top 3 tier 1. And that's fine, and means little about Ruby in the end.
There are new books written, new conferences organised, Hanami 2 is out, new organisation created by companies to support Rails docs and marketing, Phlex is a nice way to work with views, someone started to work again on Camping, someone else is working again on a new portof shoes.rb
More content is created everyday: see for example dev.to starting to have beginner articles. A very good sign.
now regarding your fear, what I can say is act like your fear is real and it will be in some way or another.
Those aren't all gone. But in the grand scheme of things, Ruby, and Rails' have been relatively decimated. There now are about twice as much (web) devs as back when it started but Rails nor Ruby is hardly twice as big. It's been going strong, solid, flatline.
I wrote a longer post, a while ago, with sources and numbers on this. It was featured on HN https://berk.es/2022/03/08/the-waning-of-ruby-and-rails/ (and frankly, it's going faster and is worse than I predicted back then)
From where I am, things don't look the same as you are describing them:
1. https://newsletter.shortruby.com - it is younger than 1 year, but you can find a lot of new content there: new podcasts were released in the last 12 months, new conferences were organized, and new books were announced. When I say new = it means never done before, not new editions.
2. https://rubyandrails.info - while it is not a comprehensive directory, it has a lot of resources. Indeed the youtube courses section is empty, but that is due to my lack of time, not because they are missing
3. Also, take a look at this https://rubyconferences.org
I don't have time to debate everything you wrote in the article, nor do I think I can change your mind.
I also don't know the future. Maybe you are right, maybe you are wrong. I choose to believe that Ruby is not dying and act like it: launch a newsletter, start to write a book, and prepare some more projects.
can you explain this a bit more? it seems to me that test coverage and typing solve different problems.
Give this a watch: https://www.destroyallsoftware.com/talks/ideology
Types do not remove the need for unit tests, but they relieve some pressure from them.
I think that it's syntax, or what "beautiful ruby code" looks like, is significantly different from most other languages, making it more off putting to pick up or switch between.
More here: https://www.artima.com/articles/the-philosophy-of-ruby
But what DHH does/did with it for Rails is of a different order.
There, often, "beauty" is in the way. Hundreds (or thousands) of methods magically appearing from nowhere on a Record, by inflecting a database scheme runtime. Thats neat and all, but I'd very much rather just explicitly write getters and setters. It's not as if (with autocomplete) such things are a time sink.
You can import the joyful drive of Ruby into your RoR codebases. I've worked on plenty of rails codebases that were a pleasure to work in. Far more than any other web framework I've worked with.
I consider a concerns to be more complex and unexpected versions of a Module.
I consider "render @foo" to be just an incomprehensible version of the explicit "render_partial("the_name", ...)" And so on.
All of these have bitten me many times, oft in production even. Many of these caused me and my step debugger hours of wading though deep stacks of method-missing or runtime code definitions.
I think this turns people away from Ruby (and is what Ruby people love about Ruby). I'm not a fan of Go, but people say they enjoy writing Go, which looks very different from Ruby.
> Once you get experienced in rails, you primarily glue things together
Both of these are equally true for most other languages with mature ecosystems. IMO the speed of Rails development reflects the speed of Ruby development in general. The standard library has everything, all kinds of little methods for all kinds of little things. Combine that with ActiveSupport extensions and you can do everything.
Date.today + 3.years + 2.days
234.in?(2..235)
[1,2,3].all?(&:odd?)It's not a mainstream one, and frankly the main reason to learn it in practice is rails. There's a big cold start problem there.
You have to convince people to like both the language and the framework at the same moment of decision, in addition to committing to learning both at once.
That's just always going to be more difficult than selling only a framework to people who either already know, or see more value in learning, a more mainstream language like JS, Python or Java.
I think this is the biggest reason it's remained niche.
It doesn't struggle. It's just not the hot new kid on the block anymore. It's a 2013 Toyota when the rest of the world is all about EVs.
Rails is, as an ecosystem, not lacking much. There's not much room for innovation. It's mature, it's stable, it's scaleable.
Personally, I value my sanity, so I stick with an older Toyota. I don't need panel gaps and batteries exploding. I just wanna build stuff.
That is debatable. Both GitHub and Hackyderm are large-scale Rails deployments, and both share a DevOps engineer (Nóva) who I've heard complaining about Ruby DevOps at least once. Twitter was forced to abandon Rails (being the poster child for Rails at the time).
This is not a reply to you, but I decided a long time ago that I will not let this argument about scalability remain with response.
If you have already decided not to try Ruby on Rails or any Ruby framework, say so.
It is ok to have different preferences.
But this thing with Ruby needs to be more scalable is a very weak argument.
Here is why:
In the tech industry, it is not uncommon to come across companies that opt to rewrite their tech stack in a different language, often citing scalability as a reason. While this argument holds some merit, it's worth noting that scalability is a complex issue that affects all web frameworks, not just Ruby on Rails. Therefore, criticizing Ruby on Rails solely based on scalability may not be a strong argument when you take into consideration the idea that there are very big companies build with it.
- Ruby on Rails is scalable for 99.999% of all startups created with it. This 99.999% will die for any other reason but not because of their tech stack. Again the same can be said about any other web framework. Of course the 99.999% is just a made up number based on the fact that there are so few companies failing because of their tech stack scalability.
- Twitter and Github are maybe in the top 0.0001% of web apps when thinking about scale or usage. Hope you (the reader of this comment) will create a startup that will be so successful in terms of scale. But the chances are that with 99.999% confidence, you are not them, and the chances to create a product that will be like them are slim.
- The problems at scale are not only technological but also organizational.
Now open this list https://www.ycombinator.com/topcompanies and this list https://www.ycombinator.com/topcompanies/public and try to check how many of them are using Ruby. There are quite a few in this top. It scales or else there should not be any big company using Ruby there.
You are right of course, but not for your stated reasons. Essentially RoR doesn't scale. RoR scalability is a meme, anything else scales much better. From node to PHP, they all can do much more on much less hardware. To achieve hyperscale with RoR you have to throw absurd hardware with layers upon layers of load balancers in front of it.
But I'd argue that it doesn't matter at all for a startup. Like you said most won't ever reach the point where they need such a thing. But they all benefit quite dearly from the excellent developer velocity provided by RoR.
> most won't ever reach the point where they need such a thing
I considered covering this argument in my gp comment. What if your startup does grow to the scale where it becomes an issue? Do you suspend new user signups until you can do the rewrite? Or do you just let things keep spiraling, like GitHub? Because by choosing RoR you are making an assertion up front: our startup will never scale beyond X users (because you're never going to get buy-in for a rewrite).
I disagree with:
> Because by choosing RoR you are making an assertion up front: our startup will never scale beyond X users (because you're never going to get buy-in for a rewrite).
How can this be true when we know that Shopify, Gitlab, Github and all others are using RoR.
Here is a more concrete scale[1]:
> We served 75.98 Million requests per minute to our commerce platform at peak. That’s 1.27 Million requests per second!
Is that a bit enough limit for you?
Here is more:
> We achieved 99.999+% uptime while averaging 3 Terabytes per minute of egress traffic across our infrastructure [2]
[1] https://twitter.com/shopifyeng/status/1597983926126977024
[2] https://twitter.com/shopifyeng/status/1597983918900510720
By the time you reach this problem, you'll have an army of developers to take care of this.
I've worked for three successful startups that started on PHP that couldn't scale the PHP code bases with their customer growth. All three rebuilt on Rails and are still in business and on Rails today.
Another startup where I'm very close with the founders they are on Node and they say the system is "a complete dumpster fire". They wish they had built on anything else.
The company I'm with now is primarily a giant Rails monolith and we have 100s of thousands of users connected at any given time. Our biggest bottleneck isn't Rails it's Postgres. We are dealing with billions of rows and Postgres isn't really even the problem. The problem is our data model wasn't designed in a way that would allow sharding/partitioning. Even this isn't an intractable problem. We create updated schemas, migrate, backfill. What we don't need to do is leave Rails "because it doesn't scale".
Most companies that moved off of Rails because of scalability either don't actually understand scalability or it was 15 years ago and they were on Rails 2 when it was still immature.
Most battle tested languages and frameworks can be adequately scaled if you have the right devs. I think that a lot of the reason we see system rewrites due to scalability is more because startups tend to hire developers that like to "build new things fast" and those aren't necessarily the same as the developers that have already dealt with 1M+ users at petabyte scale.
Once you become that successful sometimes the solution is to bring in people that have solved these problems of scalability previously. This sometimes results in rewrites in whole or in part because their experience is on a different stack.
In one of the PHP to Rails (for scalability) projects I worked on I was contacted quite early in the process. I am a longtime friend with one of the business owners. The existing developers could not scale the product horizontally and were already on the largest instances available at the time so there was no more ability to scale vertically.
They had hired a new technical lead that had extensive experience scaling Rails, but most of the team only knew PHP. My team did both Rails and PHP consulting at the time and we were hired to speed up the rewrite in Rails while the PHP devs were doing a mix of trying to keep things running and learn Rails so they could support after the rewrite.
The first thing I did was review the existing PHP codebase. I then advised that they not switch to Rails because I firmly believed that in about 3 months the PHP version could be refactored to allow for adequate horizontal scalability. The full rewrite was expected to take a little over a year.
The owner agreed that my assessment was probably right, but he still opted for the rewrite because the new lead was competent at scalability and likely would have quit if they stayed on PHP.
https://github.blog/2023-04-06-building-github-with-ruby-and...
Rails (and Ruby) make tradeoffs, or just inherently have downsides that many newer frameworks, libraries and languages solve, or solve differently.
For me, the most prominent are Rubys' dynamic typing and Rails' black magic. But my biggest gripe is how Rails lacks a space for business logic. Sure, you can bolt something on yourself. Or just throw it all throughout the http, storage and rendering layer willi-nilli.
This has caused so many of the codebases i worked on, to be unmaintainable, untestable and therefore legacy that I can certainly blame it on the framework.
I've worked on many go, rust, typescript, php and ruby-no-rails systems to be ever more certain about this. Many frameworks lack this area, and almost all quickly degrade into spaghettis. I've come to like DDD, hexagonal and clean architecture for solving this. Most are perpendicular to Rails.
So, i'm certain that contributor to the lack of popularity of Rails is how hard it is to build maintainable, testable, clean projects in it.
The latter, in my experience, is best. It's a "no framework" setup really. Where you organize code according to a "framework" that's no code, but architecture, conventions, rules, and design patterns. Where code reuse goes via libs, put aside behind abstractions.
I consider the question "what framework offers good architecture (for maintainability, DDD or business logic)" a somewhat wrong question because in it lies a strong opinion of what a framework is. And such frameworks are counter to what you want: you don't want these frameworks.
You can literally create a directory called app/my_actual_app and put all your business logic in there, Rails will even autoload it for you.
IMO it’s the sudden change from the “we’ll hold your hand every step of the way and offer tools and workflows for everything” web part (controllers, routing, ORM) to the “go and build your goddamn app” dealing with business logic. So many (especially new) devs try to stay in the cozy zone of having a nice name for everything at all costs, so they try to cram everything into “services” and “decorators” and “interactors” (yuck) and they’ll build business logic out of callbacks on ActiveRecord models and overload the poor things with dozens of “concerns” instead of, you know, going and building a goddamn Ruby app.
This recent article has some alternatives https://blog.appsignal.com/2023/05/10/organize-business-logi...
Their main argument against the first piece is:
> One problem with fat models is that unless you are really disciplined in your code hygiene, they can tend towards an assortment of code smells
And I wholeheartedly agree. With the addition that "code hygiene" if not enforced or encouraged, is always one of the first victims under stress. And every (successful) project will see such stress.
With Rails you have to spend extra effort to keep doing "the right thing", whereas is should cost cost less effort to do that, and extra effort to "do the bad thing".
Six years ago (2017), not recently.
Different strokes I guess.
Magic is a beautiful term for what Rails does, because just like a magician’s tricks, it’s possible to have a full understanding of what’s going on. It’s not as if Rails acts randomly.
It’s magic when the only way to know is to be told. Which is, to me, a nonstarter for software.
Okay, but what if instead a library was designed to be more reasonable and intuitive, such that you didn't need to dig through its source to understand what you needed? This is the problem with "magic".
> most people were using .NET or Java which were largely closed source and PHP
These are programming languages. Rails is a web framework.
Why do similar articles or headlines seem to come up at the same time on front page? e.g. there is another article on Rails that happens to be front page right now that is seemingly otherwise unrelated (the other article is called The Rails Doctrine).
Just not my cup of tea I guess.
For me, the responses are fascinating, because many of the things people seem to love about rails (and ruby) are the ones that I hate. It's not that you're not allowed to like those things, by all means feel free - I'm just perplexed.
Fwiw, I regularly use ruby for work (with and without rails) and I'm fairly competent with it. I just think it sucks.
i code in go these days. i have done perl and java and some others, started with c, did a bit of python along the way. ruby was always my favorite language. so expressive, so easy to be clear while being terse. i've spent months of my life shortening (my own) verbose ruby code. i switched to go only because of the execution speed and the compilation, a few years back the comparison was not even close. i don't know if i would like to go back to dynamic language... but i found ruby to be such a beautiful language.
p.s. this was big when i was leaving ruby: https://rubocop.org/ maybe there is a replacement now, but maybe it would have changed your view.
I'd call promises in Javascript complex. A block is Ruby isn't complex, it's just weird if you're new to the language.
I don't say this to be reductive. I believe there are two ways to approach a programming language: either from the formally-correct, highly-specified point of view; or from the communication and linguistics point of view. Ruby has a terrifying formal syntax precisely so that it can be extremely comfortable if you can get yourself to ignore the formality.
The flexibility fits my brain extremely well, and most of the time the theoretical syntactic complexity just isn't an issue.