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

Automate the boring staff with Ruby

makicamel
December 27, 2020

Automate the boring staff with Ruby

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

makicamel

December 27, 2020
Tweet

More Decks by makicamel

Other Decks in Programming

Transcript

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

    View Slide

  2. w!NBLJDBNFM઒ݪສق

    w3VCZͱϏʔϧɹɹͱ͓ञ͕޷͖
    ࣗݾ঺հ

    View Slide

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

    View Slide

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

    View Slide

  5. ˞೥݄೔ݱࡏ
    "/%1"%
    $ fd application_controller.rb | wc -l
    # => 49
    # => 325
    ˞೥݄೔࣌఺
    $ find . -name application_controller.rb | wc -l
    85%ݮʂ
    ͍͢͝Ͷ

    View Slide

  6. ॳख
    •ͻͱͭͻͱͭखͰஔ͖׵͑Δ
    •σΟϨΫτϦຖʹ౗͍͚ͯ͠͹͍͍͸ͣ
    •ࠓ·Ͱͷ׳ྫ΋कΒΕͯແடংʹͳΒͳ͍
    •2 PullRequests Ͱ໿ 40 ϑΝΠϧ࡟আ
    •࣌ؒͱࠜؾͱूதྗͷඞཁͳ࡞ۀ

    View Slide

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

    View Slide

  8. ཌ݄༵೔

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  17. ΍ͬͯΈΑ͏

    View Slide

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

    View Slide

  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 ͞Εͨ࣌ʹ
    ϒϩοΫ಺ͷίʔυ͕࣮ߦ͞ΕΔ

    View Slide

  20. •Ϟδϡʔϧ͕ include ͞ΕΔ౓ʹ࣮ߦ͞ΕΔ
    •ϞδϡʔϧͷΠϯελϯεม਺ʹϒϩοΫΛ࣋ͪଓ͚Δ
    •ਅͷϝιουఆٛʹؾΛ഑Δඞཁ͕͋Δ
    •ϦϑΝΫλϦϯάʹ༨ܭͳίετ͕͔͔Δ
    includedϒϩοΫ
    ͨ·ʹ࢖͏ʹ͸
    ΂ΜΓͩΑ

    View Slide

  21. module DepressedGreeting
    def hi
    p 'ʢ◞‸◟ʣ'
    end
    end
    class GreetingB
    include DepressedGreeting
    end
    GreetingB.new.hi
    # => “ʢ◞‸◟ʣ”
    includedϒϩοΫ
    •Πϯελϯεϝιου͸
    Module#includeͰੜ΍ͤΔ

    View Slide

  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"
    ʮਅͷϝιουఆٛʯ

    View Slide

  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"

    View Slide

  24. •Module#include
    •Ϋϥεͷܧঝؔ܎ͷؒʹϞδϡʔϧ͕ૠೖ͞ΕΔ
    •ͨͩͷΦʔϓϯΫϥεͳͷͰݺͼग़͠ݩ͕༏ઌ
    •ActiveSupport::Concern
    •ࠇຐज़Λར༻
    •هड़͕ޙͷํ͕༏ઌ
    Ή͔͍ͣ͠Ͷ͐
    ʮਅͷϝιουఆٛʯ

    View Slide

  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"

    View Slide

  26. •Ϟδϡʔϧ͕ include ͞ΕΔ౓ʹ࣮ߦ͞ΕΔ
    •ϞδϡʔϧͷΠϯελϯεม਺ʹϒϩοΫΛ࣋ͪଓ͚Δ
    •ਅͷϝιουఆٛʹؾΛ഑Δඞཁ͕͋Δ
    •ϦϑΝΫλϦϯάʹ༨ܭͳίετ͕͔͔Δ
    includedϒϩοΫ
    ࡟আΛࢼΈͨ PullRequest ΋͕͋ͬͨ
    ਅͷϝιουఆٛ໰୊͕ݪҼͰClose

    View Slide

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

    View Slide

  28. εΫϦϓτσϏϡʔ

    View Slide

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

    View Slide

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

    IUUQTEPDTSVCZMBOHPSHKBEPDTQFDqJUFSBMIUNMDPNNBOE
    files = `git grep -l "included" -- 'app/controllers'`
    `git commit -m 'Inline #{namespace}::#{module_name}'`

    View Slide

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

    View Slide

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

    IUUQTEPDTSVCZMBOHPSHKBNFUIPE*0JSFBEIUNM

    View Slide

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

    IUUQTEPDTSVCZMBOHPSHKBNFUIPE4USJOHJTDBOIUNM
    methods = src.scan(/def (.*)$/).flatten

    View Slide

  34. •sed
    •จࣈྻΛஔ׵ͨ͠Γ࡟আͨ͠ΓςΩετॲཧͷͰ͖ΔίϚϯυ
    •ϫϯϥΠφʔͰಛʹ΂ΜΓ
    ΂ΜΓͳಓ۩ͨͪ
    TFEίϚϯυcίϚϯυͷ࢖͍ํ -JOVY
    cIZESPDVMͷϝϞ
    IUUQTIZESPDVMHJUIVCJPXJLJDPNNBOETTFEIUNM
    `sed -i '' '#{line}d' #{filename}`

    View Slide

  35. DBTF
    •1Օॴ͔Β͔͠ݺ͹Ε͍ͯͳ͍ϞδϡʔϧΛ࡟আͯ͠ΠϯϥΠϯʹ͍ͨ͠

    View Slide

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

    View Slide

  37. DBTF

    View Slide

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

    View Slide

  39. •String#sub!
    •จࣈྻ΍ਖ਼نදݱΛड͚औΓɺϚονͨ͠࠷ॳͷจࣈྻΛஔ׵͢Δ
    •ϑΝΠϧ A ͷ಺༰ΛϑΝΠϧ B ʹ࣋ͬͯ͘Δ࣌ʹ΂ΜΓ
    ΂ΜΓͳಓ۩ͨͪ
    4USJOHTVC 3VCZϦϑΝϨϯεϚχϡΞϧ

    IUUQTEPDTSVCZMBOHPSHKBNFUIPE4USJOHJTVCIUNM
    src.sub!(/^\s*include #{module_name}$/, target_src)

    View Slide

  40. •String#[]
    •ୈҰҾ਺ʹਖ਼نදݱɺୈೋҾ਺ʹintegerΛऔͬͯ
    ୈೋҾ਺൪໨ͷׅހʹϚον͢Δ࠷ॳͷ෦෼จࣈྻΛฦ͢
    ΂ΜΓͳಓ۩ͨͪ
    4USJOH<> 3VCZϦϑΝϨϯεϚχϡΞϧ

    IUUQTEPDTSVCZMBOHPSHKBNFUIPE4USJOHJCEIUNM
    namespace = src[/class (.*?)Controller/, 1]

    View Slide

  41. DBTF
    •RailsͷϞσϧͷΠϯελϯεϝιουͷ͏ͪ
    ಛఆͷจࣈྻΛؚΉϞσϧͱϝιουΛྻڍ͍ͨ͠

    View Slide

  42. DBTF

    View Slide

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

    View Slide

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

    IUUQTEPDTSVCZMBOHPSHKBNFUIPE0CKFDUJNFUIPETIUNM
    [email protected] 3VCZϦϑΝϨϯεϚχϡΞϧ

    [email protected]
    klass.instance_methods.select { |method| method.to_s.start_with? ‘awesome' }

    View Slide

  45. •Method#source_location
    •ϝιου͕ ruby Ͱఆٛ͞Ε͍ͯΔ৔߹ίʔυͷϑΝΠϧ໊ͱߦ൪߸Λฦ͢
    •ϝιου͕ C Ͱఆٛ͞Ε͍ͯΔ৔߹ nil Λฦ͢
    •e.g. ϓϩμΫγϣϯίʔυͰఆٛ͞Εͨಛఆͷ໊લͷϝιουΛநग़͢Δ
    ΂ΜΓͳಓ۩ͨͪ
    [email protected] 3VCZϦϑΝϨϯεϚχϡΞϧ

    [email protected]
    if klass.instance_method(:awesome).source_location.first.include? "my_app"

    View Slide

  46. •Method#source
    •ruby Ͱॻ͔ΕͨϝιουͷίʔυΛऔಘ͢Δ
    •display ΛݺͿͱਓؒʹ༏͘͠ग़ྗ͢Δ
    ΂ΜΓͳಓ۩ͨͪ
    [email protected]@[email protected]
    [email protected]@TPVSDFSC--
    if klass.instance_method(method).source =~ /\bhi\b/

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide