<?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>DEV Community: Bhumi</title>
    <description>The latest articles on DEV Community by Bhumi (@bhumi).</description>
    <link>https://dev.to/bhumi</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%2F26708%2Fd009209c-a1d6-401c-a620-00ecd650a325.jpeg</url>
      <title>DEV Community: Bhumi</title>
      <link>https://dev.to/bhumi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bhumi"/>
    <language>en</language>
    <item>
      <title>How Method Lookup and method_missing Works</title>
      <dc:creator>Bhumi</dc:creator>
      <pubDate>Thu, 09 Nov 2023 16:00:00 +0000</pubDate>
      <link>https://dev.to/bhumi/how-method-lookup-and-methodmissing-works-2bda</link>
      <guid>https://dev.to/bhumi/how-method-lookup-and-methodmissing-works-2bda</guid>
      <description>&lt;p&gt;This post is part of a series on understanding Object Oriented Programming using Ruby.&lt;/p&gt;

&lt;p&gt;Subscribe to my &lt;a href="https://buttondown.email/bhumi"&gt;free newsletter&lt;/a&gt; for more.&lt;/p&gt;




&lt;p&gt;Have you ever wondered why we can write &lt;code&gt;Rails.env.production?&lt;/code&gt; instead of having to check with equals like &lt;code&gt;Rails.env == "production"&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;We'll take a little tour of &lt;code&gt;ActiveSupport&lt;/code&gt; code to answer this question about method calls and &lt;code&gt;method_missing&lt;/code&gt;. Specifically the &lt;code&gt;StringInquirer&lt;/code&gt; class, which is behind this little feature on &lt;code&gt;Rails.env&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On this tour, we'll also see other examples of metaprogramming concepts in Ruby. Such as &lt;code&gt;instance_variable_set&lt;/code&gt; for dynamically setting instance variables, &lt;code&gt;class_eval&lt;/code&gt; for executing a block in the context of an existing class, etc.&lt;/p&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;p&gt;Let's open up the &lt;a href="https://github.com/rails/rails/blob/832fb1de704899a230c83e7c966efac03a012137/activesupport/lib/active_support/string_inquirer.rb#L21"&gt;StringInquirer Class&lt;/a&gt;. It's pretty short and there we see &lt;code&gt;method_missing&lt;/code&gt; on line 27.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class StringInquirer &amp;lt; String
    private
      def respond_to_missing?(method_name, include_private = false)
        method_name.end_with?("?") || super
      end

      def method_missing(method_name, *arguments)
        if method_name.end_with?("?")
          self == method_name[0..-2]
        else
          super
        end
      end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What is method_missing?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's review how method calls work in Ruby. When we call a method on an object, Ruby looks for the method definition in the object's class. If it doesn't find it there, it goes up the class's ancestor chain, all the way to a class called &lt;code&gt;BasicObject&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt; String.ancestors
=&amp;gt; [String, Comparable, Object, PP::ObjectMixin, Kernel, BasicObject] 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;BasicObject&lt;/code&gt; is at the top of ruby's class hierarchy. It has an instance method called &lt;code&gt;method_missing&lt;/code&gt;, that &lt;em&gt;all&lt;/em&gt; objects in ruby inherit. So if ruby can't find the method we're calling anywhere else in the ancestor chain, it admits defeat by calling &lt;code&gt;method_missing&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This implies that we can override &lt;code&gt;method_missing&lt;/code&gt; in a new class to 'catch' calls to methods that don't actually exist. These are sometimes called Ghost Methods. Why is this useful?&lt;/p&gt;

&lt;p&gt;Let's play with &lt;code&gt;StringInquirer&lt;/code&gt; to see.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt; fruit = ActiveSupport::StringInquirer.new("apple")
=&amp;gt; "apple"
&amp;gt;&amp;gt; fruit.apple?
=&amp;gt; true
&amp;gt;&amp;gt; fruit.orange?
=&amp;gt; false
&amp;gt;&amp;gt; fruit.sldjlsd?
=&amp;gt; false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can call arbitrary methods on &lt;code&gt;fruit&lt;/code&gt; and it will return &lt;code&gt;true&lt;/code&gt; for &lt;code&gt;apple&lt;/code&gt; and &lt;code&gt;false&lt;/code&gt; for everything else. Note that these are all predicate methods, ending in a &lt;code&gt;?&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That's all the &lt;code&gt;StringInquirer&lt;/code&gt; class does. But how does it reply correctly to arbitrary method names?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;StringInquirer&lt;/code&gt; Explained&lt;/p&gt;

&lt;p&gt;When we call a method &lt;code&gt;apple?&lt;/code&gt; on &lt;code&gt;fruit&lt;/code&gt; it eventually gets to &lt;code&gt;method_missing&lt;/code&gt; of &lt;code&gt;StringInquirer&lt;/code&gt;. In &lt;code&gt;method_missing&lt;/code&gt;, it checks whether the name of the method ends with a &lt;code&gt;?&lt;/code&gt;. If it does, we want to 'catch' it. If not, we pass it to &lt;code&gt;super&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When we 'catch' the method, we return the value of this comparison &lt;code&gt;self == method_name[0..-2]&lt;/code&gt;. The right hand side is just the method name without the &lt;code&gt;?&lt;/code&gt;. The value of &lt;code&gt;self&lt;/code&gt; is &lt;code&gt;fruit&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Remember we are in a method call. &lt;strong&gt;The value of&lt;/strong&gt; &lt;code&gt;self&lt;/code&gt; during a method call is the &lt;em&gt;receiver&lt;/em&gt; (the object that the method was called on). In this case, &lt;code&gt;self&lt;/code&gt; is an &lt;code&gt;ActiveSupport::StringInquirer&lt;/code&gt; object, which is a subclass of &lt;code&gt;String&lt;/code&gt;. (We will cover how the value of &lt;code&gt;self&lt;/code&gt; changes in Ruby, in a later post)&lt;/p&gt;

&lt;p&gt;If the &lt;code&gt;method_name&lt;/code&gt; does not end with a &lt;code&gt;?&lt;/code&gt;, we don't want &lt;code&gt;method_missing&lt;/code&gt; to catch that call. It passes to &lt;code&gt;super&lt;/code&gt; which will throw 'NoMethodError' error. This is important because we don't want to catch all possible method calls.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt; fruit.grow
/Users/bhumi/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/activesupport-7.0.0/lib/active_support/string_inquirer.rb:29:in `method_missing': undefined method `grow' for "apple":ActiveSupport::StringInquirer (NoMethodError)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We get our &lt;code&gt;NoMethodError&lt;/code&gt; if we call &lt;code&gt;grow&lt;/code&gt; on &lt;code&gt;fruit&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One more thing, there is also this &lt;code&gt;respond_to_missing&lt;/code&gt; in &lt;code&gt;StringInquirer&lt;/code&gt;, we'll come back to that one.&lt;/p&gt;

&lt;p&gt;But now we're ready to look at the &lt;a rel="noopener noreferrer nofollow" href="https://github.com/rails/rails/blob/832fb1de704899a230c83e7c966efac03a012137/railties/lib/rails.rb#L72"&gt;Rails sourcecode&lt;/a&gt; that makes calls like &lt;code&gt;Rails.env.development?&lt;/code&gt; possible.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    def env
      @_env ||= ActiveSupport::EnvironmentInquirer.new(ENV["RAILS_ENV"].presence || ENV["RACK_ENV"].presence || "development")
    end

    # Sets the \Rails environment.
    #
    #   Rails.env = "staging" # =&amp;gt; "staging"
    def env=(environment)
      @_env = ActiveSupport::EnvironmentInquirer.new(environment)
    end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here are the methods for reading and writing &lt;code&gt;env&lt;/code&gt;. It wraps the env name string in a class called &lt;code&gt;EnvironmentInquirer&lt;/code&gt;. We haven't seen that class yet. But I bet that's a subclass of our &lt;code&gt;StringInquirer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Yup &lt;a href="https://github.com/rails/rails/blob/main/activesupport/lib/active_support/environment_inquirer.rb#L7"&gt;it sure is&lt;/a&gt; &lt;code&gt;class EnvironmentInquirer &amp;lt; StringInquirer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The comment tells us that this class is doing some optimization for the three default environments, so it doesn't need to rely on the slower delegation through method_missing that StringInquirer uses.&lt;/p&gt;

&lt;p&gt;This class doesn't use &lt;code&gt;method_missing&lt;/code&gt; directly but it has two nice examples of dynamic programming concepts for us to explore. &lt;code&gt;instance_variable_set&lt;/code&gt; and &lt;code&gt;class_eval&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;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;raise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ArgumentError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"'local' is a reserved environment name"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"local"&lt;/span&gt;

      &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="no"&gt;DEFAULT_ENVIRONMENTS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
        &lt;span class="nb"&gt;instance_variable_set&lt;/span&gt; &lt;span class="ss"&gt;:"@&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="vi"&gt;@local&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="no"&gt;LOCAL_ENVIRONMENTS&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="no"&gt;DEFAULT_ENVIRONMENTS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="nb"&gt;class_eval&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;~&lt;/span&gt;&lt;span class="no"&gt;RUBY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;__LINE__&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;
        def &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;?
          @&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;
        end
&lt;/span&gt;&lt;span class="no"&gt;      RUBY&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what the code is doing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;instance_variable_set&lt;/code&gt; will create 3 instance variables called @development, &lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;, @production. And set them to either true or false.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Under the &lt;code&gt;class_eval&lt;/code&gt;, we define 3 methods. &lt;code&gt;development?&lt;/code&gt;, &lt;code&gt;test?&lt;/code&gt;, &lt;code&gt;production?&lt;/code&gt;. Those methods simply return the value of the instance variable with a matching name we set up earlier.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both of these are examples of metaprogramming. We are dynamically setting instance variables and defining methods at runtime.&lt;/p&gt;

&lt;p&gt;An aside: the &lt;code&gt;__FILE__, __LINE__ + 1&lt;/code&gt; stuff in the heredoc makes it so if something goes wrong in this dynamically defined methods, the debugger can point us to a file name and line number in the code. I wasn't sure, I had to look it up, but that's what I think this stuff is for.&lt;/p&gt;

&lt;p&gt;That's all. We've gotten to the bottom of this code exploration. We can see exactly how &lt;code&gt;Rails.env.production?&lt;/code&gt; works now. It's a method that is dynamically defined on the &lt;code&gt;EnvironmentInquirer&lt;/code&gt; class (which is a subclass of &lt;code&gt;StringInquirer&lt;/code&gt; and has &lt;code&gt;method_missing&lt;/code&gt; for all calls that end in a &lt;code&gt;?&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is&lt;/strong&gt; &lt;code&gt;respond_to_missing&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Before we wrap up, I said I'd come back to &lt;code&gt;respond_to_missing&lt;/code&gt;. Why is that needed?&lt;/p&gt;

&lt;p&gt;Remember that Ruby has duck typing, and we can ask any object if it responds to a given method.&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="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;fruit&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="s2"&gt;"apple?"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;fruit&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="s2"&gt;"grow"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's answering correctly because we are overriding &lt;code&gt;respond_to_missing&lt;/code&gt; in &lt;code&gt;StringInquirer&lt;/code&gt;. If we didn't, ruby will have no way of knowing that we're catching methods that end in &lt;code&gt;?&lt;/code&gt;. With this line &lt;code&gt;method_name.end_with?("?") || super&lt;/code&gt; in &lt;code&gt;respond_to_missing&lt;/code&gt; we are telling ruby that we respond to all methods that end in &lt;code&gt;?&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In general, overriding &lt;code&gt;respond_to_missing&lt;/code&gt; whenever you override &lt;code&gt;method_missing&lt;/code&gt; is a good thing to do, so our objects don't lie to us.&lt;/p&gt;

&lt;p&gt;To wrap up, We confirm that &lt;code&gt;class&lt;/code&gt; of &lt;code&gt;Rails.env&lt;/code&gt; is &lt;code&gt;ActiveSupport::EnvironmentInquirer&lt;/code&gt; which is a subclass of &lt;code&gt;ActiveSupport::StringInquirer&lt;/code&gt; and that is why we can call those handy predicate 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="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;development?&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;EnvironmentInquirer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Beautiful. It's just a tiny little feature. But in this tiny feature of ActiveSupport, we saw many metaprogramming concepts in action. We used &lt;code&gt;method_missing&lt;/code&gt; and &lt;code&gt;respond_to_missing&lt;/code&gt;. We talked about method lookup and ancestor chain and the value of &lt;code&gt;self&lt;/code&gt;. And we saw &lt;code&gt;instance_varialbe_set&lt;/code&gt; and &lt;code&gt;class_eval&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That's all I got. Hope you enjoyed this guided tour of some &lt;code&gt;ActiveSupport&lt;/code&gt; code.&lt;/p&gt;

&lt;p&gt;Until next time,&lt;/p&gt;

&lt;p&gt;Bhumi&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ruby</category>
      <category>rails</category>
      <category>oop</category>
    </item>
    <item>
      <title>Understanding Ruby Objects and Instance Variables</title>
      <dc:creator>Bhumi</dc:creator>
      <pubDate>Thu, 09 Nov 2023 03:15:07 +0000</pubDate>
      <link>https://dev.to/bhumi/understanding-ruby-objects-and-instance-variables-4157</link>
      <guid>https://dev.to/bhumi/understanding-ruby-objects-and-instance-variables-4157</guid>
      <description>&lt;p&gt;This post is part of a series on understanding Object Oriented Programming using Ruby. &lt;/p&gt;

&lt;p&gt;Subscribe to my &lt;a href="https://buttondown.email/bhumi"&gt;free newsletter&lt;/a&gt; for more.&lt;/p&gt;




&lt;p&gt;Ruby is an object oriented language and has classes and objects and methods and instance variables and all those things. But if you are coming from other object oriented languages like Java, there are a few surprising things about how Ruby objects work that are useful to know. &lt;/p&gt;

&lt;p&gt;Here are some interesting things about ruby objects and instance variable and methods to keep in mind when you read/write Ruby code:&lt;/p&gt;

&lt;h2&gt;
  
  
  Objects of the same &lt;code&gt;class&lt;/code&gt; can carry different instance variables.
&lt;/h2&gt;

&lt;p&gt;In other words, instance variables 'belong to' or 'live in' the object. There is no connection between an object's class and its instance variables.&lt;/p&gt;

&lt;p&gt;Imagine we have this class Hello and two objects h1 and h2. h2 has the &lt;code&gt;@last_name&lt;/code&gt; instance variable but h1 does not.&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="sc"&gt;?&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Hello&lt;/span&gt;
&lt;span class="sc"&gt;?&amp;gt;&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
&lt;span class="sc"&gt;?&amp;gt;&lt;/span&gt;     &lt;span class="vi"&gt;@name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Annie"&lt;/span&gt;
&lt;span class="sc"&gt;?&amp;gt;&lt;/span&gt;     &lt;span class="vi"&gt;@greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Hello"&lt;/span&gt;
&lt;span class="sc"&gt;?&amp;gt;&lt;/span&gt;   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;Hello:0x00007fa46786a930 @greeting="Hello", @name="Annie"&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;h2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;Hello:0x00007fa462f059e8 @greeting="Hello", @name="Annie"&amp;gt;&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# Add an instance variable to one of the two objects, h2 but not h1&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_variable_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"@last_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Smith"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Smith"&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;h2&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;Hello:0x00007fa462f059e8 @greeting="Hello", @last_name="Smith", @name="Annie"&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;Hello:0x00007fa46786a930 @greeting="Hello", @name="Annie"&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now &lt;code&gt;h1&lt;/code&gt; and &lt;code&gt;h2&lt;/code&gt; are objects of the same class &lt;code&gt;Hello&lt;/code&gt; but have different set of instance variables. What do you think will happen if we add an instance method to &lt;code&gt;Hello&lt;/code&gt; that &lt;em&gt;uses&lt;/em&gt; &lt;code&gt;@last_name&lt;/code&gt;? Let's see.&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="sc"&gt;?&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Hello&lt;/span&gt;
&lt;span class="sc"&gt;?&amp;gt;&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;
&lt;span class="sc"&gt;?&amp;gt;&lt;/span&gt;     &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@greeting&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@last_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="sc"&gt;?&amp;gt;&lt;/span&gt;   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;greet&lt;/span&gt;
&lt;span class="no"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Annie&lt;/span&gt; &lt;span class="no"&gt;Smith&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;greet&lt;/span&gt;
&lt;span class="no"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Annie&lt;/span&gt; 

&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_variable_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"@last_name"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_variable_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"@blah"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing crazy. Things just work as expected. Looks like the value of &lt;em&gt;any&lt;/em&gt; instance variables that have not been assigned is &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now let's talk about the instance methods.&lt;/p&gt;

&lt;h2&gt;
  
  
  Methods of an object 'live in' the object's class.
&lt;/h2&gt;

&lt;p&gt;So unlike instance variables, &lt;em&gt;methods&lt;/em&gt; of an object are attached to its class. From the class's perspective they are called &lt;em&gt;instance methods&lt;/em&gt;. From the object's perspective they are just &lt;em&gt;methods&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;We can list the methods of an object by calling the &lt;code&gt;Object#methods&lt;/code&gt; method on the object or the &lt;code&gt;Module#instance_methods&lt;/code&gt; method on its class. (these methods are inherited from ruby's &lt;code&gt;Object&lt;/code&gt; and &lt;code&gt;Module&lt;/code&gt; classes. We'll talk more about ruby's class hierarchy in a later post).&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="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;Hello:0x00007f843b8c1038&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;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;# 'false' excludes methods from ancestors&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_methods&lt;/span&gt;  &lt;span class="c1"&gt;# without 'false', many inherited methods&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:pretty_print&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                              
 &lt;span class="ss"&gt;:pretty_print_inspect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;...&lt;/span&gt;
 &lt;span class="ss"&gt;:__send__&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;methods&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_methods&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;

&lt;span class="sc"&gt;?&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Hello&lt;/span&gt;
&lt;span class="sc"&gt;?&amp;gt;&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greeting&lt;/span&gt;
&lt;span class="sc"&gt;?&amp;gt;&lt;/span&gt;     &lt;span class="s2"&gt;"hello"&lt;/span&gt;
&lt;span class="sc"&gt;?&amp;gt;&lt;/span&gt;   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:greeting&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:greeting&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In the above example, we create an empty class &lt;code&gt;Hello&lt;/code&gt; and an object &lt;code&gt;h&lt;/code&gt; and confirm that the object's methods are same as its class's instance_methods. Then we add a method &lt;code&gt;greeting&lt;/code&gt; and see it appear in the list of object's methods / classes's instance_methods.&lt;/p&gt;

&lt;p&gt;Aside: note that in Ruby, we can add methods to a single object as well. In that case, they are not called instance methods or methods though. They are called singleton methods. When add methods to an object, that object has methods that no other object of the same class does. (If that sounds wild to you, you're not alone! We'll get to how that works in a later post. It requires learning about the concept of singleton class (aka eigenclass, aka metaclass)).&lt;/p&gt;

&lt;p&gt;One more interesting thing about instance variables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Instance variables spring into action when you assign them.
&lt;/h2&gt;

&lt;p&gt;In other words, they don't have to be 'declared' ahead of time, as part of the class definition.&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="o"&gt;&amp;gt;*&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Hello&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;*&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_instance_var_person&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;*&lt;/span&gt;     &lt;span class="vi"&gt;@person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Joe"&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;*&lt;/span&gt;   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;Hello:0x00007fecc46a3160&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_variables&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_instance_var_person&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Joe"&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_variables&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:@person&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, we create a class &lt;code&gt;Hello&lt;/code&gt; with an &lt;em&gt;instance method&lt;/em&gt; that defines an &lt;em&gt;instance variable&lt;/em&gt; &lt;code&gt;@person&lt;/code&gt;. An object that is an instance of &lt;code&gt;Hello&lt;/code&gt; that calls the method &lt;code&gt;add_instance_var_person&lt;/code&gt; will have &lt;code&gt;@person&lt;/code&gt; instance variable 'attached' to it. But before it calls that method, it's list of instance variables is empty &lt;code&gt;[]&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;This implies that another object of &lt;code&gt;Hello&lt;/code&gt; that has never called the instance method will not have the instance variable &lt;code&gt;@person&lt;/code&gt;. This goes hand in hand with first fact above. Objects of the same class can have different instance variables 'attached' to them.  &lt;/p&gt;

&lt;p&gt;This may all feel surprising. At least it did to me at first.&lt;/p&gt;

&lt;p&gt;To wrap up, what is an object in Ruby? An object is composed of a bunch of instance variables and a link to a class. Object's class carries its instance methods but its instance variables live in the object itself.&lt;/p&gt;

&lt;p&gt;Until next time,&lt;/p&gt;

&lt;p&gt;Bhumi&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ruby</category>
      <category>rails</category>
      <category>oop</category>
    </item>
    <item>
      <title>Stimulus Rails 7 Tutorial</title>
      <dc:creator>Bhumi</dc:creator>
      <pubDate>Thu, 17 Feb 2022 20:33:06 +0000</pubDate>
      <link>https://dev.to/bhumi/stimulus-rails-7-tutorial-5a6a</link>
      <guid>https://dev.to/bhumi/stimulus-rails-7-tutorial-5a6a</guid>
      <description>&lt;p&gt;Hotwire (HTML-over-the-wire) ships by default in Rails 7. Stimulus is one component of Hotwire, the other one being &lt;a href="https://codecurious.dev/introduction-to-hotwire-and-turbo/"&gt;Turbo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The key promise of the Hotwire approach is to get the benefits of single-page JavaScript applications like faster, more fluid user interfaces without writing much Javascript (certaintly not the amount needed with full-fledge client-side JavaScript frameworks). &lt;/p&gt;

&lt;p&gt;But Javascript on-the-page is still needed for modern web app behaviors like show/hide elements, add item to a todo list, etc. This is where StimulusJS comes in. &lt;/p&gt;

&lt;p&gt;Simulus is adverstised as a minimal Javascript framework. It has been around since 2017-2018. The latest version, stimulus 3.0 was released in October 2021. &lt;/p&gt;

&lt;p&gt;It is small and simple enough that if you try the examples in this post, you should have good handle on how to use Stimulus in the next 15 minutes.&lt;/p&gt;

&lt;p&gt;Fun fact - Stimulus use the browser's &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver"&gt;MutationObserver API&lt;/a&gt; to detect DOM chagnes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Let's see some code first. Consider the following html:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-controller=&lt;/span&gt;&lt;span class="s"&gt;"clipboard"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  PIN: &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;data-clipboard-target=&lt;/span&gt;&lt;span class="s"&gt;"source"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"1234"&lt;/span&gt; &lt;span class="na"&gt;readonly&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;data-action=&lt;/span&gt;&lt;span class="s"&gt;"clipboard#copy"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Copy to Clipboard&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some facts to note about Stimilus from the above code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can get an idea of what's going on by looking at the HTML alone, without looking at the &lt;code&gt;clipboard&lt;/code&gt; controller code. (This is different from other HTML where an external JS file applies event handlers to it.)&lt;/li&gt;
&lt;li&gt;Stimulus does not bother itself by &lt;em&gt;creating&lt;/em&gt; the HTML. That's still rendered on the server either on page load (first hit or via Turbo) or via Ajax request that changes the DOM.&lt;/li&gt;
&lt;li&gt;Stimulus is concerned with manipulating the existing HTML document. By adding a CSS class that hides, animates, highlights an element. &lt;/li&gt;
&lt;li&gt;Stimulus &lt;em&gt;can&lt;/em&gt; create new DOM elements and that's allowed. But that's minority case. The focus is on manipulating not creating elements.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How Stimulus differs from mainstream JavaScript frameworks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Other frameworks are focused on turning JSON into DOM elements via template language&lt;/li&gt;
&lt;li&gt;Other frameworks maintain &lt;em&gt;state&lt;/em&gt; within JavaSripts objects.
For Stimulas, state is stored in the HTML, so that controllers can be discarded between page changes, but still reinitialize as they were when the cached HTML appears again.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How Stimulus Works
&lt;/h3&gt;

&lt;p&gt;Stimulus is designed to enhance &lt;em&gt;static&lt;/em&gt; or &lt;em&gt;server-rendered&lt;/em&gt; HTML by connecting JavaScript objects to elements on the page using simple annotations.&lt;/p&gt;

&lt;p&gt;These JavaScript objects are called &lt;em&gt;controllers&lt;/em&gt; and Stimulus monitors the page waiting for HTML &lt;code&gt;data-controller&lt;/code&gt; attributes to appear. Each attribute's value is a controller class name. Stimulus finds that class, creates a new instance of that class and connects it to the element. &lt;/p&gt;

&lt;p&gt;Just like &lt;code&gt;class&lt;/code&gt; attribute is a bridge connecting HTML to CSS. &lt;code&gt;data-controller&lt;/code&gt; attribute is a bridge connecting HTML to JavaScript.&lt;/p&gt;

&lt;p&gt;In addition to controllers, 3 other major Stimulus concepts are:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;actions&lt;/strong&gt; - which connect controller methods to DOM events using &lt;code&gt;data-action&lt;/code&gt; attributes&lt;br&gt;
&lt;strong&gt;targets&lt;/strong&gt; - which locate elements of significance within a controller&lt;br&gt;
&lt;strong&gt;values&lt;/strong&gt; - which read/write/observe data attributes on the controller's element&lt;/p&gt;

&lt;p&gt;We will see more examples of how controllers, actions, targets, and values are used in the code below.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;span&gt;These examples are from the official Stimulus Handbook, you can find the repo &lt;a href="https://github.com/hotwired/stimulus-starter"&gt;here&lt;/a&gt;.&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Hello World in Stimulus
&lt;/h2&gt;

&lt;p&gt;This example prints a greeting when user clicks a button, along with the name that was typed into a text box. Demonstrates how &lt;em&gt;actions&lt;/em&gt; and &lt;em&gt;targets&lt;/em&gt; are used in the code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-controller=&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;data-hello-target=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;data-action=&lt;/span&gt;&lt;span class="s"&gt;"click-&amp;gt;hello#greet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Greet&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;&lt;code&gt;data-controller&lt;/code&gt;&lt;/strong&gt; connects this HTML to a class in hello_controller.js file. Stimulus also auto initializes this controller object.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;&lt;code&gt;data-action&lt;/code&gt;&lt;/strong&gt; means when this button is clicked, execute the code inside the &lt;code&gt;greet&lt;/code&gt; method of the &lt;code&gt;hello&lt;/code&gt; controller.&lt;/p&gt;

&lt;p&gt;The value &lt;code&gt;click-&amp;gt;hello#greet&lt;/code&gt; is called an &lt;em&gt;action descriptor&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If you try this you may notice that it works without the &lt;code&gt;click-&amp;gt;&lt;/code&gt; part, so just &lt;code&gt;data-action="hello#greet"&lt;/code&gt; works too. This is because Stimulus defines default actions for some elements (i.e. &lt;code&gt;click&lt;/code&gt; for a &lt;code&gt;button&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;&lt;code&gt;data-[controller-name]-target&lt;/code&gt;&lt;/strong&gt; is a way to connect this HTML element to the controller such that it's value can be accessed inside the controller. In this case &lt;code&gt;data-hello-target&lt;/code&gt;. This is what the code looks like inside &lt;code&gt;hello_controller.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@hotwired/stimulus&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;targets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nameTarget&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`hello, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We create a property for the target by adding &lt;code&gt;name&lt;/code&gt; to our controller’s list of target definitions. Stimulus &lt;em&gt;will automatically create&lt;/em&gt; a &lt;code&gt;this.nameTarget&lt;/code&gt; property which returns the first matching target element. We can use this property to read the element’s &lt;code&gt;value&lt;/code&gt; and build our greeting string.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Copy to Clipboard Button
&lt;/h2&gt;

&lt;p&gt;You know the little copy button or icon next to some text to make it easy to copy to clipboard. The below code builds that functionality in Stimulus using the browser's Clipboard API.&lt;/p&gt;

&lt;p&gt;The HTML looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  Example: Copy To Clipboard
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-controller=&lt;/span&gt;&lt;span class="s"&gt;"clipboard"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    PIN: &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;data-clipboard-target=&lt;/span&gt;&lt;span class="s"&gt;"source"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"1234"&lt;/span&gt; &lt;span class="na"&gt;readonly&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;data-action=&lt;/span&gt;&lt;span class="s"&gt;"clipboard#copy"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Copy to Clipboard&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  More than one instance of the clipboard controller on the page
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-controller=&lt;/span&gt;&lt;span class="s"&gt;"clipboard"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    PIN: &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;data-clipboard-target=&lt;/span&gt;&lt;span class="s"&gt;"source"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"5678"&lt;/span&gt; &lt;span class="na"&gt;readonly&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;data-action=&lt;/span&gt;&lt;span class="s"&gt;"clipboard#copy"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Copy to Clipboard&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  Use other HTML elements like link and textarea (instead of button and input)
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-controller=&lt;/span&gt;&lt;span class="s"&gt;"clipboard"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    PIN: &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;data-clipboard-target=&lt;/span&gt;&lt;span class="s"&gt;"source"&lt;/span&gt; &lt;span class="na"&gt;readonly&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;3737&lt;span class="nt"&gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;data-action=&lt;/span&gt;&lt;span class="s"&gt;"clipboard#copy"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"clipboard-button"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Copy to Clipboard&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;clipboard_controller.js&lt;/code&gt; looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@hotwired/stimulus&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;targets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;source&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="c1"&gt;//v1 - with a button, using the browswer Clipboard API&lt;/span&gt;
  &lt;span class="nx"&gt;copy_old&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clipboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sourceTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;//v2 - copy action attached to &amp;lt;a&amp;gt; link, input from a &amp;lt;textarea&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sourceTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;select&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;execCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;copy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some interesting things to learn from the above example:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does the &lt;code&gt;static targets&lt;/code&gt; line do?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When Stimulus loads our controller class, it looks for a static array with the name &lt;code&gt;targets&lt;/code&gt;. For each target name in the array, Stimulus adds three new properties to our controller. For the "source" target name above, we get these 3 properties -- &lt;code&gt;this.sourceTarget&lt;/code&gt;, &lt;code&gt;this.sourceTargets&lt;/code&gt;, and &lt;code&gt;this.hasSourceTarget&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We can instantiate the same controller more than once on a page&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Stimulus controllers are reusable. Any time we want to provide a way to copy a bit of text to the clipboard, all we need is the markup on the page with the right &lt;code&gt;data-&lt;/code&gt; annotations. And it just works.&lt;/p&gt;

&lt;p&gt;In the HTML above, we have the exact same &lt;code&gt;div&lt;/code&gt; for copying PINs duplicated twice. The 2nd copy has a different value so we can test that both copy button work and copy the right thing. The thing that's implicit here is that we have two different instances of the controller class, and each instance has its own &lt;code&gt;sourctTarget&lt;/code&gt; property with the correct &lt;code&gt;value&lt;/code&gt;. This is how we keep them separate the copy the corresponding value (and don't get the values mixed up with the other &lt;code&gt;input&lt;/code&gt; element annotated with &lt;code&gt;data-clipboard-target="source"&lt;/code&gt; on the page). It's because the &lt;em&gt;controller&lt;/em&gt; is scoped to the &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This implies that if we put &lt;em&gt;two&lt;/em&gt; buttons inside the same &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;, things would not work as expect. The below will always copy the value in the &lt;em&gt;first&lt;/em&gt; text box:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-controller=&lt;/span&gt;&lt;span class="s"&gt;"clipboard"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    PIN: &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;data-clipboard-target=&lt;/span&gt;&lt;span class="s"&gt;"source"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"1234"&lt;/span&gt; &lt;span class="na"&gt;readonly&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;data-action=&lt;/span&gt;&lt;span class="s"&gt;"clipboard#copy"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Copy to Clipboard&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    PIN: &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;data-clipboard-target=&lt;/span&gt;&lt;span class="s"&gt;"source"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"this won't get copied"&lt;/span&gt; &lt;span class="na"&gt;readonly&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;data-action=&lt;/span&gt;&lt;span class="s"&gt;"clipboard#copy"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Copy to Clipboard&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Actions and Targets can go on any HTML elements&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So do we have to use a &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; for the copy to clipboard functionality? No we could use other elements like a link &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag. (In which we want to make sure to preventDefatult).&lt;/p&gt;

&lt;p&gt;We can also use a &lt;code&gt;&amp;lt;textarea&amp;gt;&lt;/code&gt; instead of the &lt;code&gt;&amp;lt;input type="text"&amp;gt;&lt;/code&gt;. The controller only expects it to have a &lt;code&gt;value&lt;/code&gt; property and a &lt;code&gt;select()&lt;/code&gt; method.&lt;/p&gt;

&lt;h2&gt;
  
  
  Designing for Progressive Enhancement
&lt;/h2&gt;

&lt;p&gt;This is about building in support for older browsers as well as considering what happens to our application when there are network or CDN issues.&lt;/p&gt;

&lt;p&gt;It may be tempting to write these things off as not important but often it’s trivially easy to build features in a way that’s gracefully resilient to these types of problems.&lt;/p&gt;

&lt;p&gt;This approach, commonly known as &lt;strong&gt;progressive enhancement&lt;/strong&gt;, is the practice of delivering web interfaces where the basic functionality is implemented in HTML and CSS. Tiered upgrades to that base experience are layered on top with CSS and JavaScript, progressively, when supported by the browser.&lt;/p&gt;

&lt;p&gt;With the clipboard API the idea is to hide the &lt;code&gt;Copy to Clipboard&lt;/code&gt; button unless the browser has support for the clipboard API. We do this by adding classes to the HTML, adding a bit of CSS to hide the button, and adding a &lt;em&gt;feature check&lt;/em&gt; in our JavaScript controller to toggle the class to show the button if the browser supports clipboard API.&lt;/p&gt;

&lt;p&gt;The HTML looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-controller=&lt;/span&gt;&lt;span class="s"&gt;"clipboard"&lt;/span&gt; &lt;span class="na"&gt;data-clipboard-supported-class=&lt;/span&gt;&lt;span class="s"&gt;"clipboard--supported"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    PIN: &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;data-clipboard-target=&lt;/span&gt;&lt;span class="s"&gt;"source"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"1234"&lt;/span&gt; &lt;span class="na"&gt;readonly&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;data-action=&lt;/span&gt;&lt;span class="s"&gt;"clipboard#copy"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"clipboard-button"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Copy to Clipboard&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;  
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we add a &lt;code&gt;connect()&lt;/code&gt; method to the &lt;code&gt;clipboard_controller.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;supported&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="nx"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;clipboard-write&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;granted&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;supportedClass&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;An issue I ran into locally on firefox with clipboard-write&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This code runs happily on Chrome and does the progressive enhancement. On firefox, I get the error in console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Uncaught (in promise) TypeError: 'clipboard-write' (value of 'name' member of PermissionDescriptor) is not a valid value for enumeration PermissionName.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So even the code to check whether a given browser has access to a feature, in this case clipboard API, itself has browser specific issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  Managing State - Slideshow Controller
&lt;/h2&gt;

&lt;p&gt;Most JavaScript frameworks encourage you to &lt;em&gt;keep state in JavaScript&lt;/em&gt; at all times. They treat the DOM as a write-only rendering target (using client-side templates after consuming JSON from the server).&lt;/p&gt;

&lt;p&gt;Stimulus takes a different approach. A Stimulus application’s state lives as &lt;em&gt;attributes in the DOM&lt;/em&gt;; controllers (i.e. the JavaScript parts) are largely &lt;em&gt;stateless&lt;/em&gt;. This approach makes it possible to work with HTML from anywhere—the initial document, an Ajax request, a Turbo visit, or even another JavaScript library.&lt;/p&gt;

&lt;p&gt;We build a slideshow controller that keeps the index of the currently selected slide in an attribute, to learn how to store values as state in Stimulus.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lifecycle callbacks in Stimulus&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Stimulus lifecycle callback methods are useful for setting up or tearing down associated state when our controller enters or leaves the document.&lt;/p&gt;

&lt;p&gt;These methods are invoked by Stimulus:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;initialize()&lt;/code&gt; - Once, when the controller is first instantiated&lt;br&gt;
&lt;code&gt;connect()&lt;/code&gt; - Anytime the controller is connected to the DOM&lt;br&gt;
&lt;code&gt;disconnect()&lt;/code&gt; - Anytime the controller is disconnected from the DOM&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using Values in Stimulus&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The concept of &lt;em&gt;values&lt;/em&gt; is another core thing to Stimulus, similar to the concept of &lt;em&gt;controllers&lt;/em&gt;, &lt;em&gt;actions&lt;/em&gt;, and &lt;em&gt;targets&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Stimulus controllers support typed &lt;code&gt;value&lt;/code&gt; properties which automatically map to data attributes. &lt;code&gt;value&lt;/code&gt; is a hash while &lt;code&gt;targets&lt;/code&gt; and &lt;code&gt;classes&lt;/code&gt; are arrays. When we add a value definition to our controller class like this &lt;code&gt;static values = { index: Number }&lt;/code&gt;, Stimulus creates a &lt;code&gt;this.indexValue&lt;/code&gt; controller property associated with a &lt;code&gt;data-slideshow-index-value&lt;/code&gt; attribute (and handles the numeric conversion for us).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Value change callback&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the code below, notice how we are having to manually call the &lt;code&gt;this.showCurrentSlide()&lt;/code&gt; method each time we change the value in &lt;code&gt;this.indexValue&lt;/code&gt;. Actually Stimulus will automatically do this for us if we add a method with this name &lt;code&gt;indexValueChanged()&lt;/code&gt;. This method will be called at initialization and in response to any change to the &lt;code&gt;data-slideshow-index-value&lt;/code&gt; attribute (including if we make changes to it in the web inspector). Once we add &lt;code&gt;indexValueChanged()&lt;/code&gt; we can also remove the &lt;code&gt;initialize()&lt;/code&gt; method altogether.&lt;/p&gt;

&lt;p&gt;The HTML code looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-controller=&lt;/span&gt;&lt;span class="s"&gt;"slideshow"&lt;/span&gt; &lt;span class="na"&gt;data-slideshow-index-value=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;data-action=&lt;/span&gt;&lt;span class="s"&gt;"slideshow#previous"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; ← &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;data-action=&lt;/span&gt;&lt;span class="s"&gt;"slideshow#next"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; → &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-slideshow-target=&lt;/span&gt;&lt;span class="s"&gt;"slide"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;🐵&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-slideshow-target=&lt;/span&gt;&lt;span class="s"&gt;"slide"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;🙈&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-slideshow-target=&lt;/span&gt;&lt;span class="s"&gt;"slide"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;🙉&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-slideshow-target=&lt;/span&gt;&lt;span class="s"&gt;"slide"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;🙊&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;slideshow_controller.js&lt;/code&gt; looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@hotwired/stimulus&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;targets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;slide&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;showCurrentSlide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexValue&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;showCurrentSlide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexValue&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;showCurrentSlide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;showCurrentSlide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slideTargets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hidden&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexValue&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can use the web inspector to confirm that the controller element’s &lt;code&gt;data-slideshow-index-value&lt;/code&gt; attribute changes as we move from one slide to the next. And that the &lt;code&gt;hidden&lt;/code&gt; attribute is added and removed from each of the slide elements as we navigate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working With External Resources - HTTP Requests and Timers
&lt;/h2&gt;

&lt;p&gt;Sometimes our controllers need to track the state of external resources, where by external we mean anything that isn’t in the DOM or a part of Stimulus.&lt;/p&gt;

&lt;p&gt;This example build a simple email inbox where the html for new messages is loaded asychronously (in the example messages.html is just a static file but normally the server would return this html) using &lt;code&gt;fetch&lt;/code&gt; and then plopped into the &lt;code&gt;innerHTML&lt;/code&gt; of the controller's &lt;code&gt;div&lt;/code&gt;. We then also use a timer to refresh and load new messages every 5 seconds.&lt;/p&gt;

&lt;p&gt;This timer is started and stopped in the life-cycle methods, &lt;code&gt;connect()&lt;/code&gt; and &lt;code&gt;disconnect()&lt;/code&gt;, respectively.&lt;/p&gt;

&lt;p&gt;The HTML placeholder looks like this, annotated with Stimulus attributes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-controller=&lt;/span&gt;&lt;span class="s"&gt;"content-loader"&lt;/span&gt; &lt;span class="na"&gt;data-content-loader-url-value=&lt;/span&gt;&lt;span class="s"&gt;"/messages.html"&lt;/span&gt; &lt;span class="na"&gt;data-content-loader-refresh-interval-value=&lt;/span&gt;&lt;span class="s"&gt;"5000"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;content_loader_controller.js&lt;/code&gt; looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@hotwired/stimulus&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;refreshInterval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasRefreshIntervalValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startRefreshing&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;disconnect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stopRefreshing&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;urlValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;startRefreshing&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;refreshTimer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;refreshIntervalValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;stopRefreshing&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;refreshTimer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;refreshTimer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using content-loader controller on multiple elements
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;params&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So far we have seen the concepts of &lt;em&gt;controllers&lt;/em&gt;, &lt;em&gt;actions&lt;/em&gt;, &lt;em&gt;targets&lt;/em&gt;, and &lt;em&gt;values&lt;/em&gt;. &lt;em&gt;params&lt;/em&gt; is another Stimulus feature. &lt;em&gt;params&lt;/em&gt; are associated with the element and not 'attached' at the controller level, unlike &lt;em&gt;values&lt;/em&gt; and &lt;em&gt;targets&lt;/em&gt; (i.e. there is not a &lt;code&gt;static params =&lt;/code&gt; in the controller)&lt;/p&gt;

&lt;p&gt;Here is an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-controller=&lt;/span&gt;&lt;span class="s"&gt;"content-loader"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;data-content-loader-url-param=&lt;/span&gt;&lt;span class="s"&gt;"/messages.html"&lt;/span&gt; &lt;span class="na"&gt;data-action=&lt;/span&gt;&lt;span class="s"&gt;"content-loader#load"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Messages&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;data-content-loader-url-param=&lt;/span&gt;&lt;span class="s"&gt;"/comments.html"&lt;/span&gt; &lt;span class="na"&gt;data-action=&lt;/span&gt;&lt;span class="s"&gt;"content-loader#load"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Comments&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;-url-param&lt;/code&gt; can accessed in the controller's &lt;code&gt;load&lt;/code&gt; action with &lt;code&gt;params.url&lt;/code&gt;, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@hotwired/stimulus&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What happens if you add the same data-controller to nested HTML elements?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I made a goofy mistake of adding &lt;code&gt;data-controller="content-loader"&lt;/code&gt; to that 2nd &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag above, in addition to it being on the parent &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; already. And got to see some wonderfully weird results. The entire index.html loaded over and over again on the page, I could see the calls piling up in the network tab and the page's scroll bar getting smaller and smaller. Perhaps I can think through this and use it a way to play around with the internal workings of Stimulus. This specific thing was further convoluted by the fact that the above &lt;code&gt;load&lt;/code&gt; method was done in parallel with another &lt;code&gt;load&lt;/code&gt; method from the original example of getting inbox messages loaded with a 5 second interval timer. &lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In the examples above, we have seen the main concepts of Stimulus - controllers, actions, targets and values. Stimulus allows us to add behavior to static or server-rendered HTML by connecting JavaScript objects to elements on the page using simple annotations - the &lt;code&gt;data-&lt;/code&gt; attributes on out HTML elements.&lt;/p&gt;




&lt;p&gt;For more in-depth posts on all things Rails, Ruby, and Software Development, check out &lt;a href="https://codecurious.dev/welcome/"&gt;CodeCurious&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>rails</category>
    </item>
    <item>
      <title>All About Hotwire and Turbo</title>
      <dc:creator>Bhumi</dc:creator>
      <pubDate>Mon, 14 Feb 2022 19:53:30 +0000</pubDate>
      <link>https://dev.to/bhumi/all-about-hotwire-and-turbo-17hn</link>
      <guid>https://dev.to/bhumi/all-about-hotwire-and-turbo-17hn</guid>
      <description>&lt;h2&gt;
  
  
  For more in-depth content on web development check out &lt;a href="https://codecurious.dev/welcome/"&gt;CodeCurious&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Surely you've heard of &lt;code&gt;Hotwire&lt;/code&gt; by now and perhaps thought "cute name but what the heck is that? and do I  need to care about it?" &lt;/p&gt;

&lt;p&gt;I went about answering that question for myself and wrote down what I learned. If you have 10 minutes and are curious about Hotwire and Turbo, read on.&lt;/p&gt;

&lt;p&gt;You do not need to be Ruby on Rails developer to read this. The ideas around Hotwire and server-side rendering are making waves across different web development stacks - PHP/Laravel, Elixir/Pheonix, Python/Dyango have equivalent tech that implements Hotwire. Even React has added support for server-side rendering it seems.&lt;/p&gt;

&lt;p&gt;The following writing is for wrapping our heads around the &lt;em&gt;concepts&lt;/em&gt;. So you can sit back with your coffee/tea and just read (not much code to type-along).&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Hotwire and What is Turbo
&lt;/h2&gt;

&lt;p&gt;HTML-over-the-wire or Hotwire is a &lt;em&gt;technique&lt;/em&gt; for building web applications. It's not one technology, it's an umbrella term for Turbo, StimulusJS, and Strada (in the Rails world). Turbo &lt;em&gt;is&lt;/em&gt; the actual technology that makes the Hotwire approach possible. Turbo is the actual &lt;a href="https://github.com/hotwired/turbo"&gt;code&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Yes Turbo is created by the team behind Ruby on Rails and it's an evolution of Turbolinks with bunch of other functionality added.  But Turbo can be adapted to other languages and backend frameworks (and &lt;a href="https://github.com/tonysm/turbo-laravel"&gt;already&lt;/a&gt; &lt;a href="https://github.com/hotwire-django/turbo-django"&gt;has&lt;/a&gt;!). This Turbo thing is &lt;em&gt;not&lt;/em&gt; Rails specific.&lt;/p&gt;

&lt;p&gt;So what does the Turbo code do? What problem does it solve? How does it help us?&lt;/p&gt;

&lt;p&gt;Officially "Turbo is a collection of techniques for creating fast, progressively enhanced web applications without using much JavaScript. All the logic lives on the server, and the browser deals just with the final HTML."&lt;/p&gt;

&lt;p&gt;This approach can, of course, be contrasted with the Single Page Application (SPA) approach. Where we'd get JSON from the server, use client-side JavaScript (like a boatload of JS involving frameworks and libraries that need to keep state and do routing) to eventually transform that JSON data into DOM updates.&lt;/p&gt;

&lt;p&gt;The promise of Turbo is writing less JavaScript and more of your preferred backend language - Ruby or PHP or Python or what have you. All of your logic for interacting with your domain model and other business logic can live in one place, on your server. The other promise is to sidestep the complexity of full-fledge client-side JavaScript frameworks and the associated tooling (&lt;em&gt;cough&lt;/em&gt; webpack). The only JavaScript you need is Turbo.js&lt;/p&gt;

&lt;p&gt;Of course we'd want to get these benefits without sacrificing any of the speed or responsiveness associated with modern web applications with rich user experiences. And that is just what hotwire.dev promises.&lt;/p&gt;

&lt;p&gt;If we go all the back to AJAX, the official documentation (and by that I mean wikipedia) says &lt;/p&gt;

&lt;p&gt;"With Ajax, web applications can &lt;em&gt;send and retrieve data from a server asynchronously&lt;/em&gt; (in the background) without interfering with the display and behavior of the existing page...Ajax allows web pages and, by extension, web applications, to &lt;em&gt;change content dynamically without the need to reload the entire page&lt;/em&gt;." &lt;/p&gt;

&lt;p&gt;So in other words, the big promise of AJAX was to 'update content &lt;em&gt;without&lt;/em&gt; full-page reload'. So that it feels smooth and fast for the user. That is &lt;em&gt;still&lt;/em&gt; what we are after. With Turbo we can do this in a simpler, more elegant way and automatically get the benefits by including Turbo.js and following some convestions (without writing much if any JavaScript!).&lt;/p&gt;

&lt;p&gt;Turbo does its job with the following components: &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Turbo Drive&lt;/strong&gt; speeds up links and form submissions by not requiring page reloads.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Turbo Frames&lt;/strong&gt; decompose pages into independent contexts, which scope navigation and can be lazily loaded.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Turbo Streams&lt;/strong&gt; deliver page changes over WebSocket, SSE or in response to form submissions using just HTML and a set of CRUD-like actions.&lt;/p&gt;

&lt;p&gt;[aside] SSE is server-sent events. The major difference between WebSockets and Server-Sent Events is that WebSockets are bidirectional (allowing communication between the client and the server) while SSEs are one-directional (only allowing the client to receive data from the server).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Turbo Native&lt;/strong&gt; lets your majestic monolith form the center of your native iOS and Android apps, with seamless transitions between web and native sections.&lt;/p&gt;

&lt;p&gt;Turbo 7.1 was released November 24, 2021 (keeping the Turbolinks versions) and Hotwire ships by default in Rails 7, released December 15, 2022. Let's see how each of the 4 Turbo components work. We also cover some constraints and nuances to keep in mind when building applications with Turbo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turbo Drive: Navigate Within a Persistent Process
&lt;/h2&gt;

&lt;p&gt;Turbo Drive gives us the same speed of SPA by using the same persistent process. The persistent process is managed by Turbo (there is no client-side router, no state to carefully manage). &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Following Links&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This works by intercepting all clicks on &lt;code&gt;&amp;lt;a href&amp;gt;&lt;/code&gt; links to the same domain. When you click an eligible link, Turbo Drive prevents the browser from following it, changes the browser’s URL using the History API, requests the new page using fetch, and then renders the HTML response.&lt;/p&gt;

&lt;p&gt;[aside] History API - allows manipulation of the browser &lt;em&gt;session history&lt;/em&gt;, that is the pages visited in the tab or frame that the current page is loaded in. I see the &lt;code&gt;pushState()&lt;/code&gt; function is part of this API (which is what &lt;code&gt;pjax&lt;/code&gt; used to update browser URL, etc.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Form Submission&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;During rendering, Turbo Drive replaces the current &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; element outright and merges the contents of the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; element. The JavaScript &lt;code&gt;window&lt;/code&gt; and &lt;code&gt;document&lt;/code&gt; objects, and the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; element, persist from one rendering to the next.&lt;/p&gt;

&lt;p&gt;The speed with Turbo happens free just by following a few conventions. Though it is possible to interact directly with Turbo Drive to control how visits happen or hook into the lifecycle of the request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turbo Frames: Decompose Complex Pages
&lt;/h2&gt;

&lt;p&gt;Turbo Frames is a way to scope independent segments of a page inside a &lt;code&gt;turbo-frame&lt;/code&gt; element such that they can be lazily loaded and their navigation be scoped. Scoped navigation means all interaction within a frame (e.g. clicking links, submitting forms) happen within that frame, keeping rest of the page from reloading.&lt;/p&gt;

&lt;p&gt;I heard DHH say on Remote Ruby interview that the origins of Turbo Frames are based on making mobile stuff work for Hey email.&lt;/p&gt;

&lt;p&gt;[aside] the use case for which this is designed, reminds me of the 'aync dashboard' work I did to speed up the Dashboard of our web app at Castlight. Loading bits of the page 'later', in parallel instead of in-band with the initial page load. I recall using .js.erb files I think and looking at the network tab a lot.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scoped Navigation&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;turbo-frame&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"new_message"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"/messages"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    ...
  &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/turbo-frame&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we submit the form above, Turbo extracts the matching &lt;code&gt;turbo-frame&lt;/code&gt; element with the &lt;code&gt;id&lt;/code&gt; of &lt;code&gt;new_messages&lt;/code&gt; from the HTML response and swaps its content into the existing &lt;code&gt;new_message&lt;/code&gt; frame element. The rest of the page stays as it was.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deferred Loading&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;turbo-frame&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"messages"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/messages"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This message will be replaced by the response from /messages.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/turbo-frame&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To differ loading we add a &lt;code&gt;src&lt;/code&gt; attribute to the &lt;code&gt;turbo-frame&lt;/code&gt; element. The HTML response from the URL value will be used to automatically load content into the matching frame &lt;code&gt;id&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Are Turbo Frames like iframes then?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;They sound like iframes but no Turbo frames are part of the same DOM, styled by the same CSS, and part of the same JavaScript context. So they don't suffer the weirdness associated with iframes.&lt;/p&gt;

&lt;p&gt;Other advantages of Turbo Frames:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Efficient caching - each segment is cached independently, so you get longer-lived caches with fewer dependent keys.&lt;/li&gt;
&lt;li&gt;Parallelized execution - each defer-loaded frame is generated by its own HTTP request/response and handled by a separate process. So different segments on a page load in parallel without having to manage the process.&lt;/li&gt;
&lt;li&gt;Ready for mobile - Each segment can appear in native sheets and screens without alteration, since they all have independent URLs.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Turbo Streams: Deliver Live Page Changes
&lt;/h2&gt;

&lt;p&gt;While Turbo Frames give us partial page updates in response to direct interactions within a single frame (link clicks, form submits), Turbo Streams let us change any part of the page in response to updates from a WebSocket connection (or SSE).&lt;/p&gt;

&lt;p&gt;[aside] Streams is a conceptual continuation of what was first called RJS and then SJR.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The big idea around &lt;a href="https://rubyonrails.org/2006/3/28/rails-1-1-rjs-active-record-respond_to-integration-tests-and-500-other-things"&gt;RJS&lt;/a&gt;, JavaScript written in Ruby, from that 2006 post announcing Rails 1.1 is that you don't have to write JavaScript to Ajaxify things in Rails, you can write Ruby. (So yeah, we are still after the same thing!).&lt;/li&gt;
&lt;li&gt;The idea behind Server-generated Javascript Response &lt;a href="https://signalvnoise.com/posts/3697-server-generated-javascript-responses"&gt;SJR&lt;/a&gt; from this post from 2013 is pretty reminiscent of what we have with Turbo. The flow is something like this - a form is submitted via AJAX request, server generates a JavaScript response that includes an updated HTML template, client evaluates the JavaScript returned by the server, which then updates the DOM. We can see how Streams is a conceptual continuation of this flow with eliminating more JavaScript. RJS was a poor man's CoffeeScript and it turned people away from the concept of server-generated JavaScript, but in 2013 rails re-committed to SJR while leaving behind RJS. The last sentence of that 2013 post says:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;"The combination of Russian Doll-caching, Turbolinks, and SJR is an incredibly powerful cocktail for making fast, modern, and beautifully coded web applications. Enjoy!"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Unlike RJS and SJR it's not possible to send custom JavaScript as part of Turbo Stream actions, by design! Turbo focuses on sending HTML and updating the DOM and then if needed we can connect additional behavior using Stimulus actions and lifecycle callbacks.&lt;/p&gt;

&lt;h3&gt;
  
  
  How It Works?
&lt;/h3&gt;

&lt;p&gt;Turbo Streams introduces a &lt;code&gt;&amp;lt;turbo-stream&amp;gt;&lt;/code&gt; element with an &lt;code&gt;action&lt;/code&gt; and a &lt;code&gt;target&lt;/code&gt; attribute. The actions could be append, prepend, replace, update, remove, before, after. We include the HTML to insert or replace in a &lt;code&gt;template&lt;/code&gt; tag and Turbo does the rest.&lt;/p&gt;

&lt;p&gt;[aside] &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template"&gt;HTML template tag&lt;/a&gt; is a way for holding HTML that is not to be rendered immediately when a page is loaded but may be added to the page later using JavaScript.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages of Turbo Streams
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Reuse server-side templates - same templates that created the first-load page are used to generate live page updates (in practice some CSS is needed to show/hide certain elements in the two cases).&lt;/li&gt;
&lt;li&gt;HTML over the wire - don't need any client-side JavaScript (other than Turbo.js) and save all the effort it takes to fetch JSON and turn it into HTML.&lt;/li&gt;
&lt;li&gt;Simpler control flow - clear to follow what happens in response to WebSocket or SSE by looking at the HTML to be changed. No indirection with client-side routing, event bubbling and such.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Turbo Native: Hybrid apps for iOS and Android
&lt;/h2&gt;

&lt;p&gt;I am not a mobile developer. But here are some points I took away from reading about Turbo Native.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ideal for building hybrid apps where server-rendered HTML can be used to get baseline coverage of your app's functionality in a native wrapper. Along with a few native screens that can really benefit from the high fidelity.&lt;/li&gt;
&lt;li&gt;Going hybrid allows you the freedom to upgrade your app without going through the slow app store release process. Anything done in HTML can be changed in your web application and be instantly available to users.&lt;/li&gt;
&lt;li&gt;Turbo Native is not a framework that abstracts native APIs. It also does not try to create native code that's sharable across platforms. (In other words, you still need native devs for iOS and Android, but those devs just have less work do). The part that's sharable is the HTML that's rendered server-side.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;So that covers the main concepts around Turbo Drive, Turbo Frames and Turbo Streams. Let's learn about some nuances to keep in mind when building applications with Turbo.&lt;/p&gt;

&lt;p&gt;Also by the way, while Turbo is not Rails specific, &lt;a href="https://github.com/hotwired/turbo-rails"&gt;turbo-rails gem&lt;/a&gt; is the reference implementation of Turbo for Ruby on Rails. The Turbo documentation says you don't need a backend framework to use Turbo. (I don't quite get that tbh, doens't the backend need to return HTML with the appropriate elements &lt;code&gt;&amp;lt;turbo-stream&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;turbo-frame&amp;gt;&lt;/code&gt; along with the correct &lt;code&gt;ids&lt;/code&gt; to replace the right things on the page.) &lt;/p&gt;




&lt;h2&gt;
  
  
  Constraints and Nuances of Building Turbo Applications
&lt;/h2&gt;

&lt;p&gt;Since there is no full page load, the JavaScript &lt;code&gt;window&lt;/code&gt; and &lt;code&gt;document&lt;/code&gt; objects retain their sate across page changes (any other objects we leave in memory will stay in memory). We can't rely of full-page reload to reset our environment, our application is a persistent, long-running process in the browser. Below are things we need to be aware of to design our application to gracefully handle this constraint:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Script Elements
&lt;/h3&gt;

&lt;p&gt;When navigating with Turbo, &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; elements in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; are okay, Turbo Drive appends them to the current &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; and the browser loads and evaluates them. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; elements in the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; are not good. To install behavior, or to perform more complex operations when the page changes, avoid script elements and use the &lt;code&gt;turbo:load&lt;/code&gt; event instead.&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; elements we don't want Turbo to evaluate after rendering, annotate them with &lt;code&gt;data-turbo-eval="false"&lt;/code&gt;. The browser will still evaluate those scripts on the initial page load.&lt;/p&gt;

&lt;p&gt;For loading our application's JavaScript bundle, do this in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; tag always. Also if we add a fingerprint to each script and &lt;code&gt;data-turbo-track="reload"&lt;/code&gt; attribute, Turbo can force a full page reload when we deploy a new JavaScript bundle.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Caching
&lt;/h3&gt;

&lt;p&gt;Let's define some terms like Restoration visits and Application visits first.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Restoration visits are when you navigate with the Browser's back or forward button. Turbo Drive renders a copy of the page from the cache if possible. (Drive also saves the scroll position of each page before navigating away and automatically returns to this saved position. nice)&lt;/li&gt;
&lt;li&gt;Application visits are the onces initiated by clicking a Turbo Drive-enabled link or programmatically calling &lt;code&gt;Turbo.visit(location)&lt;/code&gt;. Always issues a network request. These result in a change to browser's history, Turbo Drives pushes a new entry onto the browser's history stack using &lt;code&gt;history.pushState&lt;/code&gt;. &lt;code&gt;data-turbo-action&lt;/code&gt; is the attribute to decide what type of visit it is, default is &lt;code&gt;advance&lt;/code&gt;, it could also be &lt;code&gt;replace&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;When Turbo Drive saves a copy of the current page to cache, it uses &lt;code&gt;cloneNode(true)&lt;/code&gt;, which apparently means attached event listeners and data are discarded. (&lt;code&gt;cloneNode&lt;/code&gt; clones the DOM node)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Preparing the Page to be cached&lt;/strong&gt; - we can listen to the &lt;code&gt;turbo:before-cache&lt;/code&gt; event with &lt;code&gt;document.addEventListener&lt;/code&gt; if we need to do things to the document before Turbo caches it. For example, reset forms, collapse UI elements, etc. so the page is ready to be displayed again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Detecting when a preview is visible&lt;/strong&gt; - Turbo Drive adds a &lt;code&gt;data-turbo-preview&lt;/code&gt; attribute to the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; element when it displays a page from cache. We can check for the presence of this if we want to enable/disable behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Opting out of caching&lt;/strong&gt; - We can control caching behavior on a per-page basis by including a &lt;code&gt;meta&lt;/code&gt; element in the page's &lt;code&gt;head&lt;/code&gt;. Like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  ...
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"turbo-cache-control"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"no-cache"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Installing JavaScript Behavior
&lt;/h3&gt;

&lt;p&gt;Since the usual &lt;code&gt;window.onload&lt;/code&gt;, &lt;code&gt;DOMContentLoadeded&lt;/code&gt;, or JQuery &lt;code&gt;ready&lt;/code&gt; events will only fire after initial page load, we need a strategy for installing JavaScript behavior on Turbo page loads. There are two options:&lt;/p&gt;

&lt;h4&gt;
  
  
  Observing Navigation Events
&lt;/h4&gt;

&lt;p&gt;There is an event, &lt;code&gt;turbo:load&lt;/code&gt; that fires after the initial page load and again after every Turbo Drive visit. We can use this like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;document.addEventListener("turbo:load", function() {
  // ...
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;avoid using &lt;code&gt;turbo:load&lt;/code&gt; event to add other event listeners directly to elements on the page body. Instead use &lt;a href="https://learn.jquery.com/events/event-delegation/"&gt;event delegation&lt;/a&gt; to register event listeners once on &lt;code&gt;document&lt;/code&gt; or &lt;code&gt;window&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Attaching Behavior with Stimulus
&lt;/h4&gt;

&lt;p&gt;New DOM elements can appear on the page at any time from frame navigation, stream messages, client-side rendering, or Turbo Drive page loads. Stimulus with its lifecycle callbacks and conventions can handle all of these in a single place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How Stimulus Works&lt;/strong&gt; - it connects and disconnects its controller and event handlers whenever the document changes using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver"&gt;MutationObserver API&lt;/a&gt;. This allows it to handle all types of DOM updates.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Making Transformations Idempotent
&lt;/h3&gt;

&lt;p&gt;The context here is performing client-side transformations to HTML received from the server. The example we can imagine is grouping a collection of elements by date using browser's knowledge of current time zone. &lt;/p&gt;

&lt;p&gt;[aside] Making something, a function, idempotent means that regardless of how many times we apply the function to a given input the result will be the same as applying it just once. Meaning there are no more changes beyond its initial application.&lt;/p&gt;

&lt;p&gt;We have to think about this because of caching. "Consider what happens if you’ve configured this function to run on turbo:load. When you navigate to the page, your function inserts date headers. Navigate away, and Turbo Drive saves a copy of the transformed page to its cache. Now press the Back button—Turbo Drive restores the page, fires turbo:load again, and your function inserts a second set of date headers."&lt;/p&gt;

&lt;p&gt;We can solve this by detecting if the transformation is already present on the HTML before adding it. In this we'd check for the presence of a date divider. (We can also add a flag via &lt;code&gt;data&lt;/code&gt; attribute but that's less robust)&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Persisting Elements Across Page Loads
&lt;/h3&gt;

&lt;p&gt;The context here is that we may not want certain elements to change across page loads. Turbo Drive allows us to mark them &lt;em&gt;permanent&lt;/em&gt;. The example we can imagine is a shopping cart icon with a counter. We don't want the counter to change to a previous/lower number if the user navigates with a back button after adding an item to the cart on the current page.&lt;/p&gt;

&lt;p&gt;We do this by marking the counter element permanent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"cart-counter"&lt;/span&gt; &lt;span class="na"&gt;data-turbo-permanent&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;1 item&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The HTML id is needed as Turbo Drive matches all permanent element by ID before rendering, and transfers them from the original page to the new page. Preserving data and event listeners.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;That's all, that covers most of the concepts for understanding Turbo and Hotwire. It's all about updating things on the page in a way that feels fast and smooth to the user, without needing to write a lot of client-side Javascript.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTML-over-the-wire or Hotwire&lt;/strong&gt; is a concept, not a specific technology. The main idea is to send server-rendered HTML to the client, instead of JSON, leaving application logic to the server. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Turbo&lt;/strong&gt; is the technology that implements Hotwire in the Rails world. And other backend stacks have their own version of Turbo. Turbo consists of Drive, Frames, and Streams. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Turbo Drive&lt;/strong&gt; is an evolution of Turbolinks. When enabled, it intercepts link clicks and form submission, maintains a persistent process that leaves &lt;code&gt;window&lt;/code&gt; and &lt;code&gt;document&lt;/code&gt; unchanged, but replaces the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; element of the response. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Turbo Frames&lt;/strong&gt; allow different sections of the page to be lazily loaded and elements on the page to be automatically scoped by using &lt;code&gt;&amp;lt;turbo-frame&amp;gt;&lt;/code&gt; element so that a response updates only the frame with a matching &lt;code&gt;id&lt;/code&gt;, leaving rest of the page untouched. Turbo Frames are similar to &lt;code&gt;iframes&lt;/code&gt; but different, in that they're part of the same DOM, styled by the same CSS, and part of the same JavaScript context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Turbo Streams&lt;/strong&gt; take things even further. They allow for partial page updates from not only user interactions (like form submission) but also in response to websocket and SSE. &lt;code&gt;&amp;lt;turbo-stream&amp;gt;&lt;/code&gt; elements support automatically changing the HTML of a target element by various operations like replace, append, prepend, remove, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When building applications with Turbo&lt;/strong&gt; we have to keep in mind that our application is a persistent, long-running process in the browser. We can't rely of full-page reload to reset our environment and have to approach a few things with care, like caching, script element, and installing JavaScript behavior, etc.&lt;/p&gt;

&lt;p&gt;Finally, it's worth noting that Hotwire and Turbo approach is not suitable for &lt;em&gt;all&lt;/em&gt; web applications. Sometimes the complexity of client-side rendering with a JavaScript SPA is needed for a high-fidelity user experience of text editor, for example. (such as the Trix editor from the Rails community). And yet, for many modern web applications it would be worthwhile to reach for Hotwire/Turbo for the conceptual compression of complexity offered.&lt;/p&gt;




&lt;p&gt;If you made it all the way to the end, good job! 💜 Hope you learned something! &lt;/p&gt;

&lt;p&gt;The above is a conceptual post around Hotwire and Turbo, meant for the job of wrapping our heads around what the big ideas are in the Hotwire approach. Check back for the accompanying 'code' post where we'll build an application using streams and frames and share the code step-by-step.&lt;/p&gt;

</description>
      <category>rails</category>
      <category>javascript</category>
      <category>hotwire</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Make Learning Programming Effective and Enjoyable</title>
      <dc:creator>Bhumi</dc:creator>
      <pubDate>Mon, 30 Nov 2020 03:50:33 +0000</pubDate>
      <link>https://dev.to/bhumi/how-to-make-learning-programming-effective-and-enjoyable-2kjc</link>
      <guid>https://dev.to/bhumi/how-to-make-learning-programming-effective-and-enjoyable-2kjc</guid>
      <description>&lt;p&gt;When you start to learn to code, you typically start with learning a programming language. You learn about variables, functions, statement, loops, control-flow, etc. You may follow tutorials, typing things into a browser or a code editor and learning syntax and how to make the code run and do something. You may watch online courses, videos, etc. And at least some of the times things seem to work out as advertised and you feel awesome for making the computer do things (controlling it with your mind).&lt;/p&gt;

&lt;p&gt;Then you decide to work on your own projects to implement your ideas or to build a 'portfolio' to demonstrate what you know. When you start with a blank (IDE) screen you may feel like you don't know where to start. And this is true for new programmers but also to experienced programmers learning a new tech.&lt;/p&gt;

&lt;p&gt;Here's a problem. We often confound two different types of learning - tactical learning and conceptual learning. We often jump straight to the tactical learning and forget to ask questions like 'why' and some of the tech tutorials fail to offer context, bigger picture before diving into the 'how'&lt;/p&gt;

&lt;h3&gt;
  
  
  How To Separate Tactical and Conceptual Learning
&lt;/h3&gt;

&lt;p&gt;Programming consists of two types of learning that need to happen in parallel for it to be effective and enjoyable — tactical and conceptual.&lt;/p&gt;

&lt;p&gt;Tactical learning is about the syntax, about what to type, where to type, and how to get the code to do something. &lt;/p&gt;

&lt;p&gt;Conceptual learning is about what the Things are, how they’re connected, why things are the way they are, and most importantly, how everything fits together. This book is about conceptual learning.&lt;/p&gt;

&lt;p&gt;When learning a new tech, seek out conceptual resources that provide context and explain things like - what are good use cases, what is not a good use case, how this tech fits into the existing model.&lt;/p&gt;

&lt;p&gt;Do both tactical learning and conceptual learning in parallel. Interleaving the two until you're making progress making things happen on screen but also connecting the dots in your mind. One way to test your conceptual learning is pose and answer basic questions to yourself or better explain the concepts to someone else, in plain language (without jargon). If you can do that, there is a good chance you've actually understood.&lt;/p&gt;

&lt;p&gt;What do you think? How do you approach conceptual learning.&lt;/p&gt;




&lt;p&gt;P.S. If you want to read about API, MVC, OOP, SQL, JSON, DOM, and other web programming terms in a conceptual way, I wrote 16 chapters and bundled into a nice PDF (You can get it here &lt;a href="https://connectthedots.dev/"&gt;connect the dots&lt;/a&gt; and start reading for free). I've been mentoring programmers and I wrote this based on common questions from students.&lt;/p&gt;

&lt;p&gt;I'm also learning something. Promoting and marketing my work, which is completely new to me as a developer. This quote (from Seth Godin) helped me with my mindset:&lt;/p&gt;

&lt;p&gt;"A good idea isn’t worth much if it doesn’t reach people who can benefit from it"&lt;/p&gt;

&lt;p&gt;This is my attempt to reach the people that can benefit.&lt;/p&gt;




&lt;p&gt;P.P.S. If you're in a country where stripe doesn't work or dollar value is different, send me an email with the subject "I want the book" and I'll take care of it, no explanation needed (my email is in the footer of the &lt;a href="https://connectthedots.dev/"&gt;page&lt;/a&gt;)&lt;/p&gt;

</description>
      <category>programming</category>
      <category>codenewbie</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Developer Dictionary: API</title>
      <dc:creator>Bhumi</dc:creator>
      <pubDate>Fri, 25 Sep 2020 19:16:18 +0000</pubDate>
      <link>https://dev.to/bhumi/developer-dictionary-api-2b5c</link>
      <guid>https://dev.to/bhumi/developer-dictionary-api-2b5c</guid>
      <description>&lt;p&gt;This is the first paragraph for the API page on Wikipedia. I love Wikipedia but this is not what I'd want to read:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An application programming interface (API)  is a computing interface which defines interactions between multiple software intermediaries. It  defines the kinds of calls or requests that can be made, how to make  them, the data formats that should be used, the conventions to follow,  etc. It can also provide extension mechanisms so that users can extend  existing functionality in various ways and to varying degrees.[1] An API can be entirely custom, specific to a component, or it can be  designed based on an industry-standard to ensure interoperability.  Through information hiding, APIs enable modular programming, which allows users to use the interface independently of the implementation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This description is correct and precise of course but also meaningless to someone trying to quickly get a sense of the Thing called API.&lt;/p&gt;

&lt;p&gt;Knowing what the acronym stands for is also not very meaningful. You may know the words application, programming, and even interface individually but putting them together doesn't lead to an immediate 'ah I see what it is now'.&lt;br&gt;
So what is an API? Imagine a function. When you call a function in any programming language, you have some input parameters and you have an expected output value. For example if we have a function called sum we may pass in two numbers as input and expect to receive the mathematical sum of those to numbers as the output response.&lt;/p&gt;

&lt;p&gt;Calling an API works similarly. You pass in some parameters as the input and expect to receive some output.  The difference between APIs and the function call analogy is that calling an API happens over the Internet. And the response usually contains data that is stored and maintained by the owner of the API.&lt;/p&gt;

&lt;p&gt;It's a way of making a precise request to a server. Instead of requesting a webpage (HTML) we're requesting specific data (aka resource). &lt;a href="https://bhumimakes.com/api/"&gt;keep reading&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>computerscience</category>
      <category>codenewbie</category>
      <category>firstyearincode</category>
    </item>
    <item>
      <title>Developer Dictionary: HTTP and TCP/IP</title>
      <dc:creator>Bhumi</dc:creator>
      <pubDate>Wed, 23 Sep 2020 19:31:21 +0000</pubDate>
      <link>https://dev.to/bhumi/developer-dictionary-http-and-tcp-ip-l3d</link>
      <guid>https://dev.to/bhumi/developer-dictionary-http-and-tcp-ip-l3d</guid>
      <description>&lt;p&gt;Where to Begin! There is a lot to say about this Thing named HTTP. It's a protocol, the Hyper Text Transfer Protocol, but you already know what the acronym spells. It's the way for computers to communicate with each other over the Internet. It's part of this other Thing called TCP/IP Stack. It's how you're reading what I typed many computers away — many hops of network cards, Ethernet cables, routers and switches away. Each of these machines along the way contain some component that implements HTTP as well as  other 'layers' of the TCP/IP stack? What does it mean to implement HTTP?&lt;/p&gt;

&lt;p&gt;HTTP is a specification. Or in plain English, a document listing out bunch of rules that two or more parties follow in order to play well together and be able to communicate with each other. Computers that want to communicate over The — capital I — Internet have hardware and software that follow these rules. (Side note: But we can also imagine a separate network of computer that choose to communicate in a totally different way using different set of protocols.) &lt;/p&gt;

&lt;p&gt;So far this is a bit abstract. An analogy, coming up! First, we need to look at this TCP/IP stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  TCP/IP Stack
&lt;/h2&gt;

&lt;p&gt;Let's look at HTTP in the context of this Thing called the TCP/IP Stack. It is a stack in that it has layers and each layer has some specific role to play in getting a message from computer A to computer B. &lt;a href="https://connectthedots.dev/http-tcp-ip/"&gt;keep reading&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>computerscience</category>
      <category>codenewbie</category>
      <category>firstyearincode</category>
    </item>
    <item>
      <title>Developer Dictionary: CLI Command Line Interface</title>
      <dc:creator>Bhumi</dc:creator>
      <pubDate>Fri, 18 Sep 2020 19:29:51 +0000</pubDate>
      <link>https://dev.to/bhumi/developer-dictionary-cli-command-line-interface-1bof</link>
      <guid>https://dev.to/bhumi/developer-dictionary-cli-command-line-interface-1bof</guid>
      <description>&lt;p&gt;&lt;strong&gt;This post is part of a resource called Developer Dictionary. More about why I'm writing this &lt;a href="https://connectthedots.dev/developer-dictionary/"&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  What is it
&lt;/h3&gt;

&lt;p&gt;A way for users to interact with the computer directly (i.e. with operating system and computer hardware). Each command is a small software program that takes some input from the user, does some work, and returns some output to the user. The input and output is text — typed or displayed in a terminal window. These small programs (aka commands) are intended to be combined with other commands to accomplish some higher level task or a user's goal. Meaning they are composable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why CLI
&lt;/h3&gt;

&lt;p&gt;Mouse pointer, touchscreen, LCD screen, Windows, Icons — these things that we take for granted took decades of research to bring about. Computing didn't start off with graphical user interfaces (GUIs). Before touchscreens and mouse pointers, computing was about typing text and reading text.&lt;/p&gt;

&lt;p&gt;So now that we have GUIs why do programmers still use the command line? You may be wondering are there things we can do with the CLI that we can't do with a GUI? Yes. Or rather there are things that are much more convenient to do with command line because it offer more control and it's more expressive. For example let's say we want to: &lt;/p&gt;

&lt;p&gt;-- Performing some repetitive tasks on a schedule? Like delete older photos once week.&lt;/p&gt;

&lt;p&gt;-- Running a program automatically when you start your computer.&lt;/p&gt;

&lt;p&gt;-- Find some text in a bunch of files and or rename a bunch of files at the same time.&lt;br&gt;
All the above can be accomplished nicely with a command line programs (aka scripts) like  cron, sed, awk, launchd ,launchctl, etc.&lt;/p&gt;

&lt;p&gt;There are many tutorials and cheatsheets on the Internet with details on the above and many other commands — what they do, how to use them, etc. We're not going to focus on that. Let's talk about some concepts that are common to all commands and are useful for understanding the 'big picture' around interacting with a computer using a Command Line Interface.&lt;/p&gt;

&lt;h3&gt;
  
  
  Big Picture Concepts
&lt;/h3&gt;

&lt;p&gt;If text scrolling on a command line looks like gibberish to you well that's it is a different language. One that can be learned and used effectively. Here we explore some common terms and concepts and make things less mysterious.&lt;a href="https://connectthedots.dev/cli/"&gt;keep reading&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>computerscience</category>
      <category>codenewbie</category>
      <category>firstyearincode</category>
    </item>
    <item>
      <title>Developer Dictionary: Data Structures</title>
      <dc:creator>Bhumi</dc:creator>
      <pubDate>Thu, 17 Sep 2020 18:26:34 +0000</pubDate>
      <link>https://dev.to/bhumi/developer-dictionary-data-structures-1j84</link>
      <guid>https://dev.to/bhumi/developer-dictionary-data-structures-1j84</guid>
      <description>&lt;p&gt;&lt;strong&gt;This post is part of a resource called Developer Dictionary. More about why I'm writing this &lt;a href="https://connectthedots.dev/developer-dictionary/"&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you go to the grocery store, do you make a list of things you need to buy? If it's a physical list on a piece of paper, likely you use that during the trip, mentally check off the items and then recycle the paper once you're done. The list serves as temporary storage of items from our working memory. A data structure serves a similar purpose for a program.&lt;/p&gt;

&lt;p&gt;Imagine you're writing a program to keep track of books you've read. You'll eventually need to make a list. Maybe you'll want to go through the list and rate each book. For this you would store the book titles in the computer's working memory for the duration of your program (temporary storage).&lt;/p&gt;

&lt;p&gt;Each value stored in a computer's memory has an address so that the operating system can find it later. It has a name as well – a variable name given by our program – so that our program can refer to its value. It looks something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x9RJyAfm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/viep98c7bravfwphbm1q.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x9RJyAfm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/viep98c7bravfwphbm1q.jpg" alt="Alt Text" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So &lt;code&gt;0x0001&lt;/code&gt; is the address for the operating system. Within our program, instead of &lt;code&gt;0x0001&lt;/code&gt; we can use &lt;code&gt;book_one&lt;/code&gt; as the name. But typing &lt;code&gt;book_one&lt;/code&gt;, &lt;code&gt;book_two&lt;/code&gt; feels a bit clunky right. And if we can imagine that we're using a continuous block of addresses, could we just use one variable name but have a way to refer to the entire book list? Yes, that is called an array in most programming languages. If we created an array named books, we could refer to each book with &lt;code&gt;book[1]&lt;/code&gt;, &lt;code&gt;book[2]&lt;/code&gt;, &lt;code&gt;book[10]&lt;/code&gt;, etc. That's all there is to it. An array is one type of data structure. Data structures are a shorthand for referring to memory addresses on the computer.&lt;/p&gt;

&lt;p&gt;In addition to being a convenient shorthand, most data structures also support useful operations for adding items, finding an item, removing an item, and going through the entire collection of items &lt;a href="https://connectthedots.dev/data-structures/"&gt;Keep reading&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>computerscience</category>
      <category>codenewbie</category>
      <category>firstyearincode</category>
    </item>
    <item>
      <title>Developer Dictionary: Operating System</title>
      <dc:creator>Bhumi</dc:creator>
      <pubDate>Wed, 16 Sep 2020 12:14:39 +0000</pubDate>
      <link>https://dev.to/bhumi/developer-dictionary-operating-system-5e0a</link>
      <guid>https://dev.to/bhumi/developer-dictionary-operating-system-5e0a</guid>
      <description>&lt;p&gt;&lt;strong&gt;This post is part of a resource called Developer Dictionary. More about why I'm writing this &lt;a href="https://connectthedots.dev/developer-dictionary/"&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Familiarity – even if it implies no real understanding at all – can dull the sense of mystery. Educators who wish to cultivate the sense of  wonder therefore face the challenge, as the education philosopher Kieran Egan noted, of defamiliarising the familiar.*&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;You may be thinking "operating system? I already know what that is!" And yes, you know about Mac and Windows. You may even recall those goofy commercials where two actors are playing the role of an operating system. You've probably debated the virtues of iOS vs. Android with family members and questioned their smartphone of choice? So you already have an idea of what an operating system is. But why do we need this Thing? What is inside this mysterious box? What does it do?&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Operating System?
&lt;/h2&gt;

&lt;p&gt;We have computer hardware and we have applications that run on that hardware. If we got a computer without any software on it — just the processor and memory — we wouldn't be able to do much with it. Even if it had keyboard and mouse for user input, when we press those keys nothing would happened. We would see nothing on the screen. We need some software installed that knows how to talk to the hardware, as well as how to interpret use inputs and provide users with output.&lt;br&gt;
Even if we're talking about a server, that does not interact with users directly, we still need some software to manage its various tasks and manage the memory allocated to different type of work.&lt;/p&gt;

&lt;h3&gt;
  
  
  In Search of an Analogy
&lt;/h3&gt;

&lt;p&gt;What's a good analogy for an Operating System(OS)? I was thinking of air traffic control maybe. The job of an air traffic controller is to direct airplanes in certain airspace – those taking off, those in flight, and those landing — so that no one crashes into anything. This is a difficult job but also very specific and well defined. So nah, too easy. &lt;br&gt;
What about an analogy with the human brain - our brain processes various inputs and generates various outputs. Some of the inputs for consideration might be:&lt;br&gt;&lt;br&gt;
"I'm hungry", &lt;br&gt;
"I need to use the restroom",&lt;br&gt;
"I hear a loud noise in the other room", &lt;br&gt;
"I have a meeting in 30 minutes, better type faster and finish this writing".&lt;/p&gt;

&lt;p&gt;Similarly on a computer, something needs to process all these actions:&lt;/p&gt;

&lt;p&gt;"User just opened another browser tab, need to allocate some more memory",&lt;br&gt;
 "Someone inserted headphones, need to redirect audio output to headphone jack from the speakers", &lt;br&gt;
"Someone is rapidly smacking keyboard keys, better send the correct electric currents to the liquid crystal display (LCD) of the monitor screen. So those letters display on screen and the user can see what they're typing."&lt;br&gt;
"Just launched a zoom meeting need to stream video, audio, process network I/O, schedule this program on the processor with appropriate priority".&lt;/p&gt;

&lt;p&gt;And many more. This is what an OS is 'thinking' about constantly. Let's take a look at some of the components of an OS. &lt;a href="https://connectthedots.dev/os/"&gt;Keep Reading&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>computerscience</category>
      <category>codenewbie</category>
      <category>firstyearincode</category>
    </item>
    <item>
      <title>Developer Dictionary: Client Server Pattern</title>
      <dc:creator>Bhumi</dc:creator>
      <pubDate>Fri, 11 Sep 2020 18:36:27 +0000</pubDate>
      <link>https://dev.to/bhumi/developer-dictionary-client-server-pattern-k9h</link>
      <guid>https://dev.to/bhumi/developer-dictionary-client-server-pattern-k9h</guid>
      <description>&lt;p&gt;This post is part of a resource called Developer Dictionary. More about why I'm writing this &lt;a href="https://connectthedots.dev/developer-dictionary/"&gt;here&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Client, server, frontend, backend, fullstack, request, response, website, web application — all of these terms are used very frequently in the world of web development. And if you're been learning programming for the web, even few weeks, you've probably been exposed to these terms. Here I illustrate what these words mean so you have a clear picture of the concepts behind the words and how they relate to the structure of the web.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is the Client Server Pattern?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can think of a server as a computer that holds data related to our website and code that reads/writes that data. A client is another computer that has a browser — a program capable of running code on behalf of the user (usually Javascript code) and making requests to the server. Server awaits and responds to client requests. One server serves many clients.&lt;/p&gt;

&lt;p&gt;The same client could communicate with multiple servers. And the same computer can act both a s client and as a server. These are roles played with the computer based on the context. For example, when you're programming locally and you run a server on your computer and your browswer acts as the client (If you're ever typed localhost in your broswer you know what I mean).  &lt;a href="https://connectthedots.dev/client-server/"&gt;Continue Reading&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>computerscience</category>
      <category>codenewbie</category>
      <category>firstyearincode</category>
    </item>
    <item>
      <title>Developer Dictionary: The Story of Git</title>
      <dc:creator>Bhumi</dc:creator>
      <pubDate>Thu, 10 Sep 2020 16:18:38 +0000</pubDate>
      <link>https://dev.to/bhumi/developer-dictionary-the-story-of-git-36oo</link>
      <guid>https://dev.to/bhumi/developer-dictionary-the-story-of-git-36oo</guid>
      <description>&lt;h4&gt;
  
  
  This post is part of a resource called Developer Dictionary. More about why I'm writing this &lt;a href="https://bhumimakes.com/developer-dictionary/"&gt;here&lt;/a&gt;
&lt;/h4&gt;




&lt;p&gt;There are many tutorials, videos, books, and blog posts about the internal workings of Git. This writing is more of a story of Git — what it is, why it exists, and how it came to be. &lt;/p&gt;

&lt;h3&gt;
  
  
  Why Do We Need Git?
&lt;/h3&gt;

&lt;p&gt;Git is an open source distributed version control system. What does that mean? and what is it good for?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Version Control:&lt;/strong&gt; Imagine you were editing a document or a spreadsheet with your friends or family members. You're planning a trip and everyone is adding different locations. You'd want to combine (aka merge) everyone's changes and have it all available in the final document right? And you'd want to be able to make these changes at the same time without stepping on each other's toes ideally. It would be to see what the document looked like last week and go back to that older version in case someone messed up something.  It would also be nice to see who changed what and when.&lt;/p&gt;

&lt;p&gt;A version control system allows for all of the above functionality. Git is one such version control system. We talk about Git in the context of tracking code but it can track any collection of files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Distributed:&lt;/strong&gt; This means that each peson has their own copy of the code on their local machine. There is no central server that keeps a master copy of the code. (This distinction is relevant to those familiar with other version control systems prior to Git. Many were centralized and had one master copy of the code).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open Source:&lt;/strong&gt; This means that the source code for the tool Git is not proprietary. You can see the code for Git here.&lt;br&gt;
A Taste of Git – Sample Workflow &lt;br&gt;
There is an abundance of terminology related to Git. There are precise definitions and detailed descriptions of each of the term I use below, elsewhere. My goal is to paint a picture for you using broad brushstrokes before you get lost in the details. &lt;/p&gt;

&lt;h3&gt;
  
  
  A Taste of Git – Sample Workflow
&lt;/h3&gt;

&lt;p&gt;There is an abundance of terminology related to Git. There are precise definitions and detailed descriptions of each of the term I use below, elsewhere. My goal is to paint a picture for you using broad brushstrokes before you get lost in the details.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bhumimakes.com/git/"&gt;Continue reading&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>codenewbie</category>
      <category>firstyearincode</category>
      <category>computerscience</category>
    </item>
  </channel>
</rss>
