<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Amr El-Bakry</title>
    <description>The latest articles on Forem by Amr El-Bakry (@amrrbakry).</description>
    <link>https://forem.com/amrrbakry</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F12870%2Fccf254cc-f9f4-4456-97b0-92d50b9199ae.jpg</url>
      <title>Forem: Amr El-Bakry</title>
      <link>https://forem.com/amrrbakry</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/amrrbakry"/>
    <language>en</language>
    <item>
      <title>Consistency for Agile Teams</title>
      <dc:creator>Amr El-Bakry</dc:creator>
      <pubDate>Wed, 15 Apr 2020 12:51:10 +0000</pubDate>
      <link>https://forem.com/amrrbakry/consistency-for-agile-teams-2p2g</link>
      <guid>https://forem.com/amrrbakry/consistency-for-agile-teams-2p2g</guid>
      <description>&lt;p&gt;As an agile team, we are working tirelessly to deliver &lt;em&gt;working software&lt;/em&gt;. Periodically, we pause and reflect on what we delivered, what we didn't, and what could be improved; whether it's the process itself, the organization of the team, or the tools. We improve, restart, and repeat.&lt;/p&gt;

&lt;p&gt;It gets &lt;em&gt;tempting&lt;/em&gt; to pursue one improvement after another, and naturally, there's &lt;em&gt;always&lt;/em&gt; something to improve. However, in one of our meetings, our team decided to shift focus to something else: &lt;strong&gt;consistency&lt;/strong&gt;. Before we improve, we need to be consistent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Consistency, how?
&lt;/h2&gt;

&lt;p&gt;We have delivered the sprint goal. All is well. Now, instead of looking for improvements that will supposedly help us deliver more, we will maintain the same pace and try to do it for another two sprints. If we are able to do that, then we are consistent. And now, we can introduce gradual improvements and be consistent with them.&lt;/p&gt;

&lt;p&gt;If not, then there's something that needs to be fixed. Let's revisit our process and progress and see where it went wrong. After finding and fixing the issue, we can try to be consistent again.&lt;/p&gt;

&lt;p&gt;Sounds easy enough! But it is not. It takes good, clear communication, discipline, and commitment from each team member.&lt;/p&gt;

&lt;h2&gt;
  
  
  Consistency and Change
&lt;/h2&gt;

&lt;p&gt;Consistency is not about sacrificing change. It is rather about striking a balance between the two. Before adding new functionality or behavior, we should be consistent, and thus confident that it won't break already existing ones.&lt;/p&gt;

&lt;p&gt;Change is inevitable, and we'd rather have a solid foundation that allows us to respond smoothly to that change; this &lt;em&gt;solidity&lt;/em&gt; comes through being consistent.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;this post was also published on our (RealxData) &lt;a href="http://realxdata.io/agile/2020/04/14/consistency-agile-teams.html"&gt;blog&lt;/a&gt; and &lt;a href="https://medium.com/@amrrbakry/consistency-for-agile-teams-a96734739366"&gt;medium&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>consistency</category>
      <category>agile</category>
      <category>teams</category>
      <category>change</category>
    </item>
    <item>
      <title>TIL: Using Different Database Connection with ActiveRecord Transactions</title>
      <dc:creator>Amr El-Bakry</dc:creator>
      <pubDate>Thu, 14 Feb 2019 23:40:53 +0000</pubDate>
      <link>https://forem.com/amrrbakry/til-using-different-database-connection-with-activerecord-transactions-345o</link>
      <guid>https://forem.com/amrrbakry/til-using-different-database-connection-with-activerecord-transactions-345o</guid>
      <description>&lt;p&gt;I came upon an interesting problem a few days ago at work. I had some code inside an &lt;a href="https://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html"&gt;active record transaction&lt;/a&gt; that updated some record in the db, called an external service, and then updated another record based on the response from that external service. It was something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;
  &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;record1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;external_service_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Communicator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;save_error: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# raises exception if response is not a success&lt;/span&gt;
    &lt;span class="n"&gt;record2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;external_service_response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The communicator class uses &lt;code&gt;record1&lt;/code&gt; data to build a request and call an external service. It also handles authentication and response parsing; if the response is a success, it parses and returns it. otherwise, &lt;em&gt;it updates a record in the db with the error response&lt;/em&gt; if the &lt;code&gt;save_error&lt;/code&gt; flag is set to &lt;code&gt;true&lt;/code&gt;, and finally raises an exception, causing the active record transaction to roll back everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;the issue was that the error response was not saved to the db. Do you see why?! Because it's inside the transaction; so when the communicator class raises an exception, the transaction rolls back everything, including the operation to save the error message to the database. well, duh. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;the most obvious solution and the one you should go for in most cases is to move the communicator call outside the transaction, and the save error operation won't be rolled back. However, I couldn't do that so I had to do more thinking and googling...&lt;/p&gt;

&lt;p&gt;I came across another neat solution and definitely learned something new. It uses the fact that an active record transaction "acts on a single database connection"; which basically means that if we use a different connection -from the one the transaction is using- to update a record, the transaction won't cover the update operation, and it won't be rolled back in case of an exception.&lt;/p&gt;

&lt;p&gt;So, to solve my problem, I need to make a new thread (since each thread will use a different database connection), obtain a connection, and update the record with the error response.&lt;/p&gt;

&lt;h2&gt;
  
  
  ActiveRecord::Base.connection_pool
&lt;/h2&gt;

&lt;p&gt;and to achieve all that, and to manage the database connections properly and make sure it's thread safe, we have &lt;a href="https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/ConnectionPool.html"&gt;&lt;code&gt;ActiveRecord::Base.connection_pool&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the docs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A connection pool synchronizes thread access to a limited number of database connections. The basic idea is that each thread checks out a database connection from the pool, uses that connection, and checks the connection back in. ConnectionPool is completely thread-safe, and will ensure that a connection cannot be used by two threads at the same time, as long as ConnectionPool's contract is correctly followed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and so the final solution becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# communicator class&lt;/span&gt;
&lt;span class="c1"&gt;# &lt;/span&gt;
&lt;span class="c1"&gt;# in case of error response&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save_error_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="no"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connection_pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_connection&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;external_service_error_response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the &lt;a href="https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/ConnectionPool.html#method-i-with_connection"&gt;&lt;code&gt;with_connection&lt;/code&gt;&lt;/a&gt; method will check out a connection, yield to the block (update the record), and check in the connection again to the pool after finishing. We also need to &lt;code&gt;join&lt;/code&gt; the thread to make sure the main thread will wait for it to finish before exiting.&lt;/p&gt;

&lt;p&gt;That's it! Now, the error response will be saved to the database and won't be rolled back in case of an exception as it's in a different thread and different connection from the transaction. &lt;/p&gt;

&lt;p&gt;I hope my explanation of the problem and the solution was clear.&lt;/p&gt;

&lt;p&gt;this post was also published on &lt;a href="https://medium.com/@amrrbakry/til-using-different-database-connection-with-activerecord-transactions-adb3c25cc9f1"&gt;medium&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>activerecord</category>
      <category>todayilearned</category>
    </item>
    <item>
      <title>The Importance of Selective Learning </title>
      <dc:creator>Amr El-Bakry</dc:creator>
      <pubDate>Fri, 25 Jan 2019 20:11:34 +0000</pubDate>
      <link>https://forem.com/amrrbakry/the-importance-of-selective-learning--13m6</link>
      <guid>https://forem.com/amrrbakry/the-importance-of-selective-learning--13m6</guid>
      <description>&lt;p&gt;We are very lucky to live in a time in which new technologies emerge every day to help us build all sort of stuff and make our lives easier. There's always this awesome tool or language that you want to learn and use because it introduces a new way of thinking or a different paradigm.&lt;/p&gt;

&lt;p&gt;And with today's access to information and learning resources, and if you know how to do your google search, you will find a plethora of resources to help you learn that tool or language and a plethora of many more things to learn. &lt;em&gt;It can get overwhelming&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Learning is a skill in itself and those of us who are able to learn fast are blessed, but it's also important to remember that it's not a race. Learn at your own pace; as long as you're learning, you should take all the time you need. But before you embark on this journey of learning, you should take a moment to consider if you really need to invest all this time to learn this and/or that tool. Because &lt;em&gt;you can learn anything but you can't learn everything&lt;/em&gt;; that's why you should be especially &lt;strong&gt;selective&lt;/strong&gt; about what you learn.&lt;/p&gt;

&lt;p&gt;There will always be temptations to start using this new language because of how awesome and revolutionary it is or how it will replace this other language, however, this doesn't mean that you should drop everything and start investing time to learn it. Take a step back and thoroughly think if you actually need to learn it. &lt;/p&gt;

&lt;p&gt;Being selective about what you learn is how you distinguish yourself from others. &lt;em&gt;It is essentially about what you know well not how much you know&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;and remember to never stop learning!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;this post was also published on &lt;a href="https://medium.com/@amrrbakry/the-importance-of-selective-learning-a0ec3b358ed8"&gt;medium&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>learning</category>
      <category>programming</category>
      <category>career</category>
      <category>devtips</category>
    </item>
    <item>
      <title>Runtime Introspection in Ruby</title>
      <dc:creator>Amr El-Bakry</dc:creator>
      <pubDate>Thu, 02 Aug 2018 08:57:55 +0000</pubDate>
      <link>https://forem.com/amrrbakry/runtime-introspection-in-ruby-2po1</link>
      <guid>https://forem.com/amrrbakry/runtime-introspection-in-ruby-2po1</guid>
      <description>&lt;p&gt;Ruby offers a variety of &lt;em&gt;methods&lt;/em&gt; that allows you to ask an object about its capabilities (which messages/methods does it respond to?), its variables and constants, and its backstory (the object's class and ancestors).&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Methods Introspection&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let's start by asking an object about its non-private &lt;code&gt;methods&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'a string'&lt;/span&gt;
&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;methods&lt;/span&gt;

&lt;span class="c1"&gt;# =&amp;gt; [:include?, :%, :*, :+, :unicode_normalize, :to_c, :unicode_normalize!, :unicode_normalized?, :count, ...]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;methods&lt;/code&gt; returns an array of symbols representing the names of the public and protected methods for the receiver string object &lt;em&gt;&lt;code&gt;str&lt;/code&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;We could also ask the object about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;private_methods&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;public_methods&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;protected_methods&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;singleton_methods&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;by default, Ruby will look up and list all the methods in the object's class and its ancestor classes and modules. If you want to list methods in the object's class only, you could pass the argument &lt;em&gt;false&lt;/em&gt; or &lt;em&gt;nil&lt;/em&gt; to any of these methods.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'a string'&lt;/span&gt;
&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;public_methods&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# public methods defined in String only&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; [:include?, :%, :*, :+, :unicode_normalize, :to_c, :unicode_normalize!, :unicode_normalized?, :count, ...]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sometimes, you'll only need to know if an object knows about a specific method, and that's when we use the aptly-named &lt;code&gt;respond_to?&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'a string'&lt;/span&gt;
&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;respond_to?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:include?&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;respond_to?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:first&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Variables and Constants Introspection&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In the same sense, we can query a class about &lt;code&gt;instance_variables&lt;/code&gt;, &lt;code&gt;class_variables&lt;/code&gt;, and &lt;code&gt;constants&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Cat&lt;/span&gt;
  &lt;span class="vc"&gt;@@cats_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

  &lt;span class="no"&gt;CATS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Luna'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Milo'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:age&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Max'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_variables&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; [:@name, :@age]&lt;/span&gt;

&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class_variables&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; [:@@cats_count]&lt;/span&gt;

&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;constants&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; [:CATS]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, there are top-level methods to list &lt;code&gt;local_variables&lt;/code&gt; and &lt;code&gt;global_variables&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# irb session&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;local_variables&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; [:_]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;em&gt;underscore&lt;/em&gt; local variable is actually a very interesting one; it always holds the last evaluated expression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Milo'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; #&amp;lt;Cat:0x00000002415440 @name="Milo"&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; #&amp;lt;Cat:0x00000002415440 @name="Milo"&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;The Object's Backstory&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Finally, let's ask the object about its &lt;code&gt;class&lt;/code&gt;, &lt;code&gt;superclass&lt;/code&gt;, and &lt;code&gt;ancestors&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;cats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'luna'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'milo'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;cats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; Array&lt;/span&gt;

&lt;span class="n"&gt;cats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;superclass&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; Object&lt;/span&gt;

&lt;span class="n"&gt;cats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ancestors&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; [Array, Enumerable, Object, Kernel, BasicObject]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ancestors&lt;/code&gt; returns a list which includes its receiver (Array) and modules included in Array (Enumerable, Kernel), Array's superclass (Object), and lastly the superclass of Object which is (BasicObject).&lt;/p&gt;

&lt;p&gt;But that's not it. There are also more convenient ways to ask about the object's class...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;is_a?&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kind_of?&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;&lt;code&gt;instance_of?&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;this trio of predicate methods could also help us with that query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;cats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'luna'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'milo'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;cats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_a?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One important difference to note here is that &lt;code&gt;instance_of?&lt;/code&gt; will only return true if the receiver object is a direct instance of the class and not of a subclass:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;B&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;B&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; #&amp;lt;B:0x00000001fac638&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;kind_of?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# true&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_of?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# false&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This was just a glimpse of ruby's introspection capabilities, but there are always very interesting things you can learn about your objects!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article can also be found on &lt;a href="https://medium.com/@amrrbakry/runtime-introspection-in-ruby-b2d718ec704f"&gt;Medium&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>introspection</category>
      <category>methods</category>
    </item>
    <item>
      <title>Hi, I'm Amr El-Bakry</title>
      <dc:creator>Amr El-Bakry</dc:creator>
      <pubDate>Thu, 13 Jul 2017 10:54:05 +0000</pubDate>
      <link>https://forem.com/amrrbakry/hi-im-amr-el-bakry</link>
      <guid>https://forem.com/amrrbakry/hi-im-amr-el-bakry</guid>
      <description>&lt;p&gt;I have been coding for 3 years.&lt;/p&gt;

&lt;p&gt;You can find me on Twitter as &lt;a href="https://twitter.com/amrrbakry" rel="noopener noreferrer"&gt;@amrrbakry&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I live in Cairo.&lt;/p&gt;

&lt;p&gt;I work for Eventtus.&lt;/p&gt;

&lt;p&gt;I mostly program in these languages: Ruby, Rust, Javascript.&lt;/p&gt;

&lt;p&gt;I am currently learning more about Rust.&lt;/p&gt;

&lt;p&gt;Nice to meet you.&lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
  </channel>
</rss>
