Slide 1

Slide 1 text

©2020 Wantedly, Inc. Wrap every method With just another line Meguro.rb#30 Jan 31, 2020 - Shimpei Otsubo

Slide 2

Slide 2 text

©2020 Wantedly, Inc. Shimpei Otsubo @potsbo Developer Experience Squad, Wantedly, Inc. Kubernetes Dev Tools CI / CD AuthN / Z Productivity Dvorak

Slide 3

Slide 3 text

©2020 Wantedly, Inc. AB ςετ͕೉͍͠໰୊ ςετ͕ͮ͠Β͘ͳΔ ࣗಈ΋खಈ΋ ޙΖଆͷϚΠΫϩαʔϏεͰߦ͏ͱ؅ཧෆೳ Ұ൪લͳΒport-forwardͱ͔Ͱߦ͚Δ͕ʜ ˞αʔϏεϝογϡͰղܾ͍ͨ͠ϨΠϠͰ΋͋Δʜ $4͕ࠞཚ ਓʹΑͬͯڍಈ͕ҟͳΔࣄ͕͋ͬͯ΋Կނ͔Θ͔Βͳ͍

Slide 4

Slide 4 text

©2020 Wantedly, Inc. AB ςετΛ؆୯ʹτάϧͰ͖Δextension࡞ͬͨ ˞ը૾͸αϯϓϧͰ͢ ͲΜͳflagͰࠓͷϖʔδ͕render͞Ε͔ͨΘ͔Δ ͲΜͳflagͰࠓͷϖʔδΛrenderͯ͠΄͍͔͠ࢦఆͰ͖Δ

Slide 5

Slide 5 text

©2020 Wantedly, Inc. Thread.current resp header middleware ͲΜͳ஋Λ࢖͔ͬͨʁΛfeedback ͲΜͳ஋Λ࢖ͬͯ΄͍͔͠ʁΛࢦఆ Thread.current req header Header Λհͯ͠ methodͷධՁ஋Λ read /write )FBEFSͳͷͰNJDSPTFSWJDFͰ఻ൖՄೳ call return

Slide 6

Slide 6 text

©2020 Wantedly, Inc. ڵຯର৅ͷNFUIPEʹ͢΂ͯΛIPPL͢Δඞཁ͕͋Δ ͜ͷͨΊʹ͸

Slide 7

Slide 7 text

©2020 Wantedly, Inc. class Experiment def self.enable?(name, target) # some consistent logic here end end Experiment.enable?(:show_new_button, current_user) # => true or false Wantedly ʹ͓͚ΔABςετͷํ๏ ಉҰͷuserʹରͯ͠͸ৗʹಉҰͷboolean͕ฦΔmethod

Slide 8

Slide 8 text

©2020 Wantedly, Inc. Thread.current͔Βuser͕ࢦఆͨ͠஋͕͋Ε͹ͦΕΛར༻ ͳ͚Ε͹Thread.currentʹར༻ͨ͠஋Λ٧ΊΔ class Experiment def self.enable?(name, target) # some consistent logic here end def self.wrapped_enable?(name, target) request_value = Thread.current[:request][name] return request_value unless request_value.nil? actual_value = enable?(name, target) Thread.current[:response][name] = actual_value end end ˞Thread.currentͱheaderͷؒΛͭͳ͙middlewareΛผ్༻ҙ

Slide 9

Slide 9 text

©2020 Wantedly, Inc. Renameͯͦ͠ͷ··࢖͑ΔΑ͏ʹ͢Δ class Experiment def self.real_enable?(name, target) # some consistent logic here end def self.enable?(name, target) request_value = Thread.current[:request][name] return request_value unless request_value.nil? actual_value = real_enable?(name, target) Thread.current[:response][name] = actual_value end end

Slide 10

Slide 10 text

©2020 Wantedly, Inc. ҰൠԽͯ͠ΈΔ class FeatureFlag def self.intercept(name) request_value = Thread.current[:request][name] return request_value unless request_value.nil? actual_value = yield Thread.current[:response][name] = actual_value end end class Experiment def self.real_enable?(name, target) # some consistent logic here end def self.enable?(name, target) FeatureFlag.intercept(name) do real_enable?(name, target) end end end ϒϩοΫͰғΈ͑͢͞Ε͹Ͳ͜Ͱ΋PWFSSJEFՄೳʂ

Slide 11

Slide 11 text

©2020 Wantedly, Inc. ଞͷػೳͷग़͠෼͚ʹ΋࢖͑Δ͸ͣ

Slide 12

Slide 12 text

©2020 Wantedly, Inc. Helperͷ͍ΖΜͳmethod ͰػೳΛग़͠෼͚͍ͯ͠Δ৔ॴ͕͋Δ module I18nHelper # the new landing page currently supports only Japanese!! def show_new_landing_page? I18n.locale == :ja end end

Slide 13

Slide 13 text

©2020 Wantedly, Inc. ϒϩοΫͰғΉ͚ͩͰXSBQͰ͖Δ class FeatureFlag def self.intercept(name) ... end end module I18nHelper # the new landing page currently supports only Japanese!! def show_new_landing_page? FeatureFlag.intercept(:show_new_landing_page?) do I18n.locale == :ja end end end

Slide 14

Slide 14 text

©2020 Wantedly, Inc. ϒϩοΫͰғΉ͚ͩͰXSBQͰ͖Δ class FeatureFlag def self.intercept(name) ... end end module I18nHelper # the new landing page currently supports only Japanese!! def show_new_landing_page? FeatureFlag.intercept(:show_new_landing_page?) do I18n.locale == :ja end end end ຖճॻ͘ͷ͸ྲྀੴʹ໘౗

Slide 15

Slide 15 text

©2020 Wantedly, Inc. class FeatureFlag def self.intercept(name) ... end end module I18nHelper # the new landing page currently supports only Japanese!! def show_new_landing_page? FeatureFlag.intercept(:show_new_landing_page?) do I18n.locale == :ja end end end खಈͰίʔυΛ͍͡ΔͷͰ͸ͳ͘

Slide 16

Slide 16 text

©2020 Wantedly, Inc. class FeatureFlag def self.intercept(name) ... end end module I18nHelper include FeatureFlag def show_new_landing_page? I18n.locale == :ja end end *ODMVEF͚ͩͰղܾͰ͖ͨΒ޾ͤ Ұߦ௥Ճ͢Δ͚ͩʂʂ

Slide 17

Slide 17 text

©2020 Wantedly, Inc. Ͱ͖ΔΑ͏ʹͨ͠ module FeatureFlag def self.included(base) base.class_eval do extend ClassMethods @_already_patched = [] @_patch_target = base end end module ClassMethods def intercept(name) ... end def method_added(name) if !@_already_patched.include?(name) && self == @_patch_target orig_method_name = "_#{base}_orig".to_sym @_already_patched << name @_already_patched << orig_method_name alias_method orig_method_name, name

Slide 18

Slide 18 text

©2020 Wantedly, Inc. ॳظԽ module FeatureFlag def self.included(base) base.class_eval do extend ClassMethods @_already_patched = [] @_patch_target = base end end module ClassMethods def intercept(name) ... end def method_added(name) if !@_already_patched.include?(name) && self == @_patch_target orig_method_name = "_#{base}_orig".to_sym @_already_patched << name @_already_patched << orig_method_name alias_method orig_method_name, name ͲͷNPEVMFͰJODMVEFͨ͠ͷ͔͓֮͑ͯ͘

Slide 19

Slide 19 text

©2020 Wantedly, Inc. module ClassMethods def intercept(name) ... end def method_added(name) if !@_already_patched.include?(name) && self == @_patch_target orig_method_name = "_#{base}_orig".to_sym @_already_patched << name @_already_patched << orig_method_name alias_method orig_method_name, name private orig_method_name define_method(name) do |*args| intercept(name) do send(old_name, *args) end end end super end end end ͢ͰʹXSBQ͍ͯ͠ͳ͍͔ͷ֬ೝ

Slide 20

Slide 20 text

©2020 Wantedly, Inc. module ClassMethods def intercept(name) ... end def method_added(name) if !@_already_patched.include?(name) && self == @_patch_target orig_method_name = "_#{base}_orig".to_sym @_already_patched << name @_already_patched << orig_method_name alias_method orig_method_name, name private orig_method_name define_method(name) do |*args| intercept(name) do send(old_name, *args) end end end super end end end طଘ࣮૷ͷୀආ

Slide 21

Slide 21 text

©2020 Wantedly, Inc. module ClassMethods def intercept(name) ... end def method_added(name) if !@_already_patched.include?(name) && self == @_patch_target orig_method_name = "_#{base}_orig".to_sym @_already_patched << name @_already_patched << orig_method_name alias_method orig_method_name, name private orig_method_name define_method(name) do |*args| intercept(name) do send(old_name, *args) end end end super end end end 8SBQ࣮૷

Slide 22

Slide 22 text

©2020 Wantedly, Inc. αʔόʔͷڍಈ͕ݟ͑Δม͑ΒΕΔͱָ *ODMVEF͚ͩͰ͢΂ͯͷNFUIPEXSBQ͸Մೳ ଞʹ΋͍Ζ͍Ζͳ֦ு͕Ͱ͖Δ ςετ΋σόοά΋ NFUIPE@BEEFEͰ௥Ճ͞ΕͨNFUIPEΛ͍͡Ε͹ྑ͍ XSBQ@POMZGPP CBSͱ͔΋࡞ΕΔ