davideisinger.com

My personal website
Log | Files | Refs | README

dev-to-pywrcp.txt (26200B)


      1 [1]Skip to content
      2 [3] DEV Community
      3 [4][                    ]
      4 [6]
      5 [7] Log in [8] Create account
      6 
      7 DEV Community
      8 
      9 ● Add reaction
     10 [sp] Like [mu] Unicorn [ex] Exploding Head [ra] Raised Hands [fi] Fire
     11 Jump to Comments Save
     12 Copy link
     13 Copied to Clipboard
     14 [20] Share to Twitter [21] Share to LinkedIn [22] Share to Reddit [23] Share to
     15 Hacker News [24] Share to Facebook [25] Share to Mastodon
     16 [26]Share Post via... [27]Report Abuse
     17 [28] Cover image for Decorating Ruby - Part Two - Method Added Decoration
     18 [29]Brandon Weaver
     19 [30]Brandon Weaver
     20 
     21 Posted on Aug 18, 2019 • Updated on Jan 21, 2021
     22 
     23 ●   ●   ●   ●   ●  
     24 
     25 Decorating Ruby - Part Two - Method Added Decoration
     26 
     27 [31]#ruby
     28 
     29 [32]Decorating Ruby (3 Part Series)
     30 
     31 [33] 1 Decorating Ruby - Part One - Symbol Method Decoration [34] 2 Decorating
     32 Ruby - Part Two - Method Added Decoration [35] 3 Decorating Ruby - Part Three -
     33 Prepending Decoration
     34 
     35 One precursor of me writing an article is if I keep forgetting how something's
     36 done, causing me to write a reference to look back on for later. This is one
     37 such article.
     38 
     39 [36] What's in Store for Today?
     40 
     41 We'll be looking at the next type of decoration, which involves intercepting
     42 method_added to make a more fluent interface.
     43 
     44 [37]The "Dark Lord" Crimson with Metaprogramming magic
     45 
     46 Table of Contents
     47 
     48   • [38]Part One - Symbol Method Decoration
     49   • [39]Part Two - Method Added Decoration
     50   • [40]Part Three - Prepending Decoration
     51 
     52 [41]<< Previous | [42]Next >>
     53 
     54 [43] What Does Method Added Decoration Look Like?
     55 
     56 You've seen the Symbol Method variant:
     57 
     58 private def something; end
     59 
     60 Readers that were paying very close attention in the last article may have
     61 noticed when I said that I preferred that style of declaring private methods in
     62 Ruby, but this was after the way that can be debatably considered more popular
     63 and widely used in the community:
     64 
     65 private
     66 
     67 def something; end
     68 def something_else; end
     69 
     70 Using private like this means that every method defined after will be
     71 considered private. We know how the first one works, but what about the second?
     72 There's no way it's using method names because it catches both of those methods
     73 and doesn't change the definition syntax.
     74 
     75 That's what we'll be looking into and learning today, and let me tell you it's
     76 a metaprogramming trip.
     77 
     78 [44] Making Our Own Method Added Decoration
     79 
     80 As with the last article we're going to need to learn about a few tools before
     81 we'll be ready to implement this one.
     82 
     83 [45] Module Inclusion
     84 
     85 Ruby uses Module inclusion as a way to extend classes with additional behavior,
     86 sometimes requiring an interface to be met before it can do so. Enumerable is
     87 one of the most common, and requires an each implementation to work:
     88 
     89 class Collection
     90   include Enumerable
     91 
     92   def initialize(*items)
     93     @items = items
     94   end
     95 
     96   def each(&fn)
     97     return @items.to_enum unless block_given?
     98     @items.each { |item| fn.call(item) }
     99   end
    100 end
    101 
    102 (yield could be used here instead, but is less explicit and can be confusing to
    103 teach.)
    104 
    105 By defining that one method we've given our class the ability to do all types
    106 of amazing things like map, select, and more.
    107 
    108 Through those few lines we've added a lot of functionality to a class. Here's
    109 the interesting part about Ruby: it also provides hooks to let Enumerable know
    110 it was included, including what included it.
    111 
    112 [46] Feeling Included
    113 
    114 Let's say we have our own module, [47]Affable, which gives us a method to say
    115 "hi":
    116 
    117 module Affable
    118   def greeting
    119     "It's so very lovely to see you today!"
    120   end
    121 end
    122 
    123 My, it is quite an [48]Affable module, now isn't it?
    124 
    125 We could even go as far as to make a particularly Affable lemur:
    126 
    127 class Lemur
    128   include Affable
    129   def initialize(name) @name = name; end
    130 end
    131 
    132 Lemur.new("Indigo").greeting
    133 => "It's so very lovely to see you today!"
    134 
    135 What a classy lemur, yes.
    136 
    137 [49] Hook, Line, and Sinker
    138 
    139 Let's say that we wanted to tell what particular animal was Affable. We can use
    140 included to see just that:
    141 
    142 module Affable
    143   def self.included(klass)
    144     puts "#{klass.name} has become extra Affable!"
    145   end
    146 end
    147 
    148 If we were to re-include that module:
    149 
    150 class Lemur
    151   include Affable
    152   def initialize(name) @name = name; end
    153 end
    154 
    155 # STDOUT: Lemur has become extra Affable!
    156 # => :initialize
    157 
    158 Right classy. Oh, right, speaking of classy...
    159 
    160 [50] Extra Classy Indeed
    161 
    162 So we can hook inclusion of a module, great! Why do we care?
    163 
    164 What if we wanted to both include methods into a class as well as extend its
    165 behavior?
    166 
    167 With just include it will apply all the behavior to instances of a class. With
    168 just extend it will apply all the behavior to the class itself. We can't do
    169 both.
    170 
    171 ...ok ok, it's Ruby, you caught me, we can totally do both.
    172 
    173 As it turns out, include and extend are just methods on a class. We could just
    174 Lemur.extend(ExtraBehavior) if we wanted to, or we could use our fun little
    175 hooks from earlier.
    176 
    177 A common convention for using this technique is a sub-module called
    178 ClassMethods, like so:
    179 
    180 module Affable
    181   def self.included(klass)
    182     klass.extend(ClassMethods)
    183   end
    184 
    185   module ClassMethods
    186     def affable?
    187       true
    188     end
    189   end
    190 end
    191 
    192 This allows us to inject behavior directly into the class as well as other
    193 behavior we want to include in instances.
    194 
    195 Part of me thinks this is so I don't have to remember the difference between
    196 include and extend, but I always remember that and don't have to spend 20
    197 minutes flipping between the two and prepend to see which one actually works,
    198 absolutely not.
    199 
    200 Now remember the title about Method Added being the technique for today? Oh
    201 yes, there's a hook for that as well, but first we need to indicate that
    202 something needs to be hooked in the first place.
    203 
    204 [51] Raise Your Flag
    205 
    206 We can intercept a method being added, but how do we know which method should
    207 be intercepted? We'd need to add a flag to let that hook know it's time to
    208 start intercepting in full force.
    209 
    210 module Affable
    211   def self.included(klass)
    212     klass.extend(ClassMethods)
    213   end
    214 
    215   module ClassMethods
    216     def extra_affable
    217       @extra_affable = true
    218     end
    219   end
    220 end
    221 
    222 If you remember private, this could be the flag to indicate that every method
    223 afterwards should be private:
    224 
    225 private
    226 
    227 def something; end
    228 def something_else; end
    229 
    230 Same idea here, and once a flag is raised it can also be taken down to make
    231 sure later methods aren't impacted as well. We keep hinting at hooking method
    232 added, so let's go ahead and do just that.
    233 
    234 [52] Method Added
    235 
    236 Now that we have our flag, we have enough to hook into method_added:
    237 
    238 module Affable
    239   def self.included(klass)
    240     klass.extend(ClassMethods)
    241   end
    242 
    243   module ClassMethods
    244     def extra_affable
    245       @extra_affable = true
    246     end
    247 
    248     def method_added(method_name)
    249       return unless @extra_affable
    250 
    251       @extra_affable = false
    252       # ...
    253     end
    254   end
    255 end
    256 
    257 We can use our flag to ignore method_added unless said flag is set. After we
    258 check that, we can take down the flag to make sure additional methods defined
    259 after aren't affected as well. For private this doesn't happen, but we want to
    260 be polite. It is and Affable module after all.
    261 
    262 [53] Politely Aliasing
    263 
    264 Speaking of politeness, it's not precisely kind to just overwrite a method
    265 without giving a way to call it as it was. We can use alias_method to get a new
    266 name to the method before we overwrite it:
    267 
    268 def method_added(method_name)
    269   return unless @extra_affable
    270 
    271   @extra_affable = false
    272 
    273   original_method_name = "#{method_name}_without_affability".to_sym
    274   alias_method original_method_name, method_name
    275 end
    276 
    277 This means that we can access the original method through this name.
    278 
    279 [54] Wrap Battle
    280 
    281 So we have the original method aliased, our hook in place, let's get to
    282 overwriting that method then! As with the last tutorial we can use
    283 define_method to do this:
    284 
    285 module Affable
    286   def self.included(klass)
    287     klass.extend(ClassMethods)
    288   end
    289 
    290   module ClassMethods
    291     def extra_affable
    292       @extra_affable = true
    293     end
    294 
    295     def method_added(method_name)
    296       return unless @extra_affable
    297 
    298       @extra_affable = false
    299 
    300       original_method_name = "#{method_name}_without_affability".to_sym
    301       alias_method original_method_name, method_name
    302 
    303       define_method(method_name) do |*args, &fn|
    304         original_result = send(original_method_name, *args, &fn)
    305 
    306         "#{original_result} Very lovely indeed!"
    307       end
    308     end
    309   end
    310 end
    311 
    312 Overwriting our original class again:
    313 
    314 class Lemur
    315   include Affable
    316 
    317   def initialize(name) @name = name; end
    318 
    319   extra_affable
    320 
    321   def farewell
    322     "Farewell! It was lovely to chat."
    323   end
    324 end
    325 
    326 We can give it a try:
    327 
    328 Lemur.new("Indigo").farewell
    329 => "Farewell! It was lovely to chat. Very lovely indeed!"
    330 
    331 [55] send Help!
    332 
    333 Wait wait wait wait, send? Didn't we use method last time?
    334 
    335 We did, but remember that method_added is a class method that does not have the
    336 context of an instance of the class, or in other words it has no idea where the
    337 farewell method is located.
    338 
    339 send lets us treat this as an instance again by sending the method name
    340 directly. Now we could use method inside of here as well, but that can be a bit
    341 more expensive.
    342 
    343 Only the contents inside define_method's block are executed in the context of
    344 the instance.
    345 
    346 [56] executive Functions
    347 
    348 If we wanted to, we could have our special method take blocks which execute in
    349 the context of an instance as well, and this is an extra special bonus trick
    350 for this post.
    351 
    352 Say that we made extra_affable also take a block that allows us to manipulate
    353 the original value and still execute in the context of the instance:
    354 
    355 class Lemur
    356   include Affable
    357 
    358   def initialize(name) @name = name; end
    359 
    360   extra_affable { |original|
    361     "#{@name}: #{original} Very lovely indeed!"
    362   }
    363 
    364   def farewell
    365     "Farewell! It was lovely to chat."
    366   end
    367 end
    368 
    369 With normal blocks, this will evaluate in the context of the class, but we want
    370 it to evaluate in the context of the instance instead. That's what we have
    371 instance_exec for:
    372 
    373 module Affable
    374   def self.included(klass)
    375     klass.extend(ClassMethods)
    376   end
    377 
    378   module ClassMethods
    379     def extra_affable(&fn)
    380       @extra_affable    = true
    381       @extra_affable_fn = fn
    382     end
    383 
    384     def method_added(method_name)
    385       return unless @extra_affable
    386 
    387       @extra_affable   = false
    388       extra_affable_fn = @extra_affable_fn
    389 
    390       original_method_name = "#{method_name}_without_affability".to_sym
    391       alias_method original_method_name, method_name
    392 
    393       define_method(method_name) do |*args, &fn|
    394         original_result = send(original_method_name, *args, &fn)
    395         instance_exec(original_result, &extra_affable_fn)
    396       end
    397     end
    398   end
    399 end
    400 
    401 Running that gives us this:
    402 
    403 Lemur.new("Indigo").farewell
    404 # => "Indigo: Farewell! It was lovely to chat. Very lovely indeed!"
    405 
    406 Now pay very close attention to this line:
    407 
    408 extra_affable_fn = @extra_affable_fn
    409 
    410 We need to use this because inside define_method's block is inside the
    411 instance, which has no clue what @extra_affable_fn is. That said, it can still
    412 see outside to the context where the block was called, meaning it can see that
    413 local version of extra_affable_fn sitting right there, allowing us to call it:
    414 
    415 instance_exec(original_result, &extra_affable_fn)
    416 
    417 [57] instance_eval vs instance_exec?
    418 
    419 Why not use instance_eval? instance_exec allows us to pass along arguments as
    420 well, otherwise instance_eval would make a lot of sense to evaluate something
    421 in an instance. Instead, we need to execute something in the context of an
    422 instance, so we use instance_exec here.
    423 
    424 [58] Wrapping Up
    425 
    426 So that was quite a lot of magic, and it took me a fair bit to really
    427 understand what some of it was doing and why. That's perfectly ok, if I
    428 understood everything the first time I'd be worried because that means I'm not
    429 really learning anything!
    430 
    431 One issue I think this will have later is I wonder how poorly having multiple
    432 hooks to method_added will work. If it turns out it makes things go boom in a
    433 spectacularly pretty and confounding way there'll be a part three. If not, this
    434 paragraph will disappear and I'll pretend to not know what you're talking about
    435 if you ask me about it.
    436 
    437 There's a lot of potential here for some really interesting things, but there's
    438 also a lot of potential for abuse. Be sure to not abuse such magic, because for
    439 every layer of redefinition code can become increasingly harder to reason about
    440 and test later.
    441 
    442 In most cases I would instead advocate for SimpleDelegate, Forwardable, or
    443 simple inheritance with super to extend behavior of classes. Don't use a
    444 chainsaw where hedge trimmers will do, but on occasion it's nice to know a
    445 chainsaw is there for those particularly gnarly problems.
    446 
    447 Discretion is the name of the game.
    448 
    449 Table of Contents
    450 
    451   • [59]Part One - Symbol Method Decoration
    452   • [60]Part Two - Method Added Decoration
    453   • [61]Part Three - Prepending Decoration
    454 
    455 [62]<< Previous | [63]Next >>
    456 
    457 [64]Decorating Ruby (3 Part Series)
    458 
    459 [65] 1 Decorating Ruby - Part One - Symbol Method Decoration [66] 2 Decorating
    460 Ruby - Part Two - Method Added Decoration [67] 3 Decorating Ruby - Part Three -
    461 Prepending Decoration
    462 
    463 Top comments (2)
    464 
    465 Subscribe
    466 pic
    467 [                    ]
    468 Personal Trusted User
    469 [75] Create template
    470 
    471 Templates let you quickly answer FAQs or store snippets for re-use.
    472 
    473 Submit Preview [78]Dismiss
    474  
    475 [79] edisonywh profile image
    476 [80] Edison Yap
    477 Edison Yap
    478 [82] [https] Edison Yap
    479 Follow
    480 An aspiring software engineer from the tiny city of Kuala Lumpur.
    481 
    482   • Location
    483     Stockholm, Sweden
    484   • Education
    485     RMIT University, Melbourne
    486   • Work
    487     Software Engineer at Klarna
    488   • Joined
    489     Jul 25, 2018
    490 
    491 • [84] Aug 18 '19 • Edited on Aug 18 • Edited
    492 
    493   • [86]Copy link
    494    495   • Hide
    496    497    498    499 
    500 Wow this is really cool, thanks for sharing Brandon!
    501 
    502 Is there a way to hook onto the last method_added? For example I'd like to
    503 execute something after all methods are added
    504 
    505 EDIT: also quick search online seems to say that method_added only works for
    506 instance methods, but there's singleton_method_added hook for class methods
    507 too!
    508 
    509 1 like Like [89] Reply
    510  
    511 [90] baweaver profile image
    512 [91] Brandon Weaver
    513 Brandon Weaver
    514 [93] [https] Brandon Weaver
    515 Follow
    516 Principal Ruby Engineer at Gusto on Payroll Services. Autistic / ADHD, He /
    517 Him. I'm the Lemur guy.
    518 
    519   • Location
    520     San Francisco, CA
    521   • Work
    522     Principal Engineer - Payroll Services at Gusto
    523   • Joined
    524     Jan 16, 2019
    525 
    526 • [95] Aug 18 '19 • Edited on Aug 18 • Edited
    527 
    528   • [97]Copy link
    529    530   • Hide
    531    532    533    534 
    535 Technically in Ruby there's never a point in which methods are no longer added,
    536 so it's a bit hard to hook that. One potential is to use TracePoint to hook the
    537 ending of a class definition and retaining a class of "infected" classes, but
    538 that'd be slow.
    539 
    540 Look for "Class End Event" in this article: [99]medium.com/@baweaver/
    541 exploring-tra...
    542 
    543 EDIT - ...though now I'm curious if one could use such things to freeze a class
    544 from modifications.
    545 
    546 1 like Like [101] Reply
    547 [102]Code of Conduct • [103]Report abuse
    548 
    549 Are you sure you want to hide this comment? It will become hidden in your post,
    550 but will still be visible via the comment's [107]permalink.
    551 
    552 [109][ ]
    553 
    554 Hide child comments as well
    555 
    556 Confirm
    557 
    558 For further actions, you may consider blocking this person and/or [111]
    559 reporting abuse
    560 
    561 Read next
    562 
    563 [112]
    564 cherryramatis profile image
    565 
    566 Bringing more sweetness to Ruby with Sorbet types 🍦
    567 
    568 Cherry Ramatis - Sep 18 '23
    569 
    570 [113]
    571 hungle00 profile image
    572 
    573 Ruby's main object
    574 
    575 hungle00 - Oct 1 '23
    576 
    577 [114]
    578 braindeaf profile image
    579 
    580 Making a YouTube Short
    581 
    582 RobL - Sep 28 '23
    583 
    584 [115]
    585 iberianpig profile image
    586 
    587 Enhance Your Touchpad Experience on Linux with ThumbSense!
    588 
    589 Kohei Yamada - Sep 27 '23
    590 
    591 [116] [https] Brandon Weaver
    592 Follow
    593 Principal Ruby Engineer at Gusto on Payroll Services. Autistic / ADHD, He /
    594 Him. I'm the Lemur guy.
    595 
    596   • Location
    597     San Francisco, CA
    598   • Work
    599     Principal Engineer - Payroll Services at Gusto
    600   • Joined
    601     Jan 16, 2019
    602 
    603 More from [118]Brandon Weaver
    604 
    605 [119] Understanding Ruby - Memoization
    606 #ruby #beginners
    607 [120] In Favor of Ruby Central Memberships
    608 #ruby #community
    609 [121] Pattern Matching Interfaces in Ruby
    610 #ruby #rails #functional
    611 
    612 Once suspended, baweaver will not be able to comment or publish posts until
    613 their suspension is removed.
    614 
    615       [                                                                      ]
    616       [                                                                      ]
    617       [                                                                      ]
    618 Note: [                                                                      ]
    619 
    620 Submit & Suspend
    621 
    622 Once unsuspended, baweaver will be able to comment and publish posts again.
    623 
    624       [                                                                      ]
    625       [                                                                      ]
    626       [                                                                      ]
    627 Note: [                                                                      ]
    628 
    629 Submit & Unsuspend
    630 
    631 Once unpublished, all posts by baweaver will become hidden and only accessible
    632 to themselves.
    633 
    634 If baweaver is not suspended, they can still re-publish their posts from their
    635 dashboard.
    636 
    637 Note:[                    ]
    638 
    639 Unpublish all posts
    640 
    641 Once unpublished, this post will become invisible to the public and only
    642 accessible to Brandon Weaver.
    643 
    644 They can still re-publish the post if they are not suspended.
    645 
    646 Unpublish Post
    647 
    648 Thanks for keeping DEV Community safe. Here is what you can do to flag
    649 baweaver:
    650 
    651 [129]( ) Make all posts by baweaver less visible
    652 
    653 baweaver consistently posts content that violates DEV Community's code of
    654 conduct because it is harassing, offensive or spammy.
    655 
    656 [130] Report other inappropriate conduct
    657 
    658 Confirm Flag
    659 
    660 Unflagging baweaver will restore default visibility to their posts.
    661 
    662 Confirm Unflag
    663 
    664 [133]DEV Community — A constructive and inclusive social network for software
    665 developers. With you every step of your journey.
    666 
    667   • [134] Home
    668   • [135] Podcasts
    669   • [136] Videos
    670   • [137] Tags
    671   • [138] FAQ
    672   • [139] Forem Shop
    673   • [140] Advertise on DEV
    674   • [141] About
    675   • [142] Contact
    676   • [143] Guides
    677   • [144] Software comparisons
    678 
    679   • [145] Code of Conduct
    680   • [146] Privacy Policy
    681   • [147] Terms of use
    682 
    683 Built on [148]Forem — the [149]open source software that powers [150]DEV and
    684 other inclusive communities.
    685 
    686 Made with love and [151]Ruby on Rails. DEV Community © 2016 - 2024.
    687 
    688 DEV Community
    689 
    690 We're a place where coders share, stay up-to-date and grow their careers.
    691 
    692 [152] Log in [153] Create account
    693 ● ● ● ● ●
    694 
    695 References:
    696 
    697 [1] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#main-content
    698 [3] https://dev.to/
    699 [6] https://dev.to/search
    700 [7] https://dev.to/enter
    701 [8] https://dev.to/enter?state=new-user
    702 [20] https://twitter.com/intent/tweet?text=%22Decorating%20Ruby%20-%20Part%20Two%20-%20Method%20Added%20Decoration%22%20by%20%40keystonelemur%20%23DEVCommunity%20https%3A%2F%2Fdev.to%2Fbaweaver%2Fdecorating-ruby-part-two-method-added-decoration-48mj
    703 [21] https://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Fdev.to%2Fbaweaver%2Fdecorating-ruby-part-two-method-added-decoration-48mj&title=Decorating%20Ruby%20-%20Part%20Two%20-%20Method%20Added%20Decoration&summary=How%20various%20forms%20of%20method%20decoration%20work%20in%20Ruby&source=DEV%20Community
    704 [22] https://www.reddit.com/submit?url=https%3A%2F%2Fdev.to%2Fbaweaver%2Fdecorating-ruby-part-two-method-added-decoration-48mj&title=Decorating%20Ruby%20-%20Part%20Two%20-%20Method%20Added%20Decoration
    705 [23] https://news.ycombinator.com/submitlink?u=https%3A%2F%2Fdev.to%2Fbaweaver%2Fdecorating-ruby-part-two-method-added-decoration-48mj&t=Decorating%20Ruby%20-%20Part%20Two%20-%20Method%20Added%20Decoration
    706 [24] https://www.facebook.com/sharer.php?u=https%3A%2F%2Fdev.to%2Fbaweaver%2Fdecorating-ruby-part-two-method-added-decoration-48mj
    707 [25] https://toot.kytta.dev/?text=https%3A%2F%2Fdev.to%2Fbaweaver%2Fdecorating-ruby-part-two-method-added-decoration-48mj
    708 [26] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#
    709 [27] https://dev.to/report-abuse
    710 [28] https://res.cloudinary.com/practicaldev/image/fetch/s--UjPHgJnM--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://thepracticaldev.s3.amazonaws.com/i/rdvh6fph3zoga5f9pw98.png
    711 [29] https://dev.to/baweaver
    712 [30] https://dev.to/baweaver
    713 [31] https://dev.to/t/ruby
    714 [32] https://dev.to/baweaver/series/10894
    715 [33] https://dev.to/baweaver/decorating-ruby-part-1-symbol-method-decoration-4po2
    716 [34] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj
    717 [35] https://dev.to/baweaver/decorating-ruby-part-three-prepending-decoration-1ehc
    718 [36] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#whats-in-store-for-today
    719 [37] https://res.cloudinary.com/practicaldev/image/fetch/s--L5_TPTzS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/5pzy2brl5apjtt4edgrm.png
    720 [38] https://dev.to/baweaver/decorating-ruby-part-1-symbol-method-decoration-4po2
    721 [39] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj
    722 [40] https://dev.to/baweaver/decorating-ruby-part-three-prepending-decoration-1ehc
    723 [41] https://dev.to/baweaver/decorating-ruby-part-1-symbol-method-decoration-4po2
    724 [42] https://dev.to/baweaver/decorating-ruby-part-three-prepending-decoration-1ehc
    725 [43] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#what-does-method-added-decoration-look-like
    726 [44] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#making-our-own-method-added-decoration
    727 [45] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#module-inclusion
    728 [46] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#feeling-included
    729 [47] https://www.merriam-webster.com/dictionary/affable
    730 [48] https://www.merriam-webster.com/dictionary/affable
    731 [49] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#hook-line-and-sinker
    732 [50] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#extra-classy-indeed
    733 [51] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#raise-your-flag
    734 [52] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#method-added
    735 [53] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#politely-aliasing
    736 [54] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#wrap-battle
    737 [55] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#-raw-send-endraw-help
    738 [56] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#-raw-exec-endraw-utive-functions
    739 [57] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#-raw-instanceeval-endraw-vs-raw-instanceexec-endraw-
    740 [58] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#wrapping-up
    741 [59] https://dev.to/baweaver/decorating-ruby-part-1-symbol-method-decoration-4po2
    742 [60] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj
    743 [61] https://dev.to/baweaver/decorating-ruby-part-three-prepending-decoration-1ehc
    744 [62] https://dev.to/baweaver/decorating-ruby-part-1-symbol-method-decoration-4po2
    745 [63] https://dev.to/baweaver/decorating-ruby-part-three-prepending-decoration-1ehc
    746 [64] https://dev.to/baweaver/series/10894
    747 [65] https://dev.to/baweaver/decorating-ruby-part-1-symbol-method-decoration-4po2
    748 [66] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj
    749 [67] https://dev.to/baweaver/decorating-ruby-part-three-prepending-decoration-1ehc
    750 [75] https://dev.to/settings/response-templates
    751 [78] https://dev.to/404.html
    752 [79] https://dev.to/edisonywh
    753 [80] https://dev.to/edisonywh
    754 [82] https://dev.to/edisonywh
    755 [84] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#comment-e96o
    756 [86] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#comment-e96o
    757 [89] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#/baweaver/decorating-ruby-part-two-method-added-decoration-48mj/comments/new/e96o
    758 [90] https://dev.to/baweaver
    759 [91] https://dev.to/baweaver
    760 [93] https://dev.to/baweaver
    761 [95] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#comment-e9g0
    762 [97] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#comment-e9g0
    763 [99] https://medium.com/@baweaver/exploring-tracepoint-in-ruby-part-two-events-f4fd291992f5
    764 [101] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#/baweaver/decorating-ruby-part-two-method-added-decoration-48mj/comments/new/e9g0
    765 [102] https://dev.to/code-of-conduct
    766 [103] https://dev.to/report-abuse
    767 [107] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#
    768 [111] https://dev.to/report-abuse
    769 [112] https://dev.to/cherryramatis/bringing-more-sweetness-to-ruby-with-sorbet-types-13jp
    770 [113] https://dev.to/hungle00/rubys-main-object-5hni
    771 [114] https://dev.to/braindeaf/making-a-youtube-short-5gih
    772 [115] https://dev.to/iberianpig/enhance-your-touchpad-experience-on-linux-with-thumbsense-391n
    773 [116] https://dev.to/baweaver
    774 [118] https://dev.to/baweaver
    775 [119] https://dev.to/baweaver/understanding-ruby-memoization-2be5
    776 [120] https://dev.to/baweaver/in-favor-of-ruby-central-memberships-15gl
    777 [121] https://dev.to/baweaver/pattern-matching-interfaces-in-ruby-1b15
    778 [130] javascript:void(0);
    779 [133] https://dev.to/
    780 [134] https://dev.to/
    781 [135] https://dev.to/pod
    782 [136] https://dev.to/videos
    783 [137] https://dev.to/tags
    784 [138] https://dev.to/faq
    785 [139] https://shop.forem.com/
    786 [140] https://dev.to/advertise
    787 [141] https://dev.to/about
    788 [142] https://dev.to/contact
    789 [143] https://dev.to/guides
    790 [144] https://dev.to/software-comparisons
    791 [145] https://dev.to/code-of-conduct
    792 [146] https://dev.to/privacy
    793 [147] https://dev.to/terms
    794 [148] https://www.forem.com/
    795 [149] https://dev.to/t/opensource
    796 [150] https://dev.to/
    797 [151] https://dev.to/t/rails
    798 [152] https://dev.to/enter
    799 [153] https://dev.to/enter?state=new-user