From d97b12c16427c2e2e3be173fd51e608a352cd578 Mon Sep 17 00:00:00 2001 From: "Ben Sheldon [he/him]" Date: Thu, 13 Oct 2022 08:44:48 -0700 Subject: [PATCH 1/9] Create CONTRIBUTING.md --- CONTRIBUTING.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..d1804811 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,13 @@ +# Contributing + +## Releasing a new version + +1. Update `rubocop-github.gemspec` with the next version number +2. Update the `CHANGELOG` with changes and contributor +3. Run `bundle` to update gem version contained in the lockfile +4. Make a commit: `Release v{VERSION}` +5. Tag the commit : `git tag v{VERSION}` +6. Create the package: `gem build rubocop-github.gemspec` +7. Push to GitHub: `git push origin && git push origin --tags` +8. Push to Rubygems: `gem push rubocop-github-{VERSION}.gem` +9. Publish a new release on GitHub: https://github.com/github/rubocop-github/releases/new From ce23317087c8e93ed628deebab828722eb9f9446 Mon Sep 17 00:00:00 2001 From: Ben Sheldon Date: Thu, 13 Oct 2022 13:41:13 -0700 Subject: [PATCH 2/9] Replace custom `RailsApplicationRecord` and `RailsRenderInline` cops with their upstream equivalent --- config/rails.yml | 10 +-- config/rails_cops.yml | 12 ---- guides/rails-render-inline.md | 27 -------- .../cop/github/rails_application_record.rb | 29 --------- lib/rubocop/cop/github/rails_render_inline.rb | 29 --------- test/test_rails_application_record.rb | 39 ------------ test/test_rails_render_inline.rb | 62 ------------------- 7 files changed, 2 insertions(+), 206 deletions(-) delete mode 100644 guides/rails-render-inline.md delete mode 100644 lib/rubocop/cop/github/rails_application_record.rb delete mode 100644 lib/rubocop/cop/github/rails_render_inline.rb delete mode 100644 test/test_rails_application_record.rb delete mode 100644 test/test_rails_render_inline.rb diff --git a/config/rails.yml b/config/rails.yml index e414a00a..afe402cc 100644 --- a/config/rails.yml +++ b/config/rails.yml @@ -2,9 +2,6 @@ require: - rubocop-github-rails - rubocop-rails -GitHub/RailsApplicationRecord: - Enabled: true - GitHub/RailsControllerRenderActionSymbol: Enabled: true @@ -17,9 +14,6 @@ GitHub/RailsControllerRenderPathsExist: GitHub/RailsControllerRenderShorthand: Enabled: true -GitHub/RailsRenderInline: - Enabled: true - GitHub/RailsRenderObjectCollection: Enabled: false @@ -94,7 +88,7 @@ Rails/ApplicationMailer: Enabled: false Rails/ApplicationRecord: - Enabled: false + Enabled: true Rails/ArelStar: Enabled: false @@ -307,7 +301,7 @@ Rails/RelativeDateConstant: Enabled: false Rails/RenderInline: - Enabled: false + Enabled: true Rails/RenderPlainText: Enabled: false diff --git a/config/rails_cops.yml b/config/rails_cops.yml index ef3d9a4f..87363fbc 100644 --- a/config/rails_cops.yml +++ b/config/rails_cops.yml @@ -1,6 +1,3 @@ -GitHub/RailsApplicationRecord: - Enabled: pending - GitHub/RailsControllerRenderActionSymbol: Enabled: pending Include: @@ -25,15 +22,6 @@ GitHub/RailsControllerRenderShorthand: Include: - 'app/controllers/**/*.rb' -GitHub/RailsRenderInline: - Enabled: pending - StyleGuide: https://github.com/github/rubocop-github/blob/master/guides/rails-controller-render-inline.md - Include: - - 'app/controllers/**/*.rb' - - 'app/helpers/**/*.rb' - - 'app/view_models/**/*.rb' - - 'app/views/**/*.erb' - GitHub/RailsRenderObjectCollection: Enabled: pending diff --git a/guides/rails-render-inline.md b/guides/rails-render-inline.md deleted file mode 100644 index 8b5fa9b9..00000000 --- a/guides/rails-render-inline.md +++ /dev/null @@ -1,27 +0,0 @@ -# GitHub/RailsRenderInline - -tldr; Do not use `render inline:`. - -## Rendering plain text - -``` ruby -render inline: "Just plain text" # bad -``` - -The `inline:` option is often misused when plain text is being returned. Instead use `render plain: "Just plain text"`. - -## Rendering a dynamic ERB string - -String `#{}` interpolation is often misused with `render inline:` instead of using `<%= %>` interpolation. This will lead to a memory leak where an ERB method will be compiled and cached for each invocation of `render inline:`. - -``` ruby -render inline: "Hello #{@name}" # bad -``` - -## Rendering static ERB strings - -``` ruby -render inline: "Hello <%= @name %>" # bad -``` - -If you are passing a static ERB string to `render inline:`, this string is best moved to a `.erb` template under `app/views`. Template files are able to be precompiled at boot time. diff --git a/lib/rubocop/cop/github/rails_application_record.rb b/lib/rubocop/cop/github/rails_application_record.rb deleted file mode 100644 index 1ec30cf9..00000000 --- a/lib/rubocop/cop/github/rails_application_record.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -require "rubocop" - -module RuboCop - module Cop - module GitHub - class RailsApplicationRecord < Base - MSG = "Models should subclass from ApplicationRecord" - - def_node_matcher :active_record_base_const?, <<-PATTERN - (const (const nil? :ActiveRecord) :Base) - PATTERN - - def_node_matcher :application_record_const?, <<-PATTERN - (const nil? :ApplicationRecord) - PATTERN - - def on_class(node) - klass, superclass, _ = *node - - if active_record_base_const?(superclass) && !(application_record_const?(klass)) - add_offense(superclass) - end - end - end - end - end -end diff --git a/lib/rubocop/cop/github/rails_render_inline.rb b/lib/rubocop/cop/github/rails_render_inline.rb deleted file mode 100644 index 8f76fb2f..00000000 --- a/lib/rubocop/cop/github/rails_render_inline.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -require "rubocop" - -module RuboCop - module Cop - module GitHub - class RailsRenderInline < Base - MSG = "Avoid `render inline:`" - - def_node_matcher :render_with_options?, <<-PATTERN - (send nil? {:render :render_to_string} (hash $...)) - PATTERN - - def_node_matcher :inline_key?, <<-PATTERN - (pair (sym :inline) $_) - PATTERN - - def on_send(node) - if option_pairs = render_with_options?(node) - if option_pairs.detect { |pair| inline_key?(pair) } - add_offense(node) - end - end - end - end - end - end -end diff --git a/test/test_rails_application_record.rb b/test/test_rails_application_record.rb deleted file mode 100644 index 7ac77945..00000000 --- a/test/test_rails_application_record.rb +++ /dev/null @@ -1,39 +0,0 @@ -# frozen_string_literal: true - -require_relative "./cop_test" -require "minitest/autorun" -require "rubocop/cop/github/rails_application_record" - -class TestRailsApplicationRecord < CopTest - def cop_class - RuboCop::Cop::GitHub::RailsApplicationRecord - end - - def test_good_model - offenses = investigate(cop, <<-RUBY) - class Repository < ApplicationRecord - end - RUBY - - assert_empty offenses.map(&:message) - end - - def test_application_record_model - offenses = investigate(cop, <<-RUBY) - class ApplicationRecord < ActiveRecord::Base - end - RUBY - - assert_empty offenses.map(&:message) - end - - def test_bad_model - offenses = investigate(cop, <<-RUBY) - class Repository < ActiveRecord::Base - end - RUBY - - assert_equal 1, offenses.count - assert_equal "Models should subclass from ApplicationRecord", offenses.first.message - end -end diff --git a/test/test_rails_render_inline.rb b/test/test_rails_render_inline.rb deleted file mode 100644 index 53d5cadd..00000000 --- a/test/test_rails_render_inline.rb +++ /dev/null @@ -1,62 +0,0 @@ -# frozen_string_literal: true - -require_relative "./cop_test" -require "minitest/autorun" -require "rubocop/cop/github/rails_render_inline" - -class TestRailsRenderInline < CopTest - def cop_class - RuboCop::Cop::GitHub::RailsRenderInline - end - - def test_render_string_no_offense - offenses = investigate cop, <<-RUBY, "app/controllers/foo_controller.rb" - class FooController < ActionController::Base - def index - render template: "index" - end - - def show - render template: "show.html.erb", locals: { foo: @foo } - end - end - RUBY - - assert_equal 0, offenses.count - end - - def test_render_inline_offense - offenses = investigate cop, <<-RUBY, "app/controllers/products_controller.rb" - class ProductsController < ActionController::Base - def index - render inline: "<% products.each do |p| %>

<%= p.name %>

<% end %>" - end - end - RUBY - - assert_equal 1, offenses.count - assert_equal "Avoid `render inline:`", offenses[0].message - end - - def test_render_status_with_inline_offense - offenses = investigate cop, <<-RUBY, "app/controllers/products_controller.rb" - class ProductsController < ActionController::Base - def index - render status: 200, inline: "<% products.each do |p| %>

<%= p.name %>

<% end %>" - end - end - RUBY - - assert_equal 1, offenses.count - assert_equal "Avoid `render inline:`", offenses[0].message - end - - def test_erb_render_inline_offense - offenses = erb_investigate cop, <<-ERB, "app/views/products/index.html.erb" - <%= render inline: template %> - ERB - - assert_equal 1, offenses.count - assert_equal "Avoid `render inline:`", offenses[0].message - end -end From 15a6e783a40980e48da73468c95ab240b7ca48d5 Mon Sep 17 00:00:00 2001 From: Ben Sheldon Date: Thu, 13 Oct 2022 14:03:21 -0700 Subject: [PATCH 3/9] Add Contribution instructions, code of conduct, and codeowners --- CODEOWNERS | 1 + CODE_OF_CONDUCT.md | 73 ++++++++++++++++++++++++++++++++++++++++++++++ CONTRIBUTING.md | 47 +++++++++++++++++++++++------ README.md | 2 +- 4 files changed, 113 insertions(+), 10 deletions(-) create mode 100644 CODEOWNERS create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 00000000..6e12c3bc --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1 @@ +* @github/ruby-archiecture-reviewers diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..2ef4f602 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,73 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to make participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies within all project spaces, and it also applies when +an individual is representing the project or its community in public spaces. +Examples of representing a project or community include using an official +project e-mail address, posting via an official social media account, or acting +as an appointed representative at an online or offline event. Representation of +a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at opensource+rubocop@github.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d1804811..4f1f09da 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,13 +1,42 @@ # Contributing -## Releasing a new version +We welcome your contributions to the project. Thank you! + +Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms. + + +## What to contribute + +This repository, `rubocop-github` is part of a broader RuboCop ecosystem. + +If the Cop you would like to propose is **generally applicable outside of GitHub**: + +1. Propose the change upstream in the core open source project (e.g. [`rubocop`](https://github.com/rubocop/rubocop), or [`rubocop-rails`](https://github.com/rubocop/rubocop-rails)), where it will have maximal visibility and discussion/feedback. +1. Patch the change provisionally into GitHub's project(s), for immediate benefit; that can include this repository. +1. ...if the proposal is accepted, remove the patch and pull the updated upstream. +1. ...if the proposal is not accepted, we usually learn something about our proposal, and we then choose whether to maintain the patch ourselves, discard it, or identify a better open-source home for it. + +If the Cop is **only applicable for GitHub**, then this is the right place to propose it. + +## How to contribute a Pull Request + +1. Fork and clone the repository +1. [Build it and make sure the tests pass](README.md#Testing) on your machine +1. Create a new branch: `git checkout -b my-branch-name` +1. Make your change, add tests, and make sure the tests still pass +1. Push to your fork and submit a Pull Request +1. Pat yourself on the back and wait for your pull request to be reviewed and merged. + +## For Maintainers + +### Releasing a new version 1. Update `rubocop-github.gemspec` with the next version number -2. Update the `CHANGELOG` with changes and contributor -3. Run `bundle` to update gem version contained in the lockfile -4. Make a commit: `Release v{VERSION}` -5. Tag the commit : `git tag v{VERSION}` -6. Create the package: `gem build rubocop-github.gemspec` -7. Push to GitHub: `git push origin && git push origin --tags` -8. Push to Rubygems: `gem push rubocop-github-{VERSION}.gem` -9. Publish a new release on GitHub: https://github.com/github/rubocop-github/releases/new +1. Update the `CHANGELOG` with changes and contributor +1. Run `bundle` to update gem version contained in the lockfile +1. Make a commit: `Release v{VERSION}` +1. Tag the commit : `git tag v{VERSION}` +1. Create the package: `gem build rubocop-github.gemspec` +1. Push to GitHub: `git push origin && git push origin --tags` +1. Push to Rubygems: `gem push rubocop-github-{VERSION}.gem` +1. Publish a new release on GitHub: https://github.com/github/rubocop-github/releases/new diff --git a/README.md b/README.md index 8796a67d..16b7a152 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # RuboCop GitHub ![CI](https://github.com/github/rubocop-github/workflows/CI/badge.svg?event=push) -This repository provides recommended RuboCop configuration and additional Cops for use on GitHub open source and internal Ruby projects. +This repository provides recommended RuboCop configuration and additional Cops for use on GitHub's open source and internal Ruby projects. ## Usage From 27c926dab95dc989da9e234f169a92142b33e270 Mon Sep 17 00:00:00 2001 From: "Ben Sheldon [he/him]" Date: Thu, 13 Oct 2022 14:04:25 -0700 Subject: [PATCH 4/9] Update CODEOWNERS --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index 6e12c3bc..fb48a77e 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1 +1 @@ -* @github/ruby-archiecture-reviewers +* @github/ruby-architecture-reviewers From 25a3a08f7ac3aed0216a755e104e9fdbadd9bac5 Mon Sep 17 00:00:00 2001 From: Issy Long Date: Fri, 21 Oct 2022 14:19:04 +0000 Subject: [PATCH 5/9] config/default: Remove some redundant `Enabled: true` for cops - For cops with a styleguide link, where there's evidence that we want the rule to apply, we don't need to also explicitly declare `Enabled: true` for each of them. Since we removed `DisabledByDefault`, the enablements here for cops that are *enabled by default in RuboCop itself** are redundant. - I could have gone further and removed the rules that RuboCop has enabled by default that _didn't_ have a styleguide link, but I feel like we need some evidence for why a rule is in place first for when people come looking at this gem's config to figure out why new rules are suddenly failing or not. --- config/default.yml | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/config/default.yml b/config/default.yml index d7883cef..6ae30545 100644 --- a/config/default.yml +++ b/config/default.yml @@ -182,16 +182,14 @@ Layout/HeredocIndentation: Enabled: false Layout/IndentationConsistency: - Enabled: false + StyleGuide: https://github.com/github/rubocop-github/blob/main/STYLEGUIDE.md#indentation Layout/IndentationStyle: - Enabled: true EnforcedStyle: spaces IndentationWidth: 2 StyleGuide: https://github.com/github/rubocop-github/blob/main/STYLEGUIDE.md#default-indentation Layout/IndentationWidth: - Enabled: true Width: 2 StyleGuide: https://github.com/github/rubocop-github/blob/main/STYLEGUIDE.md#default-indentation @@ -262,11 +260,9 @@ Layout/SingleLineBlockChain: Enabled: false Layout/SpaceAfterColon: - Enabled: true StyleGuide: https://github.com/github/rubocop-github/blob/main/STYLEGUIDE.md#spaces-operators Layout/SpaceAfterComma: - Enabled: true StyleGuide: https://github.com/github/rubocop-github/blob/main/STYLEGUIDE.md#spaces-operators Layout/SpaceAfterMethodName: @@ -276,18 +272,16 @@ Layout/SpaceAfterNot: Enabled: true Layout/SpaceAfterSemicolon: - Enabled: true StyleGuide: https://github.com/github/rubocop-github/blob/main/STYLEGUIDE.md#spaces-operators Layout/SpaceAroundBlockParameters: Enabled: true Layout/SpaceAroundEqualsInParameterDefault: - Enabled: true StyleGuide: https://github.com/github/rubocop-github/blob/main/STYLEGUIDE.md#spaces-around-equals Layout/SpaceAroundKeyword: - Enabled: false + StyleGuide: https://github.com/github/rubocop-github/blob/main/STYLEGUIDE.md#spaces-operators Layout/SpaceAroundMethodCallOperator: Enabled: false @@ -317,7 +311,6 @@ Layout/SpaceInLambdaLiteral: Enabled: false Layout/SpaceInsideArrayLiteralBrackets: - Enabled: true EnforcedStyle: no_space StyleGuide: https://github.com/github/rubocop-github/blob/main/STYLEGUIDE.md#no-spaces-braces @@ -349,7 +342,6 @@ Layout/TrailingEmptyLines: Enabled: true Layout/TrailingWhitespace: - Enabled: true StyleGuide: https://github.com/github/rubocop-github/blob/main/STYLEGUIDE.md#trailing-whitespace Lint/AmbiguousAssignment: @@ -1090,7 +1082,6 @@ Style/DateTime: Enabled: false Style/DefWithParentheses: - Enabled: true StyleGuide: https://github.com/github/rubocop-github/blob/main/STYLEGUIDE.md#method-parens-when-arguments Style/Dir: @@ -1178,7 +1169,6 @@ Style/FloatDivision: Enabled: false Style/For: - Enabled: true StyleGuide: https://github.com/github/rubocop-github/blob/main/STYLEGUIDE.md#avoid-for Style/FormatString: @@ -1215,7 +1205,6 @@ Style/HashLikeCase: Enabled: false Style/HashSyntax: - Enabled: true EnforcedStyle: ruby19_no_mixed_keys StyleGuide: https://github.com/github/rubocop-github/blob/main/STYLEGUIDE.md#symbols-as-keys @@ -1316,7 +1305,6 @@ Style/MultilineIfModifier: Enabled: false Style/MultilineIfThen: - Enabled: true StyleGuide: https://github.com/github/rubocop-github/blob/main/STYLEGUIDE.md#no-then-for-multi-line-if-unless Style/MultilineInPatternThen: @@ -1583,8 +1571,8 @@ Style/StringHashKeys: Enabled: false Style/StringLiterals: - Enabled: true EnforcedStyle: double_quotes + StyleGuide: https://github.com/github/rubocop-github/blob/main/STYLEGUIDE.md#double-quotes Style/StringLiteralsInInterpolation: Enabled: false From 217b98638c7636652c1430a19d32c13f97eb7e27 Mon Sep 17 00:00:00 2001 From: Sam Partington Date: Fri, 21 Oct 2022 16:35:38 +0100 Subject: [PATCH 6/9] Fix Styleguide link in default.yml https://github.com/github/rubocop-github/pull/124/files#r1000474353 --- config/default.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/default.yml b/config/default.yml index d7883cef..ad020013 100644 --- a/config/default.yml +++ b/config/default.yml @@ -691,7 +691,7 @@ Lint/UnreachableLoop: # TODO: Enable this since it's in the styleguide. Lint/UnusedBlockArgument: Enabled: false - StyleGuide: https://github.com/github/rubocop-github/blob/main/STYLEGUIDE.md#spaces-around-equals + StyleGuide: https://github.com/github/rubocop-github/blob/main/STYLEGUIDE.md#underscore-unused-vars Lint/UnusedMethodArgument: Enabled: false From 8e768057435f96782bb53fa91fc7c77f8d857a58 Mon Sep 17 00:00:00 2001 From: Sam Partington Date: Tue, 25 Oct 2022 13:52:40 +0100 Subject: [PATCH 7/9] Add link to Style Guide from README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8796a67d..7ba558fa 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # RuboCop GitHub ![CI](https://github.com/github/rubocop-github/workflows/CI/badge.svg?event=push) -This repository provides recommended RuboCop configuration and additional Cops for use on GitHub open source and internal Ruby projects. +This repository provides recommended RuboCop configuration and additional Cops for use on GitHub open source and internal Ruby projects, and is the home of [GitHub's Ruby Style Guide](./STYLEGUIDE.md). ## Usage From d24723ec59b2ceae6fd42f62746330841c35e058 Mon Sep 17 00:00:00 2001 From: Sam Partington Date: Tue, 25 Oct 2022 14:33:09 +0100 Subject: [PATCH 8/9] Add Rails recommendations to styleguide These were originally in our web-systems documentation --- STYLEGUIDE.md | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/STYLEGUIDE.md b/STYLEGUIDE.md index 1e55a3be..56839237 100644 --- a/STYLEGUIDE.md +++ b/STYLEGUIDE.md @@ -27,6 +27,9 @@ This is GitHub's Ruby Style Guide, inspired by [RuboCop's guide][rubocop-guide]. 1. [Conditional keywords](#conditional-keywords) 2. [Ternary operator](#ternary-operator) 17. [Syntax](#syntax) +18. [Rails](#rails) + 1. [content_for](#content_for) + 2. [Instance Variables in Views](#instance-variables-in-views) ## Layout @@ -893,4 +896,129 @@ result = hash.map { |_, v| v + 1 } Refactoring is even better. It's worth looking hard at any code that explicitly checks types. +## Rails + +### content_for + +Limit usage of `content_for` helper. The use of `content_for` is the same as setting an instance variable plus `capture`. + +``` erb +<% content_for :foo do %> + Hello +<% end %> +``` + +Is effectively the same as + +``` erb +<% @foo_content = capture do %> + Hello +<% end %> +``` + +See "Instance Variables in Views" below. + +#### Common Anti-patterns + +**Using `content_for` within the same template to capture data.** + +Instead, just use `capture`. + +``` erb + +<% content_for :page do %> + Hello +<% end %> +<% if foo? %> +
+ <%= yield :page %> +
+<% else %> + <%= yield :page %> +<% end %> +``` + +Simply capture and use a local variable since the result is only needed in this template. + +``` erb + +<% page = capture do %> + Hello +<% end %> +<% if foo? %> +
+ <%= page %> +
+<% else %> + <%= page %> +<% end %> +``` + +**Using `content_for` to pass content to a subtemplate.** + +Instead, `render layout:` with a block. + +``` erb + +<% content_for :page do %> + Hello +<% end %> +<%= render partial: "page" %> + +
+ <%= yield :page %> +
+``` + +Pass the content in a block directly to the `render` function. + +``` erb + +<%= render layout: "page" do %> + Hello +<% end %> + +
+ <%= yield %> +
+``` + +### Instance Variables in Views + +In general, passing data between templates with instance variables is discouraged. This even applies from controllers to templates, not just between partials. + +`:locals` can be used to pass data from a controller just like partials. + +``` ruby +def show + render "blob/show", locals: { + :repository => current_repository, + :commit => current_commit, + :blob => current_blob + } +end +``` + +Rails implicit renders are also discouraged. + +Always explicitly render templates with a full directory path. This makes template callers easier to trace. You can find all the callers of `"app/view/site/hompage.html.erb"` with a simple project search for `"site/homepage"`. + +``` ruby +def homepage + render "site/homepage" +end +``` + +#### Exceptions + +There are some known edge cases where you might be forced to use instance variables. In these cases, its okay to do so. + +##### Legacy templates + +If you need to call a subview that expects an instance variable be set. If possible consider refactoring the subview to accept a local instead. + +##### Layouts + +Unfortunately the only way to get data into a layout template is with instance variables. You can't explicitly pass locals to them. + [rubocop-guide]: https://github.com/rubocop-hq/ruby-style-guide From 9930c9050c0fd314ea291b8b08e7d7cd01dcef87 Mon Sep 17 00:00:00 2001 From: "Ben Sheldon [he/him]" Date: Wed, 26 Oct 2022 08:02:11 -0700 Subject: [PATCH 9/9] Update CONTRIBUTING.md Co-authored-by: Sam Partington --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4f1f09da..a69b7d28 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,7 +7,7 @@ Please note that this project is released with a [Contributor Code of Conduct](C ## What to contribute -This repository, `rubocop-github` is part of a broader RuboCop ecosystem. +This repository, `rubocop-github`, is part of a broader RuboCop ecosystem. If the Cop you would like to propose is **generally applicable outside of GitHub**: