commit 32acda05097748bc109a5714c8810c276331b4b9
parent d0efa6fc661e240b7c19aef4fd89ffbf68de06ee
Author: David Eisinger <[email protected]>
Date: Wed, 31 Jan 2024 10:56:46 -0500
Add some ruby references
Diffstat:
4 files changed, 1300 insertions(+), 0 deletions(-)
diff --git a/content/elsewhere/why-i-still-like-ruby-and-a-few-things-i-dont-like/index.md b/content/elsewhere/why-i-still-like-ruby-and-a-few-things-i-dont-like/index.md
@@ -9,6 +9,18 @@ references:
url: https://www.sitepoint.com/history-ruby/
date: 2023-11-16T14:54:03Z
file: www-sitepoint-com-6vwmef.txt
+- title: "In Ruby, Everything is Evaluated - Mufid's Code blog"
+ url: https://mufid.github.io/blog/2016/ruby-class-evaluation/
+ date: 2024-01-31T15:55:28Z
+ file: mufid-github-io-2czqvc.txt
+- title: "Decorating Ruby - Part Two - Method Added Decoration - DEV Community"
+ url: https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj
+ date: 2024-01-31T15:55:49Z
+ file: dev-to-pywrcp.txt
+- title: "JavaScript Needs Blocks"
+ url: https://yehudakatz.com/2012/01/10/javascript-needs-blocks/
+ date: 2024-01-31T15:55:29Z
+ file: yehudakatz-com-sacizu.txt
- title: "When Should You NOT Use Rails?"
url: https://codefol.io/posts/when-should-you-not-use-rails/
date: 2023-11-04T17:36:55Z
diff --git a/static/archive/dev-to-pywrcp.txt b/static/archive/dev-to-pywrcp.txt
@@ -0,0 +1,799 @@
+[1]Skip to content
+[3] DEV Community
+[4][ ]
+[6]
+[7] Log in [8] Create account
+
+DEV Community
+
+● Add reaction
+[sp] Like [mu] Unicorn [ex] Exploding Head [ra] Raised Hands [fi] Fire
+Jump to Comments Save
+Copy link
+Copied to Clipboard
+[20] Share to Twitter [21] Share to LinkedIn [22] Share to Reddit [23] Share to
+Hacker News [24] Share to Facebook [25] Share to Mastodon
+[26]Share Post via... [27]Report Abuse
+[28] Cover image for Decorating Ruby - Part Two - Method Added Decoration
+[29]Brandon Weaver
+[30]Brandon Weaver
+
+Posted on Aug 18, 2019 • Updated on Jan 21, 2021
+
+● ● ● ● ●
+
+Decorating Ruby - Part Two - Method Added Decoration
+
+[31]#ruby
+
+[32]Decorating Ruby (3 Part Series)
+
+[33] 1 Decorating Ruby - Part One - Symbol Method Decoration [34] 2 Decorating
+Ruby - Part Two - Method Added Decoration [35] 3 Decorating Ruby - Part Three -
+Prepending Decoration
+
+One precursor of me writing an article is if I keep forgetting how something's
+done, causing me to write a reference to look back on for later. This is one
+such article.
+
+[36] What's in Store for Today?
+
+We'll be looking at the next type of decoration, which involves intercepting
+method_added to make a more fluent interface.
+
+[37]The "Dark Lord" Crimson with Metaprogramming magic
+
+Table of Contents
+
+ • [38]Part One - Symbol Method Decoration
+ • [39]Part Two - Method Added Decoration
+ • [40]Part Three - Prepending Decoration
+
+[41]<< Previous | [42]Next >>
+
+[43] What Does Method Added Decoration Look Like?
+
+You've seen the Symbol Method variant:
+
+private def something; end
+
+Readers that were paying very close attention in the last article may have
+noticed when I said that I preferred that style of declaring private methods in
+Ruby, but this was after the way that can be debatably considered more popular
+and widely used in the community:
+
+private
+
+def something; end
+def something_else; end
+
+Using private like this means that every method defined after will be
+considered private. We know how the first one works, but what about the second?
+There's no way it's using method names because it catches both of those methods
+and doesn't change the definition syntax.
+
+That's what we'll be looking into and learning today, and let me tell you it's
+a metaprogramming trip.
+
+[44] Making Our Own Method Added Decoration
+
+As with the last article we're going to need to learn about a few tools before
+we'll be ready to implement this one.
+
+[45] Module Inclusion
+
+Ruby uses Module inclusion as a way to extend classes with additional behavior,
+sometimes requiring an interface to be met before it can do so. Enumerable is
+one of the most common, and requires an each implementation to work:
+
+class Collection
+ include Enumerable
+
+ def initialize(*items)
+ @items = items
+ end
+
+ def each(&fn)
+ return @items.to_enum unless block_given?
+ @items.each { |item| fn.call(item) }
+ end
+end
+
+(yield could be used here instead, but is less explicit and can be confusing to
+teach.)
+
+By defining that one method we've given our class the ability to do all types
+of amazing things like map, select, and more.
+
+Through those few lines we've added a lot of functionality to a class. Here's
+the interesting part about Ruby: it also provides hooks to let Enumerable know
+it was included, including what included it.
+
+[46] Feeling Included
+
+Let's say we have our own module, [47]Affable, which gives us a method to say
+"hi":
+
+module Affable
+ def greeting
+ "It's so very lovely to see you today!"
+ end
+end
+
+My, it is quite an [48]Affable module, now isn't it?
+
+We could even go as far as to make a particularly Affable lemur:
+
+class Lemur
+ include Affable
+ def initialize(name) @name = name; end
+end
+
+Lemur.new("Indigo").greeting
+=> "It's so very lovely to see you today!"
+
+What a classy lemur, yes.
+
+[49] Hook, Line, and Sinker
+
+Let's say that we wanted to tell what particular animal was Affable. We can use
+included to see just that:
+
+module Affable
+ def self.included(klass)
+ puts "#{klass.name} has become extra Affable!"
+ end
+end
+
+If we were to re-include that module:
+
+class Lemur
+ include Affable
+ def initialize(name) @name = name; end
+end
+
+# STDOUT: Lemur has become extra Affable!
+# => :initialize
+
+Right classy. Oh, right, speaking of classy...
+
+[50] Extra Classy Indeed
+
+So we can hook inclusion of a module, great! Why do we care?
+
+What if we wanted to both include methods into a class as well as extend its
+behavior?
+
+With just include it will apply all the behavior to instances of a class. With
+just extend it will apply all the behavior to the class itself. We can't do
+both.
+
+...ok ok, it's Ruby, you caught me, we can totally do both.
+
+As it turns out, include and extend are just methods on a class. We could just
+Lemur.extend(ExtraBehavior) if we wanted to, or we could use our fun little
+hooks from earlier.
+
+A common convention for using this technique is a sub-module called
+ClassMethods, like so:
+
+module Affable
+ def self.included(klass)
+ klass.extend(ClassMethods)
+ end
+
+ module ClassMethods
+ def affable?
+ true
+ end
+ end
+end
+
+This allows us to inject behavior directly into the class as well as other
+behavior we want to include in instances.
+
+Part of me thinks this is so I don't have to remember the difference between
+include and extend, but I always remember that and don't have to spend 20
+minutes flipping between the two and prepend to see which one actually works,
+absolutely not.
+
+Now remember the title about Method Added being the technique for today? Oh
+yes, there's a hook for that as well, but first we need to indicate that
+something needs to be hooked in the first place.
+
+[51] Raise Your Flag
+
+We can intercept a method being added, but how do we know which method should
+be intercepted? We'd need to add a flag to let that hook know it's time to
+start intercepting in full force.
+
+module Affable
+ def self.included(klass)
+ klass.extend(ClassMethods)
+ end
+
+ module ClassMethods
+ def extra_affable
+ @extra_affable = true
+ end
+ end
+end
+
+If you remember private, this could be the flag to indicate that every method
+afterwards should be private:
+
+private
+
+def something; end
+def something_else; end
+
+Same idea here, and once a flag is raised it can also be taken down to make
+sure later methods aren't impacted as well. We keep hinting at hooking method
+added, so let's go ahead and do just that.
+
+[52] Method Added
+
+Now that we have our flag, we have enough to hook into method_added:
+
+module Affable
+ def self.included(klass)
+ klass.extend(ClassMethods)
+ end
+
+ module ClassMethods
+ def extra_affable
+ @extra_affable = true
+ end
+
+ def method_added(method_name)
+ return unless @extra_affable
+
+ @extra_affable = false
+ # ...
+ end
+ end
+end
+
+We can use our flag to ignore method_added unless said flag is set. After we
+check that, we can take down the flag to make sure additional methods defined
+after aren't affected as well. For private this doesn't happen, but we want to
+be polite. It is and Affable module after all.
+
+[53] Politely Aliasing
+
+Speaking of politeness, it's not precisely kind to just overwrite a method
+without giving a way to call it as it was. We can use alias_method to get a new
+name to the method before we overwrite it:
+
+def method_added(method_name)
+ return unless @extra_affable
+
+ @extra_affable = false
+
+ original_method_name = "#{method_name}_without_affability".to_sym
+ alias_method original_method_name, method_name
+end
+
+This means that we can access the original method through this name.
+
+[54] Wrap Battle
+
+So we have the original method aliased, our hook in place, let's get to
+overwriting that method then! As with the last tutorial we can use
+define_method to do this:
+
+module Affable
+ def self.included(klass)
+ klass.extend(ClassMethods)
+ end
+
+ module ClassMethods
+ def extra_affable
+ @extra_affable = true
+ end
+
+ def method_added(method_name)
+ return unless @extra_affable
+
+ @extra_affable = false
+
+ original_method_name = "#{method_name}_without_affability".to_sym
+ alias_method original_method_name, method_name
+
+ define_method(method_name) do |*args, &fn|
+ original_result = send(original_method_name, *args, &fn)
+
+ "#{original_result} Very lovely indeed!"
+ end
+ end
+ end
+end
+
+Overwriting our original class again:
+
+class Lemur
+ include Affable
+
+ def initialize(name) @name = name; end
+
+ extra_affable
+
+ def farewell
+ "Farewell! It was lovely to chat."
+ end
+end
+
+We can give it a try:
+
+Lemur.new("Indigo").farewell
+=> "Farewell! It was lovely to chat. Very lovely indeed!"
+
+[55] send Help!
+
+Wait wait wait wait, send? Didn't we use method last time?
+
+We did, but remember that method_added is a class method that does not have the
+context of an instance of the class, or in other words it has no idea where the
+farewell method is located.
+
+send lets us treat this as an instance again by sending the method name
+directly. Now we could use method inside of here as well, but that can be a bit
+more expensive.
+
+Only the contents inside define_method's block are executed in the context of
+the instance.
+
+[56] executive Functions
+
+If we wanted to, we could have our special method take blocks which execute in
+the context of an instance as well, and this is an extra special bonus trick
+for this post.
+
+Say that we made extra_affable also take a block that allows us to manipulate
+the original value and still execute in the context of the instance:
+
+class Lemur
+ include Affable
+
+ def initialize(name) @name = name; end
+
+ extra_affable { |original|
+ "#{@name}: #{original} Very lovely indeed!"
+ }
+
+ def farewell
+ "Farewell! It was lovely to chat."
+ end
+end
+
+With normal blocks, this will evaluate in the context of the class, but we want
+it to evaluate in the context of the instance instead. That's what we have
+instance_exec for:
+
+module Affable
+ def self.included(klass)
+ klass.extend(ClassMethods)
+ end
+
+ module ClassMethods
+ def extra_affable(&fn)
+ @extra_affable = true
+ @extra_affable_fn = fn
+ end
+
+ def method_added(method_name)
+ return unless @extra_affable
+
+ @extra_affable = false
+ extra_affable_fn = @extra_affable_fn
+
+ original_method_name = "#{method_name}_without_affability".to_sym
+ alias_method original_method_name, method_name
+
+ define_method(method_name) do |*args, &fn|
+ original_result = send(original_method_name, *args, &fn)
+ instance_exec(original_result, &extra_affable_fn)
+ end
+ end
+ end
+end
+
+Running that gives us this:
+
+Lemur.new("Indigo").farewell
+# => "Indigo: Farewell! It was lovely to chat. Very lovely indeed!"
+
+Now pay very close attention to this line:
+
+extra_affable_fn = @extra_affable_fn
+
+We need to use this because inside define_method's block is inside the
+instance, which has no clue what @extra_affable_fn is. That said, it can still
+see outside to the context where the block was called, meaning it can see that
+local version of extra_affable_fn sitting right there, allowing us to call it:
+
+instance_exec(original_result, &extra_affable_fn)
+
+[57] instance_eval vs instance_exec?
+
+Why not use instance_eval? instance_exec allows us to pass along arguments as
+well, otherwise instance_eval would make a lot of sense to evaluate something
+in an instance. Instead, we need to execute something in the context of an
+instance, so we use instance_exec here.
+
+[58] Wrapping Up
+
+So that was quite a lot of magic, and it took me a fair bit to really
+understand what some of it was doing and why. That's perfectly ok, if I
+understood everything the first time I'd be worried because that means I'm not
+really learning anything!
+
+One issue I think this will have later is I wonder how poorly having multiple
+hooks to method_added will work. If it turns out it makes things go boom in a
+spectacularly pretty and confounding way there'll be a part three. If not, this
+paragraph will disappear and I'll pretend to not know what you're talking about
+if you ask me about it.
+
+There's a lot of potential here for some really interesting things, but there's
+also a lot of potential for abuse. Be sure to not abuse such magic, because for
+every layer of redefinition code can become increasingly harder to reason about
+and test later.
+
+In most cases I would instead advocate for SimpleDelegate, Forwardable, or
+simple inheritance with super to extend behavior of classes. Don't use a
+chainsaw where hedge trimmers will do, but on occasion it's nice to know a
+chainsaw is there for those particularly gnarly problems.
+
+Discretion is the name of the game.
+
+Table of Contents
+
+ • [59]Part One - Symbol Method Decoration
+ • [60]Part Two - Method Added Decoration
+ • [61]Part Three - Prepending Decoration
+
+[62]<< Previous | [63]Next >>
+
+[64]Decorating Ruby (3 Part Series)
+
+[65] 1 Decorating Ruby - Part One - Symbol Method Decoration [66] 2 Decorating
+Ruby - Part Two - Method Added Decoration [67] 3 Decorating Ruby - Part Three -
+Prepending Decoration
+
+Top comments (2)
+
+Subscribe
+pic
+[ ]
+Personal Trusted User
+[75] Create template
+
+Templates let you quickly answer FAQs or store snippets for re-use.
+
+Submit Preview [78]Dismiss
+
+[79] edisonywh profile image
+[80] Edison Yap
+Edison Yap
+[82] [https] Edison Yap
+Follow
+An aspiring software engineer from the tiny city of Kuala Lumpur.
+
+ • Location
+ Stockholm, Sweden
+ • Education
+ RMIT University, Melbourne
+ • Work
+ Software Engineer at Klarna
+ • Joined
+ Jul 25, 2018
+
+• [84] Aug 18 '19 • Edited on Aug 18 • Edited
+
+ • [86]Copy link
+ •
+ • Hide
+ •
+ •
+ •
+
+Wow this is really cool, thanks for sharing Brandon!
+
+Is there a way to hook onto the last method_added? For example I'd like to
+execute something after all methods are added
+
+EDIT: also quick search online seems to say that method_added only works for
+instance methods, but there's singleton_method_added hook for class methods
+too!
+
+1 like Like [89] Reply
+
+[90] baweaver profile image
+[91] Brandon Weaver
+Brandon Weaver
+[93] [https] Brandon Weaver
+Follow
+Principal Ruby Engineer at Gusto on Payroll Services. Autistic / ADHD, He /
+Him. I'm the Lemur guy.
+
+ • Location
+ San Francisco, CA
+ • Work
+ Principal Engineer - Payroll Services at Gusto
+ • Joined
+ Jan 16, 2019
+
+• [95] Aug 18 '19 • Edited on Aug 18 • Edited
+
+ • [97]Copy link
+ •
+ • Hide
+ •
+ •
+ •
+
+Technically in Ruby there's never a point in which methods are no longer added,
+so it's a bit hard to hook that. One potential is to use TracePoint to hook the
+ending of a class definition and retaining a class of "infected" classes, but
+that'd be slow.
+
+Look for "Class End Event" in this article: [99]medium.com/@baweaver/
+exploring-tra...
+
+EDIT - ...though now I'm curious if one could use such things to freeze a class
+from modifications.
+
+1 like Like [101] Reply
+[102]Code of Conduct • [103]Report abuse
+
+Are you sure you want to hide this comment? It will become hidden in your post,
+but will still be visible via the comment's [107]permalink.
+
+[109][ ]
+
+Hide child comments as well
+
+Confirm
+
+For further actions, you may consider blocking this person and/or [111]
+reporting abuse
+
+Read next
+
+[112]
+cherryramatis profile image
+
+Bringing more sweetness to Ruby with Sorbet types 🍦
+
+Cherry Ramatis - Sep 18 '23
+
+[113]
+hungle00 profile image
+
+Ruby's main object
+
+hungle00 - Oct 1 '23
+
+[114]
+braindeaf profile image
+
+Making a YouTube Short
+
+RobL - Sep 28 '23
+
+[115]
+iberianpig profile image
+
+Enhance Your Touchpad Experience on Linux with ThumbSense!
+
+Kohei Yamada - Sep 27 '23
+
+[116] [https] Brandon Weaver
+Follow
+Principal Ruby Engineer at Gusto on Payroll Services. Autistic / ADHD, He /
+Him. I'm the Lemur guy.
+
+ • Location
+ San Francisco, CA
+ • Work
+ Principal Engineer - Payroll Services at Gusto
+ • Joined
+ Jan 16, 2019
+
+More from [118]Brandon Weaver
+
+[119] Understanding Ruby - Memoization
+#ruby #beginners
+[120] In Favor of Ruby Central Memberships
+#ruby #community
+[121] Pattern Matching Interfaces in Ruby
+#ruby #rails #functional
+
+Once suspended, baweaver will not be able to comment or publish posts until
+their suspension is removed.
+
+ [ ]
+ [ ]
+ [ ]
+Note: [ ]
+
+Submit & Suspend
+
+Once unsuspended, baweaver will be able to comment and publish posts again.
+
+ [ ]
+ [ ]
+ [ ]
+Note: [ ]
+
+Submit & Unsuspend
+
+Once unpublished, all posts by baweaver will become hidden and only accessible
+to themselves.
+
+If baweaver is not suspended, they can still re-publish their posts from their
+dashboard.
+
+Note:[ ]
+
+Unpublish all posts
+
+Once unpublished, this post will become invisible to the public and only
+accessible to Brandon Weaver.
+
+They can still re-publish the post if they are not suspended.
+
+Unpublish Post
+
+Thanks for keeping DEV Community safe. Here is what you can do to flag
+baweaver:
+
+[129]( ) Make all posts by baweaver less visible
+
+baweaver consistently posts content that violates DEV Community's code of
+conduct because it is harassing, offensive or spammy.
+
+[130] Report other inappropriate conduct
+
+Confirm Flag
+
+Unflagging baweaver will restore default visibility to their posts.
+
+Confirm Unflag
+
+[133]DEV Community — A constructive and inclusive social network for software
+developers. With you every step of your journey.
+
+ • [134] Home
+ • [135] Podcasts
+ • [136] Videos
+ • [137] Tags
+ • [138] FAQ
+ • [139] Forem Shop
+ • [140] Advertise on DEV
+ • [141] About
+ • [142] Contact
+ • [143] Guides
+ • [144] Software comparisons
+
+ • [145] Code of Conduct
+ • [146] Privacy Policy
+ • [147] Terms of use
+
+Built on [148]Forem — the [149]open source software that powers [150]DEV and
+other inclusive communities.
+
+Made with love and [151]Ruby on Rails. DEV Community © 2016 - 2024.
+
+DEV Community
+
+We're a place where coders share, stay up-to-date and grow their careers.
+
+[152] Log in [153] Create account
+● ● ● ● ●
+
+References:
+
+[1] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#main-content
+[3] https://dev.to/
+[6] https://dev.to/search
+[7] https://dev.to/enter
+[8] https://dev.to/enter?state=new-user
+[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
+[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
+[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
+[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
+[24] https://www.facebook.com/sharer.php?u=https%3A%2F%2Fdev.to%2Fbaweaver%2Fdecorating-ruby-part-two-method-added-decoration-48mj
+[25] https://toot.kytta.dev/?text=https%3A%2F%2Fdev.to%2Fbaweaver%2Fdecorating-ruby-part-two-method-added-decoration-48mj
+[26] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#
+[27] https://dev.to/report-abuse
+[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
+[29] https://dev.to/baweaver
+[30] https://dev.to/baweaver
+[31] https://dev.to/t/ruby
+[32] https://dev.to/baweaver/series/10894
+[33] https://dev.to/baweaver/decorating-ruby-part-1-symbol-method-decoration-4po2
+[34] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj
+[35] https://dev.to/baweaver/decorating-ruby-part-three-prepending-decoration-1ehc
+[36] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#whats-in-store-for-today
+[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
+[38] https://dev.to/baweaver/decorating-ruby-part-1-symbol-method-decoration-4po2
+[39] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj
+[40] https://dev.to/baweaver/decorating-ruby-part-three-prepending-decoration-1ehc
+[41] https://dev.to/baweaver/decorating-ruby-part-1-symbol-method-decoration-4po2
+[42] https://dev.to/baweaver/decorating-ruby-part-three-prepending-decoration-1ehc
+[43] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#what-does-method-added-decoration-look-like
+[44] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#making-our-own-method-added-decoration
+[45] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#module-inclusion
+[46] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#feeling-included
+[47] https://www.merriam-webster.com/dictionary/affable
+[48] https://www.merriam-webster.com/dictionary/affable
+[49] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#hook-line-and-sinker
+[50] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#extra-classy-indeed
+[51] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#raise-your-flag
+[52] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#method-added
+[53] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#politely-aliasing
+[54] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#wrap-battle
+[55] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#-raw-send-endraw-help
+[56] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#-raw-exec-endraw-utive-functions
+[57] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#-raw-instanceeval-endraw-vs-raw-instanceexec-endraw-
+[58] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#wrapping-up
+[59] https://dev.to/baweaver/decorating-ruby-part-1-symbol-method-decoration-4po2
+[60] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj
+[61] https://dev.to/baweaver/decorating-ruby-part-three-prepending-decoration-1ehc
+[62] https://dev.to/baweaver/decorating-ruby-part-1-symbol-method-decoration-4po2
+[63] https://dev.to/baweaver/decorating-ruby-part-three-prepending-decoration-1ehc
+[64] https://dev.to/baweaver/series/10894
+[65] https://dev.to/baweaver/decorating-ruby-part-1-symbol-method-decoration-4po2
+[66] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj
+[67] https://dev.to/baweaver/decorating-ruby-part-three-prepending-decoration-1ehc
+[75] https://dev.to/settings/response-templates
+[78] https://dev.to/404.html
+[79] https://dev.to/edisonywh
+[80] https://dev.to/edisonywh
+[82] https://dev.to/edisonywh
+[84] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#comment-e96o
+[86] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#comment-e96o
+[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
+[90] https://dev.to/baweaver
+[91] https://dev.to/baweaver
+[93] https://dev.to/baweaver
+[95] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#comment-e9g0
+[97] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#comment-e9g0
+[99] https://medium.com/@baweaver/exploring-tracepoint-in-ruby-part-two-events-f4fd291992f5
+[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
+[102] https://dev.to/code-of-conduct
+[103] https://dev.to/report-abuse
+[107] https://dev.to/baweaver/decorating-ruby-part-two-method-added-decoration-48mj#
+[111] https://dev.to/report-abuse
+[112] https://dev.to/cherryramatis/bringing-more-sweetness-to-ruby-with-sorbet-types-13jp
+[113] https://dev.to/hungle00/rubys-main-object-5hni
+[114] https://dev.to/braindeaf/making-a-youtube-short-5gih
+[115] https://dev.to/iberianpig/enhance-your-touchpad-experience-on-linux-with-thumbsense-391n
+[116] https://dev.to/baweaver
+[118] https://dev.to/baweaver
+[119] https://dev.to/baweaver/understanding-ruby-memoization-2be5
+[120] https://dev.to/baweaver/in-favor-of-ruby-central-memberships-15gl
+[121] https://dev.to/baweaver/pattern-matching-interfaces-in-ruby-1b15
+[130] javascript:void(0);
+[133] https://dev.to/
+[134] https://dev.to/
+[135] https://dev.to/pod
+[136] https://dev.to/videos
+[137] https://dev.to/tags
+[138] https://dev.to/faq
+[139] https://shop.forem.com/
+[140] https://dev.to/advertise
+[141] https://dev.to/about
+[142] https://dev.to/contact
+[143] https://dev.to/guides
+[144] https://dev.to/software-comparisons
+[145] https://dev.to/code-of-conduct
+[146] https://dev.to/privacy
+[147] https://dev.to/terms
+[148] https://www.forem.com/
+[149] https://dev.to/t/opensource
+[150] https://dev.to/
+[151] https://dev.to/t/rails
+[152] https://dev.to/enter
+[153] https://dev.to/enter?state=new-user
diff --git a/static/archive/mufid-github-io-2czqvc.txt b/static/archive/mufid-github-io-2czqvc.txt
@@ -0,0 +1,132 @@
+{
+fidz
+}
+
+[1]Mufid's Code blog
+
+ • [2]RSS
+
+[4][ ]
+ • [5]Blog
+ • [6]Archives
+
+In Ruby, Everything is Evaluated
+
+Jul 10th, 2016 | [7]Comments
+
+So if i write
+
+1 def hello
+2 puts 'world'
+3 end
+
+It will evaluate def, to which Ruby will “create a method named hello in global
+scope, with puts ‘world’ as a block”. We can change “global scope” to any
+object we want.
+
+1 class Greeting
+2 def hello
+3 puts 'world'
+4 end
+5 end
+
+The class “Greeting” is actually EVALUATED, NOT DEFINED (e.g. In Java, after we
+define a signature of a class/method, we can’t change it, except using
+reflection). So actually, we can put anything in “Greeting” block, like
+
+1 class Greeting
+2 puts "Will define hello in greeting"
+3 def hello
+4 puts 'world'
+5 end
+6 end
+
+Save above script as “test.rb” (or anything) and try to run it. It will show
+“Will define hello in greeting” EVEN you don’t call “Greeting” class or “hello”
+class or you don’t even need to instantiate “Greeting” class. This language
+feature allows meta programming, like what we see in Rails.
+
+This time i will use Class Attribute within active support. If you ever run
+Rails, you should have it, but you can gem install active_support if you don’t.
+
+1 require 'active_support/core_ext/class/attribute'
+2
+3 module Greeting; end
+4
+5 class Greeting::Base
+6
+7 class_attribute :blocks
+8
+9 def hello(name)
+10 self.blocks[:greeting].call(name)
+11 self.blocks[:hello].call(name)
+12 end
+13
+14 protected
+15 def self.define_greeting(sym, &blk)
+16 self.blocks ||= {}
+17 self.blocks[sym] = blk
+18 end
+19 end
+20
+21 class Greeting::English < Greeting::Base
+22 define_greeting :greeting do |who|
+23 puts "Hi #{who}, Ruby will greet you with hello world!"
+24 end
+25 define_greeting :hello do |who|
+26 puts "Hello World, #{who}!"
+27 end
+28 end
+29
+30 class Greeting::Indonesian < Greeting::Base
+31 define_greeting :greeting do |who|
+32 puts "Halo kakak #{who}, Ruby akan menyapamu dengan Halo Dunia!"
+33 end
+34 define_greeting :hello do |who|
+35 puts "Halo dunia! Salam, #{who}!"
+36 end
+37 end
+38
+39 x = Greeting::English.new
+40 x.hello "Fido"
+41 # Hi Fido, Ruby will greet you with hello world!
+42 # Hello World, Fido!
+43 x = Greeting::Indonesian.new
+44 x.hello "Fido"
+45 # Halo kakak Fido, Ruby akan menyapamu dengan Halo Dunia!
+46 # Halo dunia! Salam, Fido!
+
+Previously i want to move the class attribute logic to above code, but after i
+see the [8]Active Support code, it is pretty complex, so i just require it : /
+
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+Previously, i posted [9]this in Reddit
+
+Posted by Mufid Jul 10th, 2016
+
+[10]Tweet
+
+[11]« Using Class with Generics <T> Without the T in C# [12]Cara Googling »
+
+Comments
+
+Please enable JavaScript to view the [13]comments powered by Disqus.
+
+Copyright © 2021 - Mufid - Powered by [14]Octopress
+
+
+References:
+
+[1] https://mufid.github.io/blog/
+[2] https://mufid.github.io/atom.xml
+[5] https://mufid.github.io/blog/
+[6] https://mufid.github.io/blog/blog/archives
+[7] https://mufid.github.io/blog/2016/ruby-class-evaluation/#disqus_thread
+[8] https://github.com/rails/rails/blob/e35b98e6f5c54330245645f2ed40d56c74538902/activesupport/lib/active_support/core_ext/class/attribute.rb
+[9] https://www.reddit.com/r/ProgrammerTIL/comments/4s2vmr/ruby_til_in_ruby_everything_is_evaluated/
+[10] http://twitter.com/share
+[11] https://mufid.github.io/blog/2016/generic-type-csharp/
+[12] https://mufid.github.io/blog/2016/how-to-google/
+[13] http://disqus.com/?ref_noscript
+[14] http://octopress.org/
diff --git a/static/archive/yehudakatz-com-sacizu.txt b/static/archive/yehudakatz-com-sacizu.txt
@@ -0,0 +1,357 @@
+[1] Katz Got Your Tongue
+
+ • [3]Home
+ • [4]About
+ • [5]Projects
+ • [6]Talks
+ • [7]Podcasts
+ • [8]Schedule
+
+Login Subscribe
+Jan 9, 2012 6 min read
+
+JavaScript Needs Blocks
+
+While reading Hacker News posts about JavaScript, I often come across the
+misconception that Ruby's blocks are essentially equivalent to JavaScript's
+"first class functions". Because the ability to pass functions around,
+especially when you can create them anonymously, is extremely powerful, the
+fact that both JavaScript and Ruby have a mechanism to do so makes it natural
+to assume equivalence.
+
+In fact, when people talk about why Ruby's blocks are different from Python's
+functions, they usually talk about anonymity, something that Ruby and
+JavaScript share, but Python does not have. At first glance, a Ruby block is an
+"anonymous function" (or colloquially, a "closure") just as a JavaScript
+function is one.
+
+This impression, which I admittedly shared in my early days as a Ruby/
+JavaScript developer, misses an important subtlety that turns out to have large
+implications. This subtlety is often referred to as "Tennent's Correspondence
+Principle". In short, Tennent's Correspondence Principle says:
+
+ "For a given expression expr, lambda expr should be equivalent."
+
+This is also known as the principle of abstraction, because it means that it is
+easy to refactor common code into methods that take a block. For instance,
+consider the common case of file resource management. Imagine that the block
+form of File.open didn't exist in Ruby, and you saw a lot of the following in
+your code:
+
+begin
+ f = File.open(filename, "r")
+ # do something with f
+ensure
+ f.close
+end
+
+In general, when you see some code that has the same beginning and end, but a
+different middle, it is natural to refactor it into a method that takes a
+block. You would write a method like this:
+
+def read_file(filename)
+ f = File.open(filename, "r")
+ yield f
+ensure
+ f.close
+end
+
+And you'd refactor instances of the pattern in your code with:
+
+read_file(filename) do |f|
+ # do something with f
+end
+
+In order for this strategy to work, it's important that the code inside the
+block look the same after refactoring as before. We can restate the
+correspondence principle in this case as:
+
+ ```ruby # do something with f ```
+
+ should be equivalent to:
+
+ do
+ # do something with
+ end
+
+At first glance, it looks like this is true in Ruby and JavaScript. For
+instance, let's say that what you're doing with the file is printing its mtime.
+You can easily refactor the equivalent in JavaScript:
+
+try {
+ // imaginary JS file API
+ var f = File.open(filename, "r");
+ sys.print(f.mtime);
+} finally {
+ f.close();
+}
+
+Into this:
+
+read_file(function(f) {
+ sys.print(f.mtime);
+});
+
+In fact, cases like this, which are in fact quite elegant, give people the
+mistaken impression that Ruby and JavaScript have a roughly equivalent ability
+to refactor common functionality into anonymous functions.
+
+However, consider a slightly more complicated example, first in Ruby. We'll
+write a simple class that calculates a File's mtime and retrieves its body:
+
+class FileInfo
+ def initialize(filename)
+ @name = filename
+ end
+
+ # calculate the File's +mtime+
+ def mtime
+ f = File.open(@name, "r")
+ mtime = mtime_for(f)
+ return "too old" if mtime < (Time.now - 1000)
+ puts "recent!"
+ mtime
+ ensure
+ f.close
+ end
+
+ # retrieve that file's +body+
+ def body
+ f = File.open(@name, "r")
+ f.read
+ ensure
+ f.close
+ end
+
+ # a helper method to retrieve the mtime of a file
+ def mtime_for(f)
+ File.mtime(f)
+ end
+end
+
+We can easily refactor this code using blocks:
+
+class FileInfo
+ def initialize(filename)
+ @name = filename
+ end
+
+ # refactor the common file management code into a method
+ # that takes a block
+ def mtime
+ with_file do |f|
+ mtime = mtime_for(f)
+ return "too old" if mtime < (Time.now - 1000)
+ puts "recent!"
+ mtime
+ end
+ end
+
+ def body
+ with_file { |f| f.read }
+ end
+
+ def mtime_for(f)
+ File.mtime(f)
+ end
+
+private
+ # this method opens a file, calls a block with it, and
+ # ensures that the file is closed once the block has
+ # finished executing.
+ def with_file
+ f = File.open(@name, "r")
+ yield f
+ ensure
+ f.close
+ end
+end
+
+Again, the important thing to note here is that we could move the code into a
+block without changing it. Unfortunately, this same case does not work in
+JavaScript. Let's first write the equivalent FileInfo class in JavaScript.
+
+// constructor for the FileInfo class
+FileInfo = function(filename) {
+ this.name = filename;
+};
+
+FileInfo.prototype = {
+ // retrieve the file's mtime
+ mtime: function() {
+ try {
+ var f = File.open(this.name, "r");
+ var mtime = this.mtimeFor(f);
+ if (mtime < new Date() - 1000) {
+ return "too old";
+ }
+ sys.print(mtime);
+ } finally {
+ f.close();
+ }
+ },
+
+ // retrieve the file's body
+ body: function() {
+ try {
+ var f = File.open(this.name, "r");
+ return f.read();
+ } finally {
+ f.close();
+ }
+ },
+
+ // a helper method to retrieve the mtime of a file
+ mtimeFor: function(f) {
+ return File.mtime(f);
+ }
+};
+
+If we try to convert the repeated code into a method that takes a function, the
+mtime method will look something like:
+
+function() {
+ // refactor the common file management code into a method
+ // that takes a block
+ this.withFile(function(f) {
+ var mtime = this.mtimeFor(f);
+ if (mtime < new Date() - 1000) {
+ return "too old";
+ }
+ sys.print(mtime);
+ });
+}
+
+There are two very common problems here. First, this has changed contexts. We
+can fix this by allowing a binding as a second parameter, but it means that we
+need to make sure that every time we refactor to a lambda we make sure to
+accept a binding parameter and pass it in. The var self = this pattern emerged
+in JavaScript primarily because of the lack of correspondence.
+
+This is annoying, but not deadly. More problematic is the fact that return has
+changed meaning. Instead of returning from the outer function, it returns from
+the inner one.
+
+This is the right time for JavaScript lovers (and I write this as a sometimes
+JavaScript lover myself) to argue that return behaves exactly as intended, and
+this behavior is simpler and more elegant than the Ruby behavior. That may be
+true, but it doesn't alter the fact that this behavior breaks the
+correspondence principle, with very real consequences.
+
+Instead of effortlessly refactoring code with the same start and end into a
+function taking a function, JavaScript library authors need to consider the
+fact that consumers of their APIs will often need to perform some gymnastics
+when dealing with nested functions. In my experience as an author and consumer
+of JavaScript libraries, this leads to many cases where it's just too much
+bother to provide a nice block-based API.
+
+In order to have a language with return (and possibly super and other similar
+keywords) that satisfies the correspondence principle, the language must, like
+Ruby and Smalltalk before it, have a function lambda and a block lambda.
+Keywords like return always return from the function lambda, even inside of
+block lambdas nested inside. At first glance, this appears a bit inelegant, and
+language partisans often accuse Ruby of unnecessarily having two types of
+"callables", in my experience as an author of large libraries in both Ruby and
+JavaScript, it results in more elegant abstractions in the end.
+
+Iterators and Callbacks
+
+It's worth noting that block lambdas only make sense for functions that take
+functions and invoke them immediately. In this context, keywords like return,
+super and Ruby's yield make sense. These cases include iterators, mutex
+synchronization and resource management (like the block form of File.open).
+
+In contrast, when functions are used as callbacks, those keywords no longer
+make sense. What does it mean to return from a function that has already
+returned? In these cases, typically involving callbacks, function lambdas make
+a lot of sense. In my view, this explains why JavaScript feels so elegant for
+evented code that involves a lot of callbacks, but somewhat clunky for the
+iterator case, and Ruby feels so elegant for the iterator case and somewhat
+more clunky for the evented case. In Ruby's case, (again in my opinion), this
+clunkiness is more from the massively pervasive use of blocks for synchronous
+code than a real deficiency in its structures.
+
+Because of these concerns, the ECMA working group responsible for ECMAScript,
+TC39, [12]is considering adding block lambdas to the language. This would mean
+that the above example could be refactored to:
+
+FileInfo = function(name) {
+ this.name = name;
+};
+
+FileInfo.prototype = {
+ mtime: function() {
+ // use the proposed block syntax, `{ |args| }`.
+ this.withFile { |f|
+ // in block lambdas, +this+ is unchanged
+ var mtime = this.mtimeFor(f);
+ if (mtime < new Date() - 1000) {
+ // block lambdas return from their nearest function
+ return "too old";
+ }
+ sys.print(mtime);
+ }
+ },
+
+ body: function() {
+ this.withFile { |f| f.read(); }
+ },
+
+ mtimeFor: function(f) {
+ return File.mtime(f);
+ },
+
+ withFile: function(block) {
+ try {
+ var f = File.open(this.name, "r");
+ block(f);
+ } finally {
+ f.close();
+ }
+ }
+};
+
+Note that a parallel proposal, which replaces function-scoped var with
+block-scoped let, will almost certainly be accepted by TC39, which would
+slightly, but not substantively, change this example. Also note block lambdas
+automatically return their last statement.
+
+Our experience with Smalltalk and Ruby show that people do not need to
+understand the SCARY correspondence principle for a language that satisfies it
+to yield the desired results. I love the fact that the concept of "iterator" is
+not built into the language, but is instead a consequence of natural block
+semantics. This gives Ruby a rich, broadly useful set of built-in iterators,
+and language users commonly build custom ones. As a JavaScript practitioner, I
+often run into situations where using a for loop is significantly more
+straight-forward than using forEach, always because of the lack of
+correspondence between the code inside a built-in for loop and the code inside
+the function passed to forEach.
+
+For the reasons described above, I strongly approve of [13]the block lambda
+proposal and hope it is adopted.
+
+[14]
+
+Published by:
+
+[15] Yehuda Katz
+[16]
+Katz Got Your Tongue © 2024
+[17]Powered by Ghost
+[pixel]
+
+References:
+
+[1] https://yehudakatz.com/
+[3] http://www.yehudakatz.com/
+[4] https://yehudakatz.com/about/
+[5] https://yehudakatz.com/projects/
+[6] https://yehudakatz.com/talks/
+[7] https://yehudakatz.com/podcasts/
+[8] https://yehudakatz.com/schedule/
+[12] http://wiki.ecmascript.org/doku.php?id=strawman%3Ablock_lambda_revival&ref=yehudakatz.com
+[13] http://wiki.ecmascript.org/doku.php?id=strawman%3Ablock_lambda_revival&ref=yehudakatz.com
+[14] https://yehudakatz.com/2011/12/12/amber-js-formerly-sproutcore-2-0-is-now-ember-js/
+[15] https://yehudakatz.com/author/wycats/
+[16] https://yehudakatz.com/2012/04/13/tokaido-my-hopes-and-dreams/
+[17] https://ghost.org/