Code Monkey home page Code Monkey logo

Comments (30)

searls avatar searls commented on June 7, 2024 87

A lot of the Rails ethos went into Standard itself, in that I wanted to help people get the safety and consistency of a great linter/formatter, but spare them the time spelunking docs to reverse its often unorthodox & draconian defaults. Standard also prioritizes forward-compatibility and tends not to break or misbehave after upgrades when compared to RuboCop, because the configuration exposed to users is so minimal that there's not much that can go wrong.

The reason I wanted to create Standard was that, as a consultant, I visited so many teams who responded to the mere existence of rubocop.yml's massive, configurable ruleset like it was a mandate to debate and customize every single rule—even if they otherwise wouldn't have cared—distracting them from the work of whatever app they were building. More importantly, the net effect of RuboCop's ascent was to drastically increase the barrier of entry to new codebases, as the way its rules were enforced varied so wildly from team to team. As somebody who juggles a bunch of apps, a huge selling point of Rails has always been to decrease the productivity cost of switching between apps, but the way teams tend to use RuboCop in practice makes it much more painful to switch context. I created Standard to try to remedy this (jokingly calling it "bikeshed-proof").

One problem with using adapters for linters, however, is that the generated files have to be autocorrected, assuming they can be, and I could see that being brittle.

Funny enough, I just noticed earlier this week that the app generated by rails new is already basically Standard-compliant! Only a handful of minor diffs result from running rake standard:fix against a new Rails app. This is a valid concern, however, and something worth testing in the course of whatever PR might introduce this. My suspicion, though, is that because Standard prioritizes enabling rules that can be enforced safely and universally, it's unusual to find normal-ish Ruby for which this would be a problem. Whenever a rule might not make sense in a particular context, we tend to err on the side of disabling it altogether.

Anyway, here's what I'd suggest, in order to make the default Rails experience as smooth as possible for the majority of users without forcing a single mandated style: ship Standard enabled by default with new Rails apps but make it easy to "eject" Standard's config into a customizable rubocop.yml users can subsequently run with RuboCop directly, as a lower-level tool. This way, a user wouldn't need to start tracking changes to a rubocop.yml file until the moment they actually care to, saving them ownership of the upgrade headache of keeping it up-to-date with RuboCop itself. One poorly-advertised feature of Standard is that by including an opinionated configuration of RuboCop's ruleset in the gem, upgrading Standard is relatively seamless compared to upgrading RuboCop, where minor releases often change how particular rules are configured.

(Unsure your appetite for this, but Rails could go further and ship a new wrapping CLI command like rails lint or rails format that would have Standard configured as the default provider and make it easy to drop down to RuboCop or maybe even possible for rufo/rubyfmt/prettier to publish gems to serve as alternative providers.)

from rails.

justinko avatar justinko commented on June 7, 2024 47

I don't think this will be the mother of all bike sheds, but the most prolific creator ... akin to rails new house --bikeshed

Would you consider adding standard? The stats look pretty good. Giving up that single quote felt like coming to the alter. At the very least, it'll consolidate and centralize all the bikeshedding to @searls

from rails.

tenderlove avatar tenderlove commented on June 7, 2024 41

+1 on importing Standard. I've been using it for a while, and the stuff it makes me change is very non-controversial. Its formatting rules let me write "normal Ruby". I've mostly changed my Vim config such that Standard doesn't have much to say to me anymore.

Additionally, Standard comes with an LSP so you can attach your editor and have it fix everything during editing. I'd highly recommend giving it a try!

Anyway, Standard is good and I'd be happy to foist formatting bikeshedding on to @searls rather than maintaining our on Rubocop rules.

from rails.

dhh avatar dhh commented on June 7, 2024 20

I'll run Standard on our codebases and see what it flags. I want to make sure it remains very light touch. The standard Rubocop setup is very far from something I'd like to see applied to my code.

from rails.

dhh avatar dhh commented on June 7, 2024 15

Thanks for your work on RuboCop, @bbatsov! It’s a testament to the tool you’ve built that it’s flexible enough to accommodate all these different styles. To me, that’s a feature not a bug.

Many people might enjoy gofmt, but I find it very out of spirit with Ruby to cram down one style down upon all. Ruby is a far more expressive language than Go, and having the power to develop your own style is a luxury.

from rails.

dhh avatar dhh commented on June 7, 2024 13

Also note, I had a good long discussion with @searls about Standard. It's a great project, and if it fits your sensibilities, I'd encourage anyone to check that out as an alternative. But it was a fair ways off my aesthetic preferences, so wasn't going to be suitable for the omakase menu.

from rails.

harry-herskowitz avatar harry-herskowitz commented on June 7, 2024 12

Standard rules!

from rails.

northeastprince avatar northeastprince commented on June 7, 2024 10

Standard is awesome and I definitely prefer it over RuboCop. Mainly because RuboCop is either way too strict or over configured to not be.

from rails.

bbatsov avatar bbatsov commented on June 7, 2024 10

RuboCop's author here. (a couple of people pointed me to this ticket) I'm happy to hear that @dhh considers using RuboCop for Rails and I understand the misgivings some people have about that. Just wanted to mention a couple of things that seem to be a recurring theme in "adopting RuboCop" conversations:

  1. RuboCop doesn't force you to use the bundled configurations and in the spirit of Ruby it actually encourages people to create their own depending on their style preferences. Even Standard is essentially a RuboCop configuration, which speaks to the flexibility of RuboCop. I noted last year in the plans for the future the following:

Organize cops into some “presets” that would address the common complaint that RuboCop checks for way too many things out of the box. Think of this as something like an “essential”, “standard”, “community style guide”, “github”, “rails”, “all-in” and so on configuration bundles that enable different cops. It’s not like you can’t do this today, but probably shipping this out-of-the-box would simplify the setup for many people. There are plenty of interesting ideas to explore in this direction.

If someone wants to help make this is a reality faster - you're welcome to do so! In the mean time I think DHH's plan to start with a minimal config that he's comfortable with makes perfect sense.

  1. Having One True standard for Ruby code kind of goes against the spirit of Ruby. (I know that's kind of controversial coming from the author of a Lint tool 😅 )

There are so many Ruby linters/formatters today already and some of them have existed for over a decade, so I don't think it's the lack of tooling, but rather the lack of will to actually get where some people want to the community to go.

I think that adopting an universal formatter/code style 30 years into the existence of a language is unlikely to (fully) succeed if it’s not driven from the top (Matz). There will always be strong opposition to whatever we decide (as community), as people have built strong preferences at this point and they’ll need extremely compelling arguments to change them. Change is hard, and no one really wants to deal with it, especially if they don’t have to.

Everyone wants to emulate Go, but gofmt succeeded mostly because it was pushed from the top, pushed from the start and everyone was expected to use it. I’m reasonably sure this ship has sailed for Ruby. I don’t know how successful the similar projects for other languages are, but my guess would be they aren’t much more successful than Ruby’s RuboCop.

I know that Prettier (a JavaScript formatter) is quite successful and very widely used, but it’s also configurable to some extent and it didn’t really propose anything novel or controversial in terms of formatting. That’s why I think that the only way for a code formatting tool to gain much traction in a community with some established traditions would be if it’s aiming to enforce something relatively close to what people are doing currently.

By the way here's a excerpt from RuboCop's philosophy:

Early on RuboCop aimed to be an opinionated linter/formatter that adhered very closely to the Ruby Style Guide (think gofmt and the like). In those days cops supported just a single style and you couldn’t even turn individual cops off. Eventually, we realized that in the Ruby community there were so many competing styles and preferences that it was going to be really challenging to find one set of defaults that makes everyone happy. Part of this was Ruby’s own culture and philosophy, part was the lack of common standards for almost 20 years. It’s hard to undo any of those, but it’s also not really necessary.

The early feedback we got led us to adopt a philosophy of (extreme) configurability and flexibility, and trying to account for every common style of programming in Ruby. While we still believe that there’s a lot of merit to just sticking to the community style guides, we acknowledge that Ruby is all about diversity and doing things the way that makes you happy. Whatever style preferences you have RuboCop is there for you. That’s our promises and our guarantee. Within the subjective limits of sanity that is.


At any rate I'm here to help with whatever I can.

from rails.

harsh183 avatar harsh183 commented on June 7, 2024 4

+1 on having a very minimal rubocop shipped in with Standard. This helps maintainability with the automatic fixes using rubocop -A and quickly teaching many rils good practices. Editors hook onto rubocop quite well too.

from rails.

zzak avatar zzak commented on June 7, 2024 4

I've taken a very simple path to adding standard to the Gemfile, and explained my thoughts on linting other options and generators in #50478. 🙏

My guess is we need to decide:

  1. What the default linter should be 🚲
  2. Should it be configurable (other than disable)
  3. What to do with other generated code, like scaffolding, migrations, etc

from rails.

zzak avatar zzak commented on June 7, 2024 3

This reminds me of an idea I saw floating around to have there be an option to configure a linter on rails new, so there could be an adapter where people can bundle whatever linter they see fit (probably in order to help reduce distractions).

One problem with using adapters for linters, however, is that the generated files have to be autocorrected, assuming they can be, and I could see that being brittle.

Are you able to drop standardrb into a .rubocop.yml and it Just Works?

from rails.

Austio avatar Austio commented on June 7, 2024 3

Have had this discussion a half dozen ways to sunday, if you don't use something like standard that is no config there is a very good chance that you will end up with something that people debate hours over. @dhh personal preferences aside it will do more damage to have two standards here that the community has to pick from over integrating the already existing standardrb which takes care of so many useless and no-value decisions for teams.

from rails.

dhh avatar dhh commented on June 7, 2024 3

Taking about “damage” over the inclusion of Rubocop with a set of overridable defaults is hyperbolic and offers no convincing argument to me. Nobody is stopping you or anyone else from using Standard, and it’s actively against what I believe is in the best interest of this language to enforce one uniform style guide upon all. That’s something meant for Go. I love the fact that we can have different stylistic dialects in Ruby, yet collaborate on tooling that helps individuals and teams enforce their own decisions.

from rails.

jamie avatar jamie commented on June 7, 2024 2

Thoughts on adopting rubocop-rails-omakase on rails itself, for consistency/dogfooding?

I ran a quick test adding the dependency and then removing duplicate rules from the rails .rubocop.yml, summary is 3254 files inspected, 20831 offenses detected, 11691 offenses autocorrectable with a breakdown like:

  28 Layout/CaseIndentation
 106 Layout/SpaceInLambdaLiteral
18448 Layout/SpaceInsideArrayLiteralBrackets
  25 Layout/SpaceInsideArrayPercentLiteral
   1 Layout/SpaceInsideReferenceBrackets
1835 Style/PercentLiteralDelimiters
  63 Style/StabbyLambdaParentheses
 163 Style/TrailingCommaInArrayLiteral
 162 Style/TrailingCommaInHashLiteral

So just whitespace, trailing commas, and a few delimiter/parens switches.

I know those kinds of bulk changes add a bunch of noise, but I've had success with adding the relevant commits to .git-blame-ignore-revs (at least for the safe autocorrect changes) - Github picks it up automatically and otherwise it's a global git config to get it to ignore locally.

edit: also worth mentioning, the current rubocop config explicitly differs from rubocop-rails-omikase on Layout/IndentationConsistency, Layout/IndentationWidth, and Style/RedundantPercentQ, the above stats were retaining the current config.

from rails.

dhh avatar dhh commented on June 7, 2024 1

Published https://github.com/rails/rubocop-rails-omakase/ to serve as a base for this. If anyone would like to work on a PR that configures new apps by default with this style set, creates the default rubocop.yml file, and creates the bin/rubocop binstub, please proceed and assign to me.

from rails.

zzak avatar zzak commented on June 7, 2024 1

@jamie I think the rubocop rules for rails/rails are intended to fit the style of the framework and libraries, not Rails applications. These are serving two completely different purposes IMO.

from rails.

jamie avatar jamie commented on June 7, 2024 1

As a default? meh. Anyone who cares will apply their own config anyways.

(But it'd be swell if there was a config option, so I could rails new --rubocop=standard or rails new --rubocop=rubocop-shopify or whatever, but the generator would need to know what files to use and that'd maybe be better as a separate gem? If I can steal some time later I might just try to work that out.)

from rails.

ryanseys avatar ryanseys commented on June 7, 2024 1

I agree on the premise that the style of your files is a personal choice and that should always be configurable. I've never been a fan of standard for that reason.

Not because I disagree with its style decisions, but because I disagree with the decision to not allow personal preferences / changes.

Putting all style decisions aside, the entrypoint to formatting has not yet been standardized in Ruby / Rails so there's an opportunity there to improve.

Rubocop is the strongest suite of tooling that the Ruby and Rails community has to offer to itself for solving the problem of how to format, so the next step I believe is not to decide for everyone what all code should look like, but instead to arrive at a standard way to format an entire Ruby project to follow whatever the maintainers believe to be their agreed upon style.

rails fmt seems like a good starting point, and maybe someday we will get ruby fmt ?

@kddnewton 🤔 perhaps this has been discussed at the Ruby Core level now that the parser is stable and FAST? 🏎️

from rails.

zzak avatar zzak commented on June 7, 2024 1

Based on our discussion here I've opened #50486

edit: @codergeek121 I saw you also work on a similar branch, happy to add you as a co-author 🙏

from rails.

dhh avatar dhh commented on June 7, 2024

Should also consider adding enforcement to a git pre-commit hook.

from rails.

zzak avatar zzak commented on June 7, 2024

@dhh I think that approach makes sense, not sure about pre-commit hooks as I often let my editor do the formatting and catch any mistakes in CI -- but I can see that could help adoption for a team regardless of editor config or functioning CI.

This omakase style is automatically included with new Rails 8 applications. But if you're running an earlier version, you can easily add them yourself.

Did you intend to physically include the style somehow, or is dropping that in the Gemfile.tt sufficient?

In the latter case, I think that a PR to configure rubocop with the rubocop-rails-omakase defaults is about the same amount of effort as my last PR.

That resolves my first two questions from before, but still curious if there is any idea about:

What to do with other generated code, like scaffolding, migrations, etc

Maybe that is out of scope for the first iteration, but the moment someone runs bin/rails g whatever that generates invalid rubocop rules they have to --autocorrect-all and that will prevent them from committing if that hook is in place. (I'm assuming you don't want the hook to autocorrect on commit).

from rails.

jamie avatar jamie commented on June 7, 2024

@zzak indeed, I was talking the other way - add inherit_gem: { rubocop-rails-omakase: rubocop.yml } to the rails/rails rubocop config, and then dedup the rules. On the theory that if we get folks using a particular style in their applications, having the same baseline config when contributing to the framework would be better developer ergonomics.

from rails.

ryanseys avatar ryanseys commented on June 7, 2024

Thoughts on rails fmt ?

from rails.

dhh avatar dhh commented on June 7, 2024

Ideally, yes, I’d prefer for the rails framework to follow this style too. But not willing to make development work with blame or whatever harder in service of that goal. So unless there’s a path forward with very little to no trade-offs on that front, I don’t think it’s worth messing with.

Generators on the other hand should absolutely be brought in line with this default style. I believe they mostly are since I wrote and polished the majority of them. But if they’re not there 100%, we can get them there.

from rails.

Austio avatar Austio commented on June 7, 2024

The damage isn't hyperbole, it is the real time that teams will waste debating and configuring artistical and aesthetic rules vs having a clear established standard. Standardrb has already set that so you don't have to deal with the debates, only pick a path for the things that rails cares about and then be done, then we have one thing for the entire community.

Given, i'm talking about larger teams, but any time we went half way here it ends up with the same result in the future, something changes with aesthetic preferences and we have another round of debating the right way to add a space or block to no real benefit to customers.

from rails.

dhh avatar dhh commented on June 7, 2024

Glad you found your solution in Standard! But there’s a philosophical difference here that we aren’t going to gap in these comments, so I’ll refrain from attempting that any further. The menu is omakase, but you’re always welcome to make personal substitutions.

from rails.

Austio avatar Austio commented on June 7, 2024

Agree, that we won't bridge the gap here, will duck out after this as well.

We actually didn't end up on standard though, teams rehash this every so often now due to using rubocop with a bunch of artisinal, aesthetic preferences over using standardrb. Each time this happens, someone resurfaces the comment i made in the original discussion saying that doing this luke warm is opting future developers into continued discussion over the same thing.

I don't think this is omakase, it is opting people into picking things that don't actually matter in the long run.

from rails.

zzak avatar zzak commented on June 7, 2024

Generators on the other hand should absolutely be brought in line with this default style. I believe they mostly are since I wrote and polished the majority of them. But if they’re not there 100%, we can get them there.

My concern with aligning the generators with rubocop-rails-omakase is that unless there are tests for each generator, it could easily drift. There is large amount of variation too from rails new flags, scaffolding, and migration generators. If those rules aren't enforced on each of those, we end up with some generated code which the developer then has to autocorrect, I think to some extent that is fine -- but I'm curious as to how far we should take it and if that is a shared concern here. I'm fairly opinionated that style/cosmetic changes should not be made unless there is a linter/whatever to enforce it.

rails new --rubocop=standard or rails new --rubocop=rubocop-shopify or whatever

I think the idea is to not make it configurable, leaving only a --skip-rubocop flag.

from rails.

bbatsov avatar bbatsov commented on June 7, 2024

Additionally, Standard comes with an LSP so you can attach your editor and have it fix everything during editing. I'd highly recommend giving it a try!

FYI - RuboCop also comes with an LSP server. :-)

from rails.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.