<?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: Mahmoud Sultan</title>
    <description>The latest articles on DEV Community by Mahmoud Sultan (@mahmoudsultan36).</description>
    <link>https://dev.to/mahmoudsultan36</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%2F224366%2F0b6e035f-a89f-4ac0-84c1-c2b2b86ef98c.jpg</url>
      <title>DEV Community: Mahmoud Sultan</title>
      <link>https://dev.to/mahmoudsultan36</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mahmoudsultan36"/>
    <language>en</language>
    <item>
      <title>Patching Searchkich Gem To Add Custom Queries By Default</title>
      <dc:creator>Mahmoud Sultan</dc:creator>
      <pubDate>Tue, 21 Jan 2020 18:42:31 +0000</pubDate>
      <link>https://dev.to/mahmoudsultan36/patching-searchkich-gem-to-add-custom-queries-by-default-21m0</link>
      <guid>https://dev.to/mahmoudsultan36/patching-searchkich-gem-to-add-custom-queries-by-default-21m0</guid>
      <description>&lt;h1&gt;
  
  
  Context
&lt;/h1&gt;

&lt;p&gt;So a bit of context, as I'm working on Triplancer.net which is a Multi-Tenant Project developed by Ionite I needed to scope results returning for any Searchkick Query by the Current Tenant Id not to return results from other tenants.&lt;/p&gt;

&lt;p&gt;You can do that simply by using a where query something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;where: { tenant_id: current_tenant_id }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I did not want, however, to have to write this on every query I write, I wanted a way to override search method for models that are tenant-scoped, and add that tiny query by default to whatever Searchkick queries are made on that model.&lt;/p&gt;

&lt;p&gt;Luckily, overriding stuff is fairly easy in Ruby, I just needed to look for where exactly should I inject my code.&lt;/p&gt;

&lt;h1&gt;
  
  
  SearchKick search() method
&lt;/h1&gt;

&lt;p&gt;Looking at the Searchkick codebase for the source code of the method &lt;code&gt;searchkick&lt;/code&gt; - that used to initialize searching inside a model - here: &lt;a href="https://github.com/ankane/searchkick/blob/master/lib/searchkick/model.rb"&gt;https://github.com/ankane/searchkick/blob/master/lib/searchkick/model.rb&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find that, on line 43, Searchkick inserts a method called &lt;code&gt;searchkick_search&lt;/code&gt; to the model eigenclass and conveniently to us alias this method with &lt;code&gt;Searchkick.search_method_name&lt;/code&gt; which you can change but is set by default to &lt;code&gt;search&lt;/code&gt; here: &lt;a href="https://github.com/ankane/searchkick/blob/d10ffd4fd97003b638cb93821dcab3c86a2abba5/lib/searchkick.rb#L42"&gt;https://github.com/ankane/searchkick/blob/d10ffd4fd97003b638cb93821dcab3c86a2abba5/lib/searchkick.rb#L42&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That makes our job very easy, all we need to do is follow the same convention and define a method, let's call it &lt;code&gt;scope_searchkick&lt;/code&gt;, that has the same signature and currys the searchkick_search method with the scoping query.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scope_searchkick&lt;/span&gt;
    &lt;span class="nb"&gt;class_eval&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;
        &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;term&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'*'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:where&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;key?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:where&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="n"&gt;options_with_tenant_scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:where&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;tenant_id: &lt;/span&gt;&lt;span class="n"&gt;current_tenant_id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;)&lt;/span&gt;

          &lt;span class="n"&gt;searchkick_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options_with_tenant_scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, all we need to do is call this method after the &lt;code&gt;searchkick&lt;/code&gt; method in our models.&lt;/p&gt;

&lt;p&gt;I've defined this method in the ApplicationRecord class so that it'd be available in every model to call but you can define it anywhere you see suitable.&lt;/p&gt;

&lt;p&gt;One last edit: Let's make it defensive and define it in a way that if we change &lt;code&gt;Searchkick.search_method_name&lt;/code&gt; our patch would still work.&lt;/p&gt;

&lt;p&gt;How to do that?, we can simply use &lt;code&gt;define_method&lt;/code&gt; instead of &lt;code&gt;def&lt;/code&gt; and pass the &lt;code&gt;Searchkick.search_method_name&lt;/code&gt; now our &lt;code&gt;scope_searchkick&lt;/code&gt; method is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scope_searchkick&lt;/span&gt;
    &lt;span class="nb"&gt;class_eval&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;
        &lt;span class="n"&gt;define_method&lt;/span&gt; &lt;span class="no"&gt;Searchkick&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search_method_name&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;term&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'*'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
          &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:where&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;key?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:where&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="n"&gt;options_with_tenant_scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:where&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;tenant_id: &lt;/span&gt;&lt;span class="n"&gt;current_tenant_id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;)&lt;/span&gt;

          &lt;span class="n"&gt;searchkick_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options_with_tenant_scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You've got to love the Ruby Metaprogramming.&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>searchkick</category>
      <category>monkeypatching</category>
    </item>
    <item>
      <title>Vuetify TreeView Async Error (Cannot set property 'vnode' of undefined) Workaround</title>
      <dc:creator>Mahmoud Sultan</dc:creator>
      <pubDate>Sat, 19 Oct 2019 14:08:04 +0000</pubDate>
      <link>https://dev.to/mahmoudsultan36/vuetify-treeview-async-error-cannot-set-property-vnode-of-undefined-workaround-34gf</link>
      <guid>https://dev.to/mahmoudsultan36/vuetify-treeview-async-error-cannot-set-property-vnode-of-undefined-workaround-34gf</guid>
      <description>&lt;h1&gt;
  
  
  Context
&lt;/h1&gt;

&lt;p&gt;This is my first blog post here, so I wanted to keep it short and talk about a bug that I came across quite recently in Vuetify TreeView when using Async child loading.&lt;/p&gt;

&lt;p&gt;This is, however, a workaround - for the people, like me, who need to push this now without opening a PR - and not a fix for the bug, so keep that in mind.&lt;/p&gt;

&lt;h1&gt;
  
  
  Recreating The Bug
&lt;/h1&gt;

&lt;p&gt;Let's start with the code found on the vuetify component page found here: &lt;a href="https://v15.vuetifyjs.com/en/components/treeview#async-items"&gt;https://v15.vuetifyjs.com/en/components/treeview#async-items&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;However, when I do push the children of the item, something like this happens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TypeError: Cannot set property 'vnode' of undefined
    at a.register (VTreeview.js:257)
    at a.created (VTreeviewNode.js:132)
....
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After a long session of debugging (not really I just open Chrome DevTools and set a breakpoint "at a.register (VTreeview.js:257)" and read the problem description on this StackOverflow here: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/57293198/vuetify-treeview-error-loading-children-asynchronously/58396813#58396813"&gt;https://stackoverflow.com/questions/57293198/vuetify-treeview-error-loading-children-asynchronously/58396813#58396813&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vuetify basically tries to find a node in the nodes objects with key equal to the id of the child node, the child node, however, has no entry on this object hence the error.&lt;/p&gt;

&lt;p&gt;Given the timeline I had and the need to push this ASAP:&lt;/p&gt;

&lt;p&gt;My Just-Hack-it-For-Now Part of Brain: Then just create one.&lt;br&gt;
Me: Aha.&lt;br&gt;
My Just-Hack-it-For-Now Part of Brain: Yeah.&lt;/p&gt;

&lt;p&gt;So that's exactly what I did.&lt;/p&gt;

&lt;p&gt;in the &lt;code&gt;fetchUsers&lt;/code&gt; function we can add a few lines for this &lt;strong&gt;before&lt;/strong&gt; pushing the items the parent's children array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parentNode&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;$refs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;treeReference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;childNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;children&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;child&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;childNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;parentNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;vnode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&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;$refs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;treeReference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;childNode&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

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



&lt;p&gt;First, let's get the ParentNode - which we are going to clone for the child - using the key &lt;code&gt;item.id&lt;/code&gt; from nodes object in the tree.&lt;/p&gt;

&lt;p&gt;Then for each child just clone the parentNode setting item to the child however and vnode to null.&lt;/p&gt;

&lt;p&gt;This fixes it for me; code pushed and everyone is happy.&lt;/p&gt;

&lt;p&gt;Please let me know if you have a less hacky solution for this, I'd really appreciate it.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>vuetify</category>
      <category>javascript</category>
      <category>bug</category>
    </item>
  </channel>
</rss>
