Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Automate the boring staff with Ruby

Cfbe23392787cb3ad4689c5f72463fcc?s=47 makicamel
December 27, 2020

Automate the boring staff with Ruby

- 2020.12.27. Tama.rb #25 年忘れLT会

Cfbe23392787cb3ad4689c5f72463fcc?s=128

makicamel

December 27, 2020
Tweet

Transcript

  1. ୀ۶ͳ͜ͱ͸ 3VCZʹ͓Ͷ͕͍͠Α͏ 2020.12.27. Tama.rb #25 ೥๨ΕLTձ @makicamel

  2. w!NBLJDBNFM઒ݪສق wɹ w3VCZͱϏʔϧɹɹͱ͓ञ͕޷͖ ࣗݾ঺հ

  3. ͓खݩͷRails ΞϓϦʹ BQQMJDBUJPO@DPOUSPMMFSSC ͍ͭ͋͘Γ·͔͢ʁ ಥવͰ͕͢ ܧঝͱϝλϓϩάϥϛϯάຬࡌͳΞϓϦέʔγϣϯίʔυͰ΋ΞΫγϣϯͱϑΟϧλʹ೰·ͳ͍ͨΊͷ(FNΛ࡞ͬͨ࿩ IUUQTTQFBLFSEFDLDPNNBLJDBNFMMFUTFOKPZDSFBUJOHHFNT

  4. ˞೥݄೔࣌఺ "/%1"% # => 325 $ find . -name application_controller.rb

    | wc -l
  5. ˞೥݄೔ݱࡏ "/%1"% $ fd application_controller.rb | wc -l # =>

    49 # => 325 ˞೥݄೔࣌఺ $ find . -name application_controller.rb | wc -l 85%ݮʂ ͍͢͝Ͷ
  6. ॳख •ͻͱͭͻͱͭखͰஔ͖׵͑Δ •σΟϨΫτϦຖʹ౗͍͚ͯ͠͹͍͍͸ͣ •ࠓ·Ͱͷ׳ྫ΋कΒΕͯແடংʹͳΒͳ͍ •2 PullRequests Ͱ໿ 40 ϑΝΠϧ࡟আ •࣌ؒͱࠜؾͱूதྗͷඞཁͳ࡞ۀ

  7. खΛಈ͔ͯ͠ؾͮ͘ •εΫϦϓτͰ͍͚ΔͷͰ͸ʁ

  8. ཌ݄༵೔

  9. ཌ݄༵೔ ࢒໿ 240 ϑΝΠϧ͸দా͞Μ͕౗ͯ͘͠Ε·ͨ͠

  10. εΫϦϓτͰ΍Δͱ ͳʹ͕͏Ε͍͠ͷ͔

  11. εΫϦϓτͰ΍Δͱ •࡞ۀϛε͕ͳ͍ •ਓؒ͸ؒҧ͑Δ •ϓϩάϥϜ͸໊લ͕ࣅ͍ͯΔϞδϡʔϧ͕͋ͬͯ΋ؒҧ͑ͳ͍ •ϛεʹ஫ҙΛ෷Θͳͯ͘Α͍ͷͰϨϏϡʔෛ୲͕ݮΔ

  12. εΫϦϓτͰ΍Δͱ •࠶ݱੑ͕ߴ͍ •ߟྀ࿙Ε͕͋ͬͯ΋ԿճͰ΋΍Γ௚͠Մೳ •ख࡞ۀͰಉ͡࡞ۀɾݕূΛ܁Γฦ͞ͳͯ͘Α͍

  13. εΫϦϓτͰ΍Δͱ •࠶ར༻ੑ͕ߴ͍ •৚݅Λม͑ͯΑΓ෯޿͍໰୊ʹద༻Ͱ͖Δ •ૣ͍ •80 ϑΝΠϧͷ࡟আ͕਺ඵ •ίϛοτͷ࡞੒΋Ͱ͖Δ

  14. εΫϦϓτͰ΍Δͱ •࣮֬ •ʮ֬ೝͷ Rails.application.eager_load! ๨Εͨʂʯͱ͔ͳ͍ •ʮrubocop -a ๨Εͨʂʯͱ͔ͳ͍

  15. εΫϦϓτͰ΍Δͱ •ؾ͍͍࣋ͪ •Ruby ͷΑ͞ •୯७࡞ۀ͸ͭ·Βͳ͍ɾ͖͋Δɾूதྗɾࠜؾ͕ඞཁ •࢓ࣄͷ߹ؒʹؾ߹͍Ͱ΍͍ͬͯΔͷͰΤλΔ •ؾ͍͍࣋ͪͱΤλΒͳ͍ʂ

  16. εΫϦϓτͰ΍Δͱ •໰୊ͷ੾Γ෼͚ํ͕ҟͳΔ •ख࡞ۀ࣌ɿʮਓ͕ؒཧղ͢Δҙຯͷ୯Ґʯ •Θ͕ͨ͠࡞ۀͨ͠ͷ͸໊લۭؒ୯Ґ •εΫϦϓτ࣌ɿʮઃఆͨ͠৚݅୯Ґʯ •দా͞Μ͕࠷ॳʹઃఆͨ͠৚݅͸ʮ͔ΒͬΆͳίϯτϩʔϥʯ •ҙຯ͝ͱʹద༻΋Ͱ͖Δ͕ʮશ෦౗͢ʯͱ͍͏࡞ઓͰ΍ͬͨํָ͕

  17. ΍ͬͯΈΑ͏

  18. DBTF •ActiveSupport::Concern ͷ included ϒϩοΫͷ࢖༻ΛݮΒ͍ͨ͠

  19. DBTF •ActiveSupport::Concern ͷ included ϒϩοΫͷ࢖༻ΛݮΒ͍ͨ͠ module EnergeticGreeting extend ActiveSupport::Concern included

    do def hi p '٩(ˊᗜˋ*)و' end end end class GreetingA include EnergeticGreeting end GreetingA.new.hi # => "٩(ˊᗜˋ*)و" •include ͞Εͨ࣌ʹ ϒϩοΫ಺ͷίʔυ͕࣮ߦ͞ΕΔ
  20. •Ϟδϡʔϧ͕ include ͞ΕΔ౓ʹ࣮ߦ͞ΕΔ •ϞδϡʔϧͷΠϯελϯεม਺ʹϒϩοΫΛ࣋ͪଓ͚Δ •ਅͷϝιουఆٛʹؾΛ഑Δඞཁ͕͋Δ •ϦϑΝΫλϦϯάʹ༨ܭͳίετ͕͔͔Δ includedϒϩοΫ ͨ·ʹ࢖͏ʹ͸ ΂ΜΓͩΑ

  21. module DepressedGreeting def hi p 'ʢ◞‸◟ʣ' end end class GreetingB

    include DepressedGreeting end GreetingB.new.hi # => “ʢ◞‸◟ʣ” includedϒϩοΫ •Πϯελϯεϝιου͸ Module#includeͰੜ΍ͤΔ
  22. module EnergeticGreeting extend ActiveSupport::Concern included do def hi p '٩(ˊᗜˋ*)و'

    end end end class GreetingA def hi p 'hi' end include EnergeticGreeting end GreetingA.new.hi # => "٩(ˊᗜˋ*)و" module DepressedGreeting def hi p 'ʢ◞‸◟ʣ' end end class GreetingB def hi p 'hi' end include DepressedGreeting end GreetingB.new.hi # => "hi" ʮਅͷϝιουఆٛʯ
  23. module EnergeticGreeting extend ActiveSupport::Concern included do def hi p '٩(ˊᗜˋ*)و'

    end end end class GreetingA def hi p 'hi' end include EnergeticGreeting end GreetingA.new.hi # => "٩(ˊᗜˋ*)و" ʮਅͷϝιουఆٛʯ module EnergeticGreeting extend ActiveSupport::Concern included do def hi p '٩(ˊᗜˋ*)و' end end end class GreetingA2 include EnergeticGreeting def hi p 'hi' end end GreetingA2.new.hi # => "hi"
  24. •Module#include •Ϋϥεͷܧঝؔ܎ͷؒʹϞδϡʔϧ͕ૠೖ͞ΕΔ •ͨͩͷΦʔϓϯΫϥεͳͷͰݺͼग़͠ݩ͕༏ઌ •ActiveSupport::Concern •ࠇຐज़Λར༻ •هड़͕ޙͷํ͕༏ઌ Ή͔͍ͣ͠Ͷ͐ ʮਅͷϝιουఆٛʯ

  25. module EnergeticGreeting extend ActiveSupport::Concern included do def hi p '٩(ˊᗜˋ*)و'

    end end end class GreetingA def hi p 'hi' end include EnergeticGreeting end GreetingA.new.hi # => "٩(ˊᗜˋ*)و" ʮਅͷϝιουఆٛʯ module EnergeticGreeting extend ActiveSupport::Concern included do def hi p '٩(ˊᗜˋ*)و' end end end class GreetingA2 include EnergeticGreeting def hi p 'hi' end end GreetingA2.new.hi # => "hi"
  26. •Ϟδϡʔϧ͕ include ͞ΕΔ౓ʹ࣮ߦ͞ΕΔ •ϞδϡʔϧͷΠϯελϯεม਺ʹϒϩοΫΛ࣋ͪଓ͚Δ •ਅͷϝιουఆٛʹؾΛ഑Δඞཁ͕͋Δ •ϦϑΝΫλϦϯάʹ༨ܭͳίετ͕͔͔Δ includedϒϩοΫ ࡟আΛࢼΈͨ PullRequest ΋͕͋ͬͨ

    ਅͷϝιουఆٛ໰୊͕ݪҼͰClose
  27. Ϟδϡʔϧ಺ͷϝιου͕࠶ఆٛ͞Ε͍ͯͳ͚Ε͹ included ϒϩοΫΛ֎͍͍ͯ͠ͱݴ͑ΔͷͰ͸

  28. εΫϦϓτσϏϡʔ

  29. •খ࢝͘͞Ίͨ •͜ͷ࣌ͷର৅ϑΝΠϧ͸11ϑΝΠϧ •ϨϏϡʔ͕༰қ •εΫϦϓτ΋ description ʹష͓ͬͯ͘ •ϨϏϡʔͷҰॿʹͳΔ͔΋ •ϑΟʔυόοΫ͕͋ͬͯษڧʹͳͬͨΓ͢Δ εΫϦϓτσϏϡʔ

  30. •`ʢόοΫΫΥʔτʣ •ίϚϯυͱ࣮ͯ͠ߦ͞Εɺͦͷඪ४ग़ྗ͕จࣈྻͱͯ͠༩͑ΒΕΔ •͜ͷதͷจࣈྻ͸μϒϧΫΥʔτͱಉ༷ͷղऍͱࣜల։͕ߦΘΕΔ ΂ΜΓͳಓ۩ͨͪ Ϧςϥϧ 3VCZϦϑΝϨϯεϚχϡΞϧ  IUUQTEPDTSVCZMBOHPSHKBEPDTQFDqJUFSBMIUNMDPNNBOE files =

    `git grep -l "included" -- 'app/controllers'` `git commit -m 'Inline #{namespace}::#{module_name}'`
  31. •git grep •git ؅ཧԼͷϑΝΠϧΛ grep •ਖ਼نදݱͱ͔σΟϨΫτϦࢦఆ(include/exclude)ͱ͔ ͍ΖΜͳΦϓγϣϯ͕͋ͬͯ΂ΜΓ ΂ΜΓͳಓ۩ͨͪ files =

    `git grep -l "included" -- 'app/controllers'`
  32. •File.read •ϑΝΠϧಡΈࠐΈ •ϑΝΠϧύε͕Θ͔Ε͹ಡΈࠐΜͰจࣈྻͱͯ͠ॲཧͰ͖Δ ΂ΜΓͳಓ۩ͨͪ src = File.read File.expand_path(filename) *0SFBE 3VCZϦϑΝϨϯεϚχϡΞϧ

     IUUQTEPDTSVCZMBOHPSHKBNFUIPE*0JSFBEIUNM
  33. •String#scan •Ϩγʔόʹର͠ਖ਼نදݱΛ܁Γฦ͠Ϛον͠ɺ෦෼จࣈྻͷ഑ྻΛฦ͢ •Ϛονάϧʔϓ΋΂ΜΓͦ͏ ΂ΜΓͳಓ۩ͨͪ 4USJOHTDBO 3VCZϦϑΝϨϯεϚχϡΞϧ  IUUQTEPDTSVCZMBOHPSHKBNFUIPE4USJOHJTDBOIUNM methods =

    src.scan(/def (.*)$/).flatten
  34. •sed •จࣈྻΛஔ׵ͨ͠Γ࡟আͨ͠ΓςΩετॲཧͷͰ͖ΔίϚϯυ •ϫϯϥΠφʔͰಛʹ΂ΜΓ ΂ΜΓͳಓ۩ͨͪ TFEίϚϯυcίϚϯυͷ࢖͍ํ -JOVY cIZESPDVMͷϝϞ IUUQTIZESPDVMHJUIVCJPXJLJDPNNBOETTFEIUNM `sed -i

    '' '#{line}d' #{filename}`
  35. DBTF •1Օॴ͔Β͔͠ݺ͹Ε͍ͯͳ͍ϞδϡʔϧΛ࡟আͯ͠ΠϯϥΠϯʹ͍ͨ͠

  36. DBTF •1Օॴ͔Β͔͠ݺ͹Ε͍ͯͳ͍ϞδϡʔϧΛ࡟আͯ͠ΠϯϥΠϯʹ͍ͨ͠ •FatίϯτϩʔϥରࡦʢͨͿΜʣͰϝιουΛϞδϡʔϧʹ੾Γग़͍ͯ͠Δ •ίʔυ͕௥͍ͮΒ͍ •ϦϑΝΫλϦϯά࣌ʹϞδϡʔϧશ෦֬ೝ͢Δඞཁ͕͋ͬͯίετ

  37. DBTF

  38. •String#remove! •จࣈྻ΍ਖ਼نදݱΛड͚औΓɺϚονͨ͠จࣈྻΛ܁Γฦ͠࡟আ͢Δ •ࡶʹ࢖͑Δॻ͖৺஍͕ͱͯ΋͖͢ ΂ΜΓͳಓ۩ͨͪ SFNPWF 4USJOH "1*EPDL IUUQTBQJEPDLDPNSBJMTW4USJOHSFNPWF target_src.remove!( /module

    .*#{module_name}$/, /^\s*extend ActiveSupport::Concern/, /^\s*included do/ )
  39. •String#sub! •จࣈྻ΍ਖ਼نදݱΛड͚औΓɺϚονͨ͠࠷ॳͷจࣈྻΛஔ׵͢Δ •ϑΝΠϧ A ͷ಺༰ΛϑΝΠϧ B ʹ࣋ͬͯ͘Δ࣌ʹ΂ΜΓ ΂ΜΓͳಓ۩ͨͪ 4USJOHTVC 3VCZϦϑΝϨϯεϚχϡΞϧ

     IUUQTEPDTSVCZMBOHPSHKBNFUIPE4USJOHJTVCIUNM src.sub!(/^\s*include #{module_name}$/, target_src)
  40. •String#[] •ୈҰҾ਺ʹਖ਼نදݱɺୈೋҾ਺ʹintegerΛऔͬͯ ୈೋҾ਺൪໨ͷׅހʹϚον͢Δ࠷ॳͷ෦෼จࣈྻΛฦ͢ ΂ΜΓͳಓ۩ͨͪ 4USJOH<> 3VCZϦϑΝϨϯεϚχϡΞϧ  IUUQTEPDTSVCZMBOHPSHKBNFUIPE4USJOHJCEIUNM namespace =

    src[/class (.*?)Controller/, 1]
  41. DBTF •RailsͷϞσϧͷΠϯελϯεϝιουͷ͏ͪ ಛఆͷจࣈྻΛؚΉϞσϧͱϝιουΛྻڍ͍ͨ͠

  42. DBTF

  43. •rails runner •Rails ͷจ຺Ͱ Ruby ίʔυΛ࣮ߦͰ͖Δ •Rails ʹฉ͘ͱ͍Ζ͍Ζڭ͑ͯ͘ΕΔ ΂ΜΓͳಓ۩ͨͪ 3BJMTͷίϚϯυϥΠϯπʔϧ3BJMTΨΠυ

    IUUQTSBJMTHVJEFTKQDPNNBOE@MJOFIUNMSBJMTSVOOFS rails runner script.rb
  44. •Object#methods, Module#instance_methods •Ϩγʔό͕͍࣋ͬͯΔϝιου / ΠϯελϯεϝιουΛҰ๬͢Δ ΂ΜΓͳಓ۩ͨͪ 0CKFDUNFUIPET 3VCZϦϑΝϨϯεϚχϡΞϧ  IUUQTEPDTSVCZMBOHPSHKBNFUIPE0CKFDUJNFUIPETIUNM

    .PEVMFJOTUBODF@NFUIPET 3VCZϦϑΝϨϯεϚχϡΞϧ  IUUQTEPDTSVCZMBOHPSHKBNFUIPE.PEVMFJJOTUBODF@NFUIPETIUNM klass.instance_methods.select { |method| method.to_s.start_with? ‘awesome' }
  45. •Method#source_location •ϝιου͕ ruby Ͱఆٛ͞Ε͍ͯΔ৔߹ίʔυͷϑΝΠϧ໊ͱߦ൪߸Λฦ͢ •ϝιου͕ C Ͱఆٛ͞Ε͍ͯΔ৔߹ nil Λฦ͢ •e.g.

    ϓϩμΫγϣϯίʔυͰఆٛ͞Εͨಛఆͷ໊લͷϝιουΛநग़͢Δ ΂ΜΓͳಓ۩ͨͪ .FUIPETPVSDF@MPDBUJPO 3VCZϦϑΝϨϯεϚχϡΞϧ  IUUQTEPDTSVCZMBOHPSHKBNFUIPE.FUIPEJTPVSDF@MPDBUJPOIUNM if klass.instance_method(:awesome).source_location.first.include? "my_app"
  46. •Method#source •ruby Ͱॻ͔ΕͨϝιουͷίʔυΛऔಘ͢Δ •display ΛݺͿͱਓؒʹ༏͘͠ग़ྗ͢Δ ΂ΜΓͳಓ۩ͨͪ NFUIPE@TPVSDFNFUIPE@TPVSDFSCBUWuCBOJTUFSNFUIPE@TPVSDF IUUQTHJUIVCDPNCBOJTUFSNFUIPE@TPVSDFCMPCWMJCNFUIPE@TPVSDFSC-- if klass.instance_method(method).source

    =~ /\bhi\b/
  47. ·ͱΊ •εΫϦϓτ͸΂ΜΓ •.rb ϑΝΠϧ΋ͨͩͷจࣈྻ •Ruby ΍ Rails ͸͍ΖΜͳ͜ͱΛ஌͍ͬͯΔ •;ͩΜ࢖͍ͬͯΔϝιου΋ݟํΛม͑Δͱੈք͕޿͕Δ

  48. ·ͱΊ ୀ۶ͳ͜ͱ͸ Ruby ʹ͓ئ͍ͯ͠ ͓΋͠Ζ͍͜ͱΛ΍Ζ͏

  49. ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠