Share
Embed
RuboCop in 2021: Stable and Beyond
RubyKaigi Takeout 2021
https://rubykaigi.org/2021-takeout
Koichi ITO
September 09, 2021
Transcript
97 slides
-
!LPJD w 044QSPHSBNNFS w 3VCP$PQDPSFUFBN w )FBENBJOUBJOFSPG3VCP$PQ3BJMT 3VCP$PQ1FSGPSNBODF BOE
3VCP$PQ.JOJUFTU w &OHJOFFSJOH.BOBHFSBOE %JTUJOHVJTIFE&OHJOFFSPG&4. *OD -
/FXDPQTBSFQFOEJOHCZEFGBVMUVOUJM gem 'rubocop', '~> 1.19', require: false gem 'rubocop', '~>
0.78.0', require: false w/POFFEUPTQFDJGZUIFQBUDI WFSTJPOJO(FNpMFXIFOVTJOH~> WY WY -
*GZPVBSFFBSMZBEPQUFS ZPVDBOFOBCMFQFOEJOHDPQT &OBCMFOFXDPQT % bundle exec rubocop The following cops
were added to RuboCop, but are not configured. Please set Enabled to either `true` or `false` in your `.rubocop.yml` file. Please also note that you can opt-in to new cops by default by adding this to your config: AllCops: NewCops: enable Gemspec/DateAssignment: # (new in 1.10) Enabled: true Layout/LineEndStringConcatenationIndentation: # (new in 1.18) Enabled: true Layout/SpaceBeforeBrackets: # (new in 1.7) Enabled: true Lint/AmbiguousAssignment: # (new in 1.7) Enabled: true -
w 4FUEnabledUPFJUIFStruePSfalseJOZPVS SVCPDPQZNM w :PVDBODIPPTFFOBCMFOFXDPQTCZ EFGBVMUJGZPVXBOUJUNewCops: enable UPSVCPDPQZNM w 0S
EJTBCMFOFXDPQTCZEFGBVMUJGZPV EPOUXBOUJUNewCops: disable &OBCMFOFXDPQT -
8IZOPUTVQQPSUFE % cd path/to/rubocop % bin/console RuboCop::Cop::Registry.global. with_department(:Layout). reject(&:support_autocorrect?) =>
[RuboCop::Cop::Layout::EndOfLine] *EPOUIBWF8JOEPXT🤦 -
3VCZOFXTZOUBY w1BUUFSONBUDIJOH /VNCFSFEQBSBNFUFST &OEMFTT NFUIPEEFpOJUJPO BOEFUD w"TBUSJWJBGPSDPQEFWFMPQFST UIFPOFMJOFQBUUFSO NBUDIJOHTZOUBY"45EJGGFSTCFUXFFOBOE In
Ruby 2.7(Parser::Ruby27) SVCZQBSTFFJOGPP NBUDIQBUUFSO JOU NBUDIWBSGPP SVCZQBSTFFGPP NBUDIQBUUFSO JOU NBUDIWBSGPP SVCZQBSTFFJOGPP NBUDIQBUUFSOQ JOU NBUDIWBSGPP In Ruby 3.0(Parser::Ruby30) ruby-parseDPNNBOEJTQSPWJEFECZ1BSTFSHFN -
DPSF$16T )ZQFS5ISFBEJOH TFD OPQBSBMMFM QBSBMMFM
w8IFO3VCP$PQ JOTQFDUTBMPUPG pMFT JUXJMMCF FGGFDUJWF wFHTFDTFD BCPVUpMFT -
#VHpYFT w*OUIFQBTU 3VCP$PQTVHHFTUFEUPDIBOHF expr and returnUPexpr && returnCZEFGBVMU w*UMPPLFEXFJSE TP*DIBOHFEUIFDPOpHVSBUJPO
UPBDDFQUexpr and returnCZEFGBVMU 6TF `and return` % ruby -e \ 'p false || true and return' # => true # p(false || true) and return % ruby -e \ 'p false || true && return' # noop # p(false || (true && return)) 6TF `&& return` -
w 3VCZIBTOPTUBUJDUZQJOH w /PUZQFJOGPSNBUJPOGPSWBSJBCMFT BSHVNFOUT SFUVSOWBMVFT XJUIPVU3#4 w
Safe: falseJTTFUJODBTFTXIFSFGBMTF QPTJUJWFTDBOOPUCFQSFWFOUFE w "WPJESafe: falseBTNVDIBTQPTTJCMF BOE EFTJHODPQTDBSFGVMMZOPUUPDBVTFGBMTF QPTJUJWFT 3VCP$PQJTBTUBUJDBOBMZ[FS -
w "TTFSUJPONFUIPEOPUVTFEJO assert_raises w *OPUIFSXPSET HPPEDBTF 5SVFOFHBUJWF EFpOJUFMZ assert_raises FooError
do do_something('foo', obj.bar) end "TTFSUJPONFUIPEOPUVTFE -
assert_raises FooError do obj.foo assert_equal('foo', obj.bar) end w "OBTTFSUJPONFUIPE FHassert_equal
JT DBMMFEBUUIFCPUUPNPGassert_raisesCMPDL w 5IFSFGPSF OPUBTTFSUFEJUCFDBVTFBO FYDFQUJPOTIPVMEIBWFPDDVSSFE TPNFXIFSFCFGPSF 5SVFQPTJUJWF EFpOJUFMZ assert_equalJTOFWFSDBMMFE assert_raises FooError do obj.foo assert_equal('foo', obj.bar) end %PFTfooSBJTFBOFYDFQUJPO 0S EPFTbarSBJTFBOFYDFQUJPO assert_equalJTOFWFSDBMMFECFDBVTFUIFNFUIPEJTFWBMVBUFEMBTU -
w GBMTFQPTJUJWFJGOPFYDFQUJPO PDDVSTJOobj.foo w USVFQPTJUJWFJGBOFYDFQUJPO PDDVSTJOobj.foo $POTFSWBUJWFEFTJHO assert_raises FooError do
assert_equal('foo', obj.foo) obj.bar end *GJUEPFTOUSBJTFTIFSF JUTBGBMTFQPTJUJWF *GJUSBJTFTIFSF JUTBUSVFQPTJUJWF RuboCop don't know if it's a false positive or not -
w *GUIFMBTUNFUIPEDBMMFEJTBOBTTFSUJPO NFUIPE UIFSFTIPVMECFBOFYDFQUJPOJO UIFQSFWJPVTNFUIPEDBMM /FWFSSFBDIFE w 'BMTFOFHBUJWFTBDDFQUFE w
1SFWFOUCSFBLJOHDPEFCZGBMTFQPTJUJWFT w /PUFTUDPEFQSPUFDUTUIFUFTUDPEF %FTJHOUPBWPJEGBMTFQPTJUJWFT -
w *UTJNQPSUBOUUPSVO3VCP$PQUIBUBDUVBMMZVTFT .JOJUFTU w *SBOJUJOUIFSBJMTSBJMTSFQPTJUPSZBOEGPVOE GBMTFQPTJUJWFT w "EESVCPDPQNJOJUFTUUPSBJMTSBJMT(FNpMFBOE TQFDJGZpathPSgithubPQUJPO w
3VOrubocop --only Minitest/UnreachableAssertion %PHGPPEJOHXJUISFBMXPSMEDPEF -
w 6TFBaseDMBTTJOTUFBEPGCopDMBTT w .PTUPGHFNTNBJOUBJOFECZSVCPDPQPSH TVDIBT3VCP$PQ1FSGPSNBODF 3BJMT 34QFD .JOJUFTU 3BLFIBWFCFFONJHSBUFE
w "EFQSFDBUFEXBSOJOHNBZCFEJTQMBZFE BGUFS3VCP$PQDPSFJUTFMGIBTCFFOBMM NJHSBUFE W"1*GPSDPQEFWFMPQFST -
w $POTJEFSEFpOJOH RESTRICT_ON_SENDDPOTUBOUXIFO EFpOJOHon_sendIBOEMFS <5JQ>1FSGPSNBODFJNQSPWFNFOU # `on_send` is called only
when `foo` was called class ExampleCop < Base RESTRICT_ON_SEND = %i[foo].freeze def on_send(node) = add_offense(node) end -
w $VSSFOUMZOPXBSOJOHJTEJTQMBZFE TPGUEFQSFDBUJPO w 8JMMEJTQMBZBXBSOJOHBUTPNF QPJOUJOW w 5IPTF"1*XJMMCFDIBOHFE PSSFNPWFE
JOW %FQSFDBUFE"1*GPSSEQBSUZHFNT -
w TargetRailsVersionBOETJNJMBS"1* SFNBJOTJO3VCP$PQDPSFBGUFS3BJMT EFQBSUNFOUFYUSBDUFE w 3FNPWJOHTargetRailsVersion BOE TJNJMBS"1*SFGFSFODFECZ3VCP$PQ 3BJMTJTBCSFBLJOHDIBOHF TP*XJMM
UBLFJUDBSFGVMMZ 3FNPWF3BJMTEFQFOEFODJFTGSPNDPSF -
"Default rules are too strict, but customization is hard..." 'FFECBDLGSPNVTFST
*EPOUIBWFUIFCFTUBOTXFS CVU*MMUBMLJEFBTIFSF -
"QQMJDBUJPOTUSBUFHZ %JTBCMFE#Z%FGBVMUUSVF &OBCMFE#Z%FGBVMUUSVF %FGBVMUDPOpHVSBUJPO 5IJSEQBSUZQSFTFU 3VMFTUSFOHUIBOEDPNQMFYJUZ 5JNFUPBQQMZ3VCP$PQ $VTUPNDPOpHVSBUJPO 8IFUIFSUPDPOpHVSFPSOPU 8IFUIFSUPDPOpHVSFPSOPU
1SPCBCMZPOMZGPS3VCP$PQUFTUJOH $POpHVSFMBUFS 5IFDPOpHVSBUJPOZPVMJLF ⭐ ⭐ ⭐ ⭐)PXUPHFUTUBSUFE .BZCFUIFSFJTBQSFTFUUIBU JTDMPTFUPZPVSUBTUF 3VMFTFUUPBQQMZ -
"QQMJDBUJPOTUSBUFHZ %JTBCMFE#Z%FGBVMUUSVF &OBCMFE#Z%FGBVMUUSVF %FGBVMUDPOpHVSBUJPO 5IJSEQBSUZQSFTFU Today's topic 3VMFTUSFOHUIBOEDPNQMFYJUZ 5JNFUPBQQMZ3VCP$PQ $VTUPNDPOpHVSBUJPO
8IFUIFSUPDPOpHVSFPSOPU 8IFUIFSUPDPOpHVSFPSOPU 1SPCBCMZPOMZGPS3VCP$PQUFTUJOH $POpHVSFMBUFS 5IFDPOpHVSBUJPOZPVMJLF ⭐ ⭐ ⭐ ⭐)PXUPHFUTUBSUFE .BZCFUIFSFJTBQSFTFUUIBU JTDMPTFUPZPVSUBTUF 3VMFTFUUPBQQMZ -
3VOUJNFFOHJOFBOE DPSFDPQT $POpHVSBUJPO $POpHVSBUJPO 3VCP$PQDPSF SVCPDPQZNM SBJMTSBJMTSFQP &YUFOEBCMFDPOpHVSBUJPO $POpHVSBUJPO SVCPDPQSBJMT@DPOpH
HFN SVCPDPQZNM BQQMJDBUJPO 4UBOEBSEHFN UFTUEPVCMFTUBOEBSE You can use existing 3rd party configurations Configurable No configuration -
3VOUJNFFOHJOFBOE DPSFDPQT $POpHVSBUJPO 1SFTFUDPOpHVSBUJPO 3VCP$PQDPSF SVCPDPQZNM SBJMTSBJMTSFQP 3JEFPOSEQBSUZQSFTFUXBZ $POpHVSBUJPO SVCPDPQSBJMT@DPOpH
HFN SVCPDPQZNM BQQMJDBUJPO 4UBOEBSEHFN UFTUEPVCMFTUBOEBSE You can use existing 3rd party preset or your config Configurable No configuration -
.JOJNVNQSFTFU %JTBCMFE#Z%FGBVMUUSVF &OBCMFE#Z%FGBVMUUSVF %FGBVMUDPOpHVSBUJPO 5IJSEQBSUZQSFTFU 3VMFTUSFOHUI CVUDPNQMFY 5JNFUPJOUSPEVDFBQSPKFDU $VTUPNDPOpHVSBUJPO 8IFUIFSUPDPOpHVSFPSOPU
8IFUIFSUPDPOpHVSFPSOPU 1SPCBCMZPOMZGPS3VCP$PQUFTUJOH $POpHVSFMBUFS 5IFDPOpHVSBUJPOZPVMJLF ⭐ ⭐ ⭐ ⭐)PXUPHFUTUBSUFE .BZCFUIFSFJTBQSFTFUUIBU JTDMPTFUPZPVSUBTUF 3VMFTFUUPBQQMZ JEFB .JOJNVNQSFTFUGSPNP⒏DJBM -
w #PPUTOBQXBTQSPQPTFEJOUIFQBTU CVUXPSUISFWJTJUFE w *OUFHSBUFEBFNPOTMJLFSVCPDPQ EBFNPO
BOEDPMMBCPSBUFXJUI-41 4PMBSHSBQI w *UTIPVMEDPOUSJCVUFUPUIF3VCZ DPODFQU4NBSUFS 'BTUFS 1FSGPSNBODFJNQSPWFNFOUJEFBT