Jekyll2022-10-05T10:06:05+00:00https://blog.ershadk.com/feed.xmlErshad KunnakkadanA blog of life and technology.{"name"=>nil, "avatar"=>"/assets/images/ershad.jpg", "bio"=>"Hey! I'm Ershad. Welcome to my blog. I write about programming and technology.", "location"=>nil, "email"=>nil, "uri"=>nil, "home"=>nil, "bitbucket"=>nil, "codepen"=>nil, "dribbble"=>nil, "flickr"=>"ershad_k", "facebook"=>nil, "foursquare"=>nil, "github"=>"ershad", "gitlab"=>nil, "google_plus"=>nil, "keybase"=>nil, "instagram"=>nil, "lastfm"=>nil, "linkedin"=>"ershadk", "pinterest"=>nil, "quora"=>nil, "soundcloud"=>nil, "stackoverflow"=>nil, "steam"=>nil, "tumblr"=>nil, "twitter"=>"ershus", "vine"=>nil, "weibo"=>nil, "xing"=>nil, "youtube"=>nil}How to parse JSON in command line using jq2020-05-17T00:00:00+00:002020-05-17T00:00:00+00:00https://blog.ershadk.com/2020/05/17/how-to-parse-json-in-command-line-using-jq<p><a href="https://stedolan.github.io/jq">jq</a> is an exceptional tool to parse JSON in command line. In this post, we will go through some of its basic options and usages.</p>
<h3 id="installation">Installation</h3>
<p>If you are on Ubuntu or Debian, you can install <code class="language-plaintext highlighter-rouge">jq</code> using <code class="language-plaintext highlighter-rouge">apt</code>.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">sudo </span>apt-get <span class="nb">install </span>jq</code></pre></figure>
<p>On macOS, you can install it using Homebrew.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">brew <span class="nb">install </span>jq</code></pre></figure>
<h3 id="usage">Usage</h3>
<p>To demonstrate the usage of <code class="language-plaintext highlighter-rouge">jq</code>, we will use the sample JSON data provided by <a href="https://jsonplaceholder.typicode.com">jsonplaceholder.typicode.com</a>. Its <code class="language-plaintext highlighter-rouge">/users</code> endpoint lists 10 sample users in the following format.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>curl <span class="nt">-s</span> https://jsonplaceholder.typicode.com/users
<span class="o">[</span>
<span class="o">{</span>
<span class="s2">"id"</span>: 1,
<span class="s2">"name"</span>: <span class="s2">"Leanne Graham"</span>,
<span class="s2">"username"</span>: <span class="s2">"Bret"</span>,
<span class="s2">"email"</span>: <span class="s2">"Sincere@april.biz"</span>,
<span class="s2">"address"</span>: <span class="o">{</span>
<span class="s2">"street"</span>: <span class="s2">"Kulas Light"</span>,
<span class="s2">"suite"</span>: <span class="s2">"Apt. 556"</span>,
<span class="s2">"city"</span>: <span class="s2">"Gwenborough"</span>,
<span class="s2">"zipcode"</span>: <span class="s2">"92998-3874"</span>,
<span class="s2">"geo"</span>: <span class="o">{</span>
<span class="s2">"lat"</span>: <span class="s2">"-37.3159"</span>,
<span class="s2">"lng"</span>: <span class="s2">"81.1496"</span>
<span class="o">}</span>
<span class="o">}</span>,
<span class="s2">"phone"</span>: <span class="s2">"1-770-736-8031 x56442"</span>,
<span class="s2">"website"</span>: <span class="s2">"hildegard.org"</span>,
<span class="s2">"company"</span>: <span class="o">{</span>
<span class="s2">"name"</span>: <span class="s2">"Romaguera-Crona"</span>,
<span class="s2">"catchPhrase"</span>: <span class="s2">"Multi-layered client-server neural-net"</span>,
<span class="s2">"bs"</span>: <span class="s2">"harness real-time e-markets"</span>
<span class="o">}</span>
<span class="o">}</span>,
.....</code></pre></figure>
<p class="notice--info">đĄ <code class="language-plaintext highlighter-rouge">curl -s</code> runs <code class="language-plaintext highlighter-rouge">curl</code> in quiet mode and hides the request progress meter.</p>
<p><strong>1.</strong> Extract the name from the first user.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>curl <span class="nt">-s</span> https://jsonplaceholder.typicode.com/users | <span class="se">\</span>
jq <span class="s1">'.[0] .name'</span>
<span class="s2">"Leanne Graham"</span></code></pre></figure>
<p><code class="language-plaintext highlighter-rouge">'.'</code> refers to the entire JSON object.</p>
<p><code class="language-plaintext highlighter-rouge">'.[0]'</code> refers to the first object in the JSON array.</p>
<p><code class="language-plaintext highlighter-rouge">'.[0] .name'</code> refers to the <code class="language-plaintext highlighter-rouge">name</code> attribute in the first object in the JSON array.</p>
<p>We can use <code class="language-plaintext highlighter-rouge">-r</code> switch in <code class="language-plaintext highlighter-rouge">jq</code> to remove the quotes from the output.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>curl <span class="nt">-s</span> https://jsonplaceholder.typicode.com/users | <span class="se">\</span>
jq <span class="nt">-r</span> <span class="s1">'.[0] .name'</span>
Leanne Graham</code></pre></figure>
<p><strong>2.</strong> Extract the names of all users.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>curl <span class="nt">-s</span> https://jsonplaceholder.typicode.com/users | <span class="se">\</span>
jq <span class="nt">-r</span> <span class="s1">'.[] .name'</span>
Leanne Graham
Ervin Howell
Clementine Bauch
Patricia Lebsack
Chelsey Dietrich
.....</code></pre></figure>
<p><code class="language-plaintext highlighter-rouge">'.[]'</code> refers to all objects in the JSON array.</p>
<p><strong>3.</strong> Extract selected attributes.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>curl <span class="nt">-s</span> https://jsonplaceholder.typicode.com/users | <span class="se">\</span>
jq <span class="s1">'.[0] | { name: .name, city: .address.city}'</span>
<span class="o">{</span>
<span class="s2">"name"</span>: <span class="s2">"Leanne Graham"</span>,
<span class="s2">"city"</span>: <span class="s2">"Gwenborough"</span>
<span class="o">}</span></code></pre></figure>
<p>Notice how we extract <code class="language-plaintext highlighter-rouge">city</code> field using <code class="language-plaintext highlighter-rouge">.address.city</code> expression. It looks inside <code class="language-plaintext highlighter-rouge">address</code> object to fetch the <code class="language-plaintext highlighter-rouge">city</code> attribute of the user.</p>
<p><strong>4.</strong> Extract selected attributes of all users.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>curl <span class="nt">-s</span> https://jsonplaceholder.typicode.com/users | <span class="se">\</span>
jq <span class="s1">'[.[] | { name: .name, city: .address.city}]'</span>
<span class="o">[</span>
<span class="o">{</span>
<span class="s2">"name"</span>: <span class="s2">"Leanne Graham"</span>,
<span class="s2">"city"</span>: <span class="s2">"Gwenborough"</span>
<span class="o">}</span>,
<span class="o">{</span>
<span class="s2">"name"</span>: <span class="s2">"Ervin Howell"</span>,
<span class="s2">"city"</span>: <span class="s2">"Wisokyburgh"</span>
<span class="o">}</span>,
.....
<span class="o">]</span></code></pre></figure>
<p>Wrapping the expression inside <code class="language-plaintext highlighter-rouge">[]</code> encloses the result in an array.</p>
<p><strong>5.</strong> Conditionally extract attributes of users.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>curl <span class="nt">-s</span> https://jsonplaceholder.typicode.com/users | <span class="se">\</span>
jq <span class="nt">-r</span> <span class="s1">'.[] | select(.address.zipcode == "92998-3874") | .name'</span>
Leanne Graham</code></pre></figure>
<p>Using <code class="language-plaintext highlighter-rouge">select</code> function, we can filter through the JSON objects based on a boolean expression. In this example, we are parsing the names of all users with zipcode <code class="language-plaintext highlighter-rouge">92998-3874</code>.</p>
<p><code class="language-plaintext highlighter-rouge">jq</code> is quite useful in shell scripts that process JSON data. It has many other features and they all are documented in its <a href="https://stedolan.github.io/jq/manual">manual</a>.</p>ershadjq is an exceptional tool to parse JSON in command line. In this post, we will go through some of its basic options and usages.How to configure a simple internet status widget in macOS Menu Bar2020-05-11T00:00:00+00:002020-05-11T00:00:00+00:00https://blog.ershadk.com/2020/05/11/how-to-configure-a-simple-internet-status-widget-in-macos-menu-bar<p>Sometimes during online calls, when we cannot hear the other person speaking, we would be wondering if itâs an issue with our internet or theirs.</p>
<p>If itâs an issue with our internet, we could try switching to a different network and resume the call. Just that we have to know it at the earliest so that we donât have to keep the other person waiting.</p>
<p>I had some internet connectivity issues a few months back and faced this problem. Each time when I couldnât hear the other person speaking I wondered if it was an issue with my internet. During those times I used <code class="language-plaintext highlighter-rouge">ping</code> command or refreshed pages in the browser to check the status of my connection. I wanted to automate this check and put together a solution using <a href="https://getbitbar.com">BitBar</a>.</p>
<p>BitBar is an opensource macOS utility to put the output of any executable script in the Mac menu bar. I wrote a small script to periodically check the internet connection and show an emoji (or latency) when the connection isnât stable. Here are the steps to configure it.</p>
<p><strong>Step 1:</strong> Download, install and run <a href="https://getbitbar.com">BitBar</a>.</p>
<p><strong>Step 2:</strong> Open its plugin folder.</p>
<p><img src="/assets/images/bitbar_plugin_dir.png" alt="BitBar plugin directory" class="project-image align-center" /></p>
<p><strong>Step 3:</strong> Copy this script with file name <code class="language-plaintext highlighter-rouge">check_internet.5s.sh</code> to the plugin folder.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c">#!/bin/bash</span>
<span class="nv">LATENCY_THRESHOLD</span><span class="o">=</span>30
<span class="nv">latency</span><span class="o">=</span><span class="si">$(</span>ping <span class="nt">-c1</span> 8.8.8.8 <span class="nt">-t</span> 2 | <span class="se">\</span>
perl <span class="nt">-n</span> <span class="nt">-e</span><span class="s1">'/time=(\d+)/ && print $1'</span><span class="si">)</span>
<span class="k">if</span> <span class="o">[[</span> <span class="o">!</span> <span class="nt">-z</span> <span class="s2">"</span><span class="nv">$latency</span><span class="s2">"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
if</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$latency</span><span class="s2">"</span> <span class="nt">-gt</span> <span class="nv">$LATENCY_THRESHOLD</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
</span><span class="nb">echo</span> <span class="s2">"âď¸ </span><span class="nv">$latency</span><span class="s2">"</span>
<span class="k">else
</span><span class="nb">echo</span> <span class="s2">"âď¸"</span>
<span class="k">fi
else
</span><span class="nb">echo</span> <span class="s2">"â"</span>
<span class="k">fi</span></code></pre></figure>
<p><strong>Step 4:</strong> Make the script executable. Run the following command in terminal after replacing <code class="language-plaintext highlighter-rouge"><path to></code> with the path of plugin folder.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">chmod</span> +x <path to>/check_internet.5s.sh</code></pre></figure>
<p><strong>Step 5:</strong> Click <code class="language-plaintext highlighter-rouge">Refresh all</code></p>
<p><img src="/assets/images/bitbar_refresh_all.png" alt="BitBar Refresh all" class="project-image align-center" /></p>
<p>You are all set! BitBar now checks your internet every 5 seconds and it would show âââ emoji in the menu bar when your internet isnât working.</p>
<p><img src="/assets/images/bitbar_not_connected.png" alt="BitBar not connected" class="project-image align-center" /></p>
<p>When you have a stable internet, it shows a ââď¸â.</p>
<p><img src="/assets/images/bitbar_connected.png" alt="BitBar connected" class="project-image align-center" /></p>
<p>It would also show you the latency if itâs above 30ms. This information would be useful when you have the internet but the connection isnât stable.</p>
<p><img src="/assets/images/bitbar_high_latency.png" alt="BitBar not connected" class="project-image align-center" /></p>
<p>I hope it helped. Thanks for reading. Stay Safe.</p>ershadSometimes during online calls, when we cannot hear the other person speaking, we would be wondering if itâs an issue with our internet or theirs.How to terminate EC2 instance by IP from terminal2020-04-04T00:00:00+00:002020-04-04T00:00:00+00:00https://blog.ershadk.com/2020/04/04/how-to-terminate-ec2-instance-by-ip-from-terminal<p>Hereâs an quick command line shortcut to terminate an <a href="https://aws.amazon.com/ec2/">AWS EC2</a> instance if you know the private IP address but not the instance ID.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># Function to terminate EC2 instance by IP</span>
<span class="k">function </span>terminate_instance<span class="o">(){</span>
<span class="nv">instance_id</span><span class="o">=</span><span class="si">$(</span>aws ec2 describe-instances <span class="se">\</span>
<span class="nt">--filter</span> <span class="nv">Name</span><span class="o">=</span>private-ip-address,Values<span class="o">=</span><span class="nv">$1</span> <span class="se">\</span>
<span class="nt">--query</span> <span class="s2">"Reservations[].Instances[].[InstanceId]"</span> <span class="se">\</span>
<span class="nt">--output</span> text<span class="si">)</span>
aws ec2 terminate-instances <span class="nt">--instance-ids</span> <span class="nv">$instance_id</span>
<span class="o">}</span>
<span class="c"># Usage</span>
<span class="c"># $ terminate_instance <private IP address></span>
<span class="c"># Example</span>
<span class="c"># $ terminate_instance 10.0.32.64</span></code></pre></figure>
<p>This shortcut often saves me visits to the EC2 Dashboard đ</p>ershadHereâs an quick command line shortcut to terminate an AWS EC2 instance if you know the private IP address but not the instance ID.Install RMagick 2.13.2 in macOS Sierra2017-02-01T01:29:25+00:002017-02-01T01:29:25+00:00https://blog.ershadk.com/2017/02/01/install-rmagick-2-13-2-in-macos-sierra<p><a href="http://brew.sh/" target="_blank">Homebrew</a>Â is usually pretty good at installing ImageMagick and I was wondering why it threw the following error when I tried to configure an old Rails project in macOS Sierra. I had run <code>brew install imagemagick</code> before installing the RMagick gem and still got this -</p>
<figure class="highlight"><pre><code class="language-text" data-lang="text">checking for ruby version &gt;= 1.8.5... yes
checking for /usr/local/cellar/gcc@4.9/4.9.3_1/bin/gcc-4.9... yes
checking for magick-config... no
can't install rmagick 2.13.2. can't find magick-config in &lt;snip&gt;</code></pre></figure>
<p>Turns out Homebrew installed <code>ImageMagick 7.0.4-6</code> and it doesn't have <code>Magick-config</code> executable in its <code>bin</code> directory, instead it has <code>Magick++-config</code>.</p>
<p>Got the gem installed by downgrading ImageMagick to version 6 as follows.</p>
<figure class="highlight"><pre><code class="language-text" data-lang="text"># Uninstall ImageMagick 7
brew uninstall imagemagick
brew install imagemagick@6
brew link imagemagick@6 --force</code></pre></figure>
<p>Now we can install the gem.</p>
<figure class="highlight"><pre><code class="language-text" data-lang="text">gem install rmagick -v '2.13.2'</code></pre></figure>{"name"=>nil, "avatar"=>"/assets/images/ershad.jpg", "bio"=>"Hey! I'm Ershad. Welcome to my blog. I write about programming and technology.", "location"=>nil, "email"=>nil, "uri"=>nil, "home"=>nil, "bitbucket"=>nil, "codepen"=>nil, "dribbble"=>nil, "flickr"=>"ershad_k", "facebook"=>nil, "foursquare"=>nil, "github"=>"ershad", "gitlab"=>nil, "google_plus"=>nil, "keybase"=>nil, "instagram"=>nil, "lastfm"=>nil, "linkedin"=>"ershadk", "pinterest"=>nil, "quora"=>nil, "soundcloud"=>nil, "stackoverflow"=>nil, "steam"=>nil, "tumblr"=>nil, "twitter"=>"ershus", "vine"=>nil, "weibo"=>nil, "xing"=>nil, "youtube"=>nil}Homebrew is usually pretty good at installing ImageMagick and I was wondering why it threw the following error when I tried to configure an old Rails project in macOS Sierra. I had run brew install imagemagick before installing the RMagick gem and still got this -TalentSpace and the 2 months BootCamp program2015-11-08T17:45:29+00:002015-11-08T17:45:29+00:00https://blog.ershadk.com/2015/11/08/talentspace<p>A few months back I joined <a href="http://bigbinary.com" target="_blank">BigBinary</a> as <em>remote</em> Software Developer and relocated to <a href="https://en.wikipedia.org/wiki/Kochi" target="_blank">Kochi</a> to stay close with family and friends. It's an unique experience working completely from home, I would save it for another post.</p>
<p><em>"What should I learn to get a job?"</em></p>
<p>It's a question I've seen a lot of people asking, often the talented ones. With many students graduating every year, only a few of them are able to secure good jobs or higher education opportunities. Rest are forced to pursue jobs unrelated to their interests with low salary or are left jobless. Interesting fact is that this happens when good companies are desperately looking for people to hire! It's a problem worth solving.</p>
<p>I always had a dream to build a place to learn and do technology together. Because it's more fun when things are done collaboratively with people of similar interests. I thought this would be the best time and soon put up a small website with an application form, <a href="http://talentspace.in" target="_blank">TalentSpace.in</a>.</p>
<p>Idea was to select a few passionate people through an online test/phone interview, train them in general programming and Ruby on Rails on Sundays, and refer them to good companies. Meanwhile I contacted a few companies asking whether they would like to be employer-partners in this venture. They were interested and happily came onboard. The overall response was exciting. Soon TalentSpace started getting applications, out of which 6 passionate people were selected.</p>
<p>Next challenge was to build a space for this. The apartment I live in Kochi has some commercial space in first 2 floors. Talked to the builder owners and they were more than happy to give a 1200sq ft hall for rent to build the office. They have a furniture shop as well through which they quickly arranged tables and chairs. Meanwhile I got a projector, screen and cables delivered through Amazon. Friends helped to arrange everything over a night and we were all set to begin!</p>
<p> </p>
<p><a href="http://ershadk.com/blog/wp-content/uploads/2015/11/DSC_0651.jpg"><img class="alignleft wp-image-831 size-thumbnail" src="/assets/DSC_0651-150x150.jpg" alt="TalentSpace_1" width="150" height="150" /></a><a href="http://ershadk.com/blog/wp-content/uploads/2015/11/Talentspace3.jpg"><img class="alignleft wp-image-833 size-thumbnail" src="/assets/12010583_10201129037505096_4090089986412591266_o-150x150.jpg" alt="TalentSpace_2" width="150" height="150" /></a><a href="http://ershadk.com/blog/wp-content/uploads/2015/11/Talentspace3.jpg"><img class="alignleft wp-image-832 size-thumbnail" src="/assets/Talentspace3-150x150.jpg" alt="TalentSpace_3" width="150" height="150" /></a></p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p>As scheduled 6 selected folks came for the first session on November 1, Sunday. We had another session last week and they have been doing fun-to-solve programming assignments in between. Currently we have a Slack group for discussions and a trello board to manage tasks. The entire BootCamp program is 2 months long with a fees of INR 20K. We hope to cover everything from building an application from scratch and deploying it in production.</p>
<p>We believe in social coding, going forward our plan is to take everything to <a href="http://github.com">GitHub</a>. Online code reviews and assigning with issues would give them an exposure to real world software development. Also none of us believes in certificates, the code these folks push would serve as a portfolio for potential recruiters.</p>
<p>It's all going great. Thanks to everyone who helped and supported to start this venture :)</p>{"name"=>nil, "avatar"=>"/assets/images/ershad.jpg", "bio"=>"Hey! I'm Ershad. Welcome to my blog. I write about programming and technology.", "location"=>nil, "email"=>nil, "uri"=>nil, "home"=>nil, "bitbucket"=>nil, "codepen"=>nil, "dribbble"=>nil, "flickr"=>"ershad_k", "facebook"=>nil, "foursquare"=>nil, "github"=>"ershad", "gitlab"=>nil, "google_plus"=>nil, "keybase"=>nil, "instagram"=>nil, "lastfm"=>nil, "linkedin"=>"ershadk", "pinterest"=>nil, "quora"=>nil, "soundcloud"=>nil, "stackoverflow"=>nil, "steam"=>nil, "tumblr"=>nil, "twitter"=>"ershus", "vine"=>nil, "weibo"=>nil, "xing"=>nil, "youtube"=>nil}A few months back I joined BigBinary as remote Software Developer and relocated to Kochi to stay close with family and friends. It's an unique experience working completely from home, I would save it for another post. "What should I learn to get a job?" It's a question I've seen a lot of people asking, often the talented ones. With many students graduating every year, only a few of them are able to secure good jobs or higher education opportunities. Rest are forced to pursue jobs unrelated to their interests with low salary or are left jobless. Interesting fact is that this happens when good companies are desperately looking for people to hire! It's a problem worth solving. I always had a dream to build a place to learn and do technology together. Because it's more fun when things are done collaboratively with people of similar interests. I thought this would be the best time and soon put up a small website with an application form, TalentSpace.in. Idea was to select a few passionate people through an online test/phone interview, train them in general programming and Ruby on Rails on Sundays, and refer them to good companies. Meanwhile I contacted a few companies asking whether they would like to be employer-partners in this venture. They were interested and happily came onboard. The overall response was exciting. Soon TalentSpace started getting applications, out of which 6 passionate people were selected. Next challenge was to build a space for this. The apartment I live in Kochi has some commercial space in first 2 floors. Talked to the builder owners and they were more than happy to give a 1200sq ft hall for rent to build the office. They have a furniture shop as well through which they quickly arranged tables and chairs. Meanwhile I got a projector, screen and cables delivered through Amazon. Friends helped to arrange everything over a night and we were all set to begin! As scheduled 6 selected folks came for the first session on November 1, Sunday. We had another session last week and they have been doing fun-to-solve programming assignments in between. Currently we have a Slack group for discussions and a trello board to manage tasks. The entire BootCamp program is 2 months long with a fees of INR 20K. We hope to cover everything from building an application from scratch and deploying it in production. We believe in social coding, going forward our plan is to take everything to GitHub. Online code reviews and assigning with issues would give them an exposure to real world software development. Also none of us believes in certificates, the code these folks push would serve as a portfolio for potential recruiters. It's all going great. Thanks to everyone who helped and supported to start this venture :)GSoC 2013: Week 10 of Grandham project2013-08-25T15:05:39+00:002013-08-25T15:05:39+00:00https://blog.ershadk.com/2013/08/25/grandham-week-10<p>Last week I've been working on admin review feature to incorporate the new changes happened in the user end.</p>
<p style="text-align: center;"><a href="http://ershadk.com/blog/wp-content/uploads/2013/08/Screen-Shot-2013-08-26-at-1.56.09-AM.png"><img class="aligncenter size-large wp-image-754" alt="Screen Shot 2013-08-26 at 1.56.09 AM" src="/assets/Screen-Shot-2013-08-26-at-1.56.09-AM-1024x290.png" width="625" height="177" /></a></p>
<p>With the addition of in-place editing feature, admins can now approve minor edits by actually looking the difference. They also have options to replace author/publisher if the previously set author was different.</p>
<p>Along with that, we now have an option to upload book cover. It can be found in 'Add new book' form. In the long run, it will be also appearing under each book cover(in book page) where user can upload a cover just like they edit other information.</p>
<p style="text-align: center;"><a href="http://ershadk.com/blog/wp-content/uploads/2013/08/Screen-Shot-2013-08-26-at-2.03.44-AM.png"><img class="aligncenter wp-image-755" alt="Screen Shot 2013-08-26 at 2.03.44 AM" src="/assets/Screen-Shot-2013-08-26-at-2.03.44-AM.png" width="429" height="176" /></a></p>{"name"=>nil, "avatar"=>"/assets/images/ershad.jpg", "bio"=>"Hey! I'm Ershad. Welcome to my blog. I write about programming and technology.", "location"=>nil, "email"=>nil, "uri"=>nil, "home"=>nil, "bitbucket"=>nil, "codepen"=>nil, "dribbble"=>nil, "flickr"=>"ershad_k", "facebook"=>nil, "foursquare"=>nil, "github"=>"ershad", "gitlab"=>nil, "google_plus"=>nil, "keybase"=>nil, "instagram"=>nil, "lastfm"=>nil, "linkedin"=>"ershadk", "pinterest"=>nil, "quora"=>nil, "soundcloud"=>nil, "stackoverflow"=>nil, "steam"=>nil, "tumblr"=>nil, "twitter"=>"ershus", "vine"=>nil, "weibo"=>nil, "xing"=>nil, "youtube"=>nil}Last week I've been working on admin review feature to incorporate the new changes happened in the user end. With the addition of in-place editing feature, admins can now approve minor edits by actually looking the difference. They also have options to replace author/publisher if the previously set author was different. Along with that, we now have an option to upload book cover. It can be found in 'Add new book' form. In the long run, it will be also appearing under each book cover(in book page) where user can upload a cover just like they edit other information.GSoC 2013: Week 9 of Grandham project2013-08-25T14:50:50+00:002013-08-25T14:50:50+00:00https://blog.ershadk.com/2013/08/25/grandham-week-9<p>In Week 9, I rewrote the complete crowdsourcing functionality of Grandham from a submission based approach to micro-edits based approach. Earlier we used to store the entire snapshot while recording modifications but now we store only the 'edit' (similar to diff, but in a structured database table) and pass it to admins for reviewing. This approach has some significant advantages including the easy generation of history of book pages.</p>
<p>In-place editing was integrated during the same week. Now participants can click on a field and edit it.</p>{"name"=>nil, "avatar"=>"/assets/images/ershad.jpg", "bio"=>"Hey! I'm Ershad. Welcome to my blog. I write about programming and technology.", "location"=>nil, "email"=>nil, "uri"=>nil, "home"=>nil, "bitbucket"=>nil, "codepen"=>nil, "dribbble"=>nil, "flickr"=>"ershad_k", "facebook"=>nil, "foursquare"=>nil, "github"=>"ershad", "gitlab"=>nil, "google_plus"=>nil, "keybase"=>nil, "instagram"=>nil, "lastfm"=>nil, "linkedin"=>"ershadk", "pinterest"=>nil, "quora"=>nil, "soundcloud"=>nil, "stackoverflow"=>nil, "steam"=>nil, "tumblr"=>nil, "twitter"=>"ershus", "vine"=>nil, "weibo"=>nil, "xing"=>nil, "youtube"=>nil}In Week 9, I rewrote the complete crowdsourcing functionality of Grandham from a submission based approach to micro-edits based approach. Earlier we used to store the entire snapshot while recording modifications but now we store only the 'edit' (similar to diff, but in a structured database table) and pass it to admins for reviewing. This approach has some significant advantages including the easy generation of history of book pages. In-place editing was integrated during the same week. Now participants can click on a field and edit it.GSoC 2013: Week 8 of Grandham project2013-08-11T13:17:22+00:002013-08-11T13:17:22+00:00https://blog.ershadk.com/2013/08/11/grandham-week-8<p style="text-align: left;">Last weekly I mainly worked on Search feature and admin interfaces. Here's a quick review:</p>
<ul>
<li>Experimented with various search engines like Sphinx, Ferret, etc and finally decided to use <a href="http://lucene.apache.org/solr/">Solr</a>Â with <a href="https://github.com/sunspot/sunspot">sunspot</a> gem as it worked well with unicorn data without any configuration.</li>
<li>Wrote a general search backend interface for Grandham. We can plugin other search engines anytime as long as it communicated the way Grandham needs it.</li>
<li>Added Admin interfaces managing Authors and Publishers.</li>
</ul>
<p style="padding-left: 30px;">{"name"=>nil, "avatar"=>"/assets/images/ershad.jpg", "bio"=>"Hey! I'm Ershad. Welcome to my blog. I write about programming and technology.", "location"=>nil, "email"=>nil, "uri"=>nil, "home"=>nil, "bitbucket"=>nil, "codepen"=>nil, "dribbble"=>nil, "flickr"=>"ershad_k", "facebook"=>nil, "foursquare"=>nil, "github"=>"ershad", "gitlab"=>nil, "google_plus"=>nil, "keybase"=>nil, "instagram"=>nil, "lastfm"=>nil, "linkedin"=>"ershadk", "pinterest"=>nil, "quora"=>nil, "soundcloud"=>nil, "stackoverflow"=>nil, "steam"=>nil, "tumblr"=>nil, "twitter"=>"ershus", "vine"=>nil, "weibo"=>nil, "xing"=>nil, "youtube"=>nil}Last weekly I mainly worked on Search feature and admin interfaces. Here's a quick review: Experimented with various search engines like Sphinx, Ferret, etc and finally decided to use Solr with sunspot gem as it worked well with unicorn data without any configuration. Wrote a general search backend interface for Grandham. We can plugin other search engines anytime as long as it communicated the way Grandham needs it. Added Admin interfaces managing Authors and Publishers.GSoC 2013: Week 7 of Grandham project2013-08-11T13:10:05+00:002013-08-11T13:10:05+00:00https://blog.ershadk.com/2013/08/11/grandham-week-7<p>I couldn't post the weekly updates regularly for the last two times since I was kept more busy than I had expected and the festive holiday that came in between. Here's a quick review of what happened during the 7th week of GSoC.</p>
<ul>
<li>Grandham got an UI revamp!</li>
<li>Integrated new <a href="bootswatch.com/readable/">theme</a>.</li>
<li>Separate books / authors / publishers lists were implemented</li>
<li>Updated user sign in / sign up pages</li>
<li>Integrated database clear and fixed failing specs (It's green now, yay!)</li>
</ul>{"name"=>nil, "avatar"=>"/assets/images/ershad.jpg", "bio"=>"Hey! I'm Ershad. Welcome to my blog. I write about programming and technology.", "location"=>nil, "email"=>nil, "uri"=>nil, "home"=>nil, "bitbucket"=>nil, "codepen"=>nil, "dribbble"=>nil, "flickr"=>"ershad_k", "facebook"=>nil, "foursquare"=>nil, "github"=>"ershad", "gitlab"=>nil, "google_plus"=>nil, "keybase"=>nil, "instagram"=>nil, "lastfm"=>nil, "linkedin"=>"ershadk", "pinterest"=>nil, "quora"=>nil, "soundcloud"=>nil, "stackoverflow"=>nil, "steam"=>nil, "tumblr"=>nil, "twitter"=>"ershus", "vine"=>nil, "weibo"=>nil, "xing"=>nil, "youtube"=>nil}I couldn't post the weekly updates regularly for the last two times since I was kept more busy than I had expected and the festive holiday that came in between. Here's a quick review of what happened during the 7th week of GSoC. Grandham got an UI revamp! Integrated new theme. Separate books / authors / publishers lists were implemented Updated user sign in / sign up pages Integrated database clear and fixed failing specs (It's green now, yay!)GSoC 2013: Week 6 of Grandham project2013-07-28T14:23:23+00:002013-07-28T14:23:23+00:00https://blog.ershadk.com/2013/07/28/grandham-week-6<p>This week I've been mostly fixing bugs, refactoring code and building admin features. Grandham has built in checks to avoid duplication in Authors/Publishers now.</p>
<p><strong>Submission Review Interface</strong>Â <a href="http://ershadk.com/blog/wp-content/uploads/2013/07/Grandham-review-page.png"><img class="alignright size-thumbnail wp-image-738" alt="Grandham review page" src="/assets/Grandham-review-page-150x150.png" width="150" height="150" /></a></p>
<p>We have a new interface this week -  A screen to review <em>crowdsourced </em>information submissions. Administrators can use this feature to control the information displayed to user. Currently every review item has 3 actions - Approve, Archive or Comment. Out of these, 'Comment' is a new feature which needs to be implemented. It will be helpful for the task force to generate discussions around specific submissions.</p>
<p><strong>Miscellaneous</strong></p>
<p>After a couple of rounds of refactoring, Grandham got a <a href="https://codeclimate.com/github/smc/grandham/trends">Code Climate score</a> of 4.0 from 1.61! :)</p>{"name"=>nil, "avatar"=>"/assets/images/ershad.jpg", "bio"=>"Hey! I'm Ershad. Welcome to my blog. I write about programming and technology.", "location"=>nil, "email"=>nil, "uri"=>nil, "home"=>nil, "bitbucket"=>nil, "codepen"=>nil, "dribbble"=>nil, "flickr"=>"ershad_k", "facebook"=>nil, "foursquare"=>nil, "github"=>"ershad", "gitlab"=>nil, "google_plus"=>nil, "keybase"=>nil, "instagram"=>nil, "lastfm"=>nil, "linkedin"=>"ershadk", "pinterest"=>nil, "quora"=>nil, "soundcloud"=>nil, "stackoverflow"=>nil, "steam"=>nil, "tumblr"=>nil, "twitter"=>"ershus", "vine"=>nil, "weibo"=>nil, "xing"=>nil, "youtube"=>nil}This week I've been mostly fixing bugs, refactoring code and building admin features. Grandham has built in checks to avoid duplication in Authors/Publishers now. Submission Review Interface We have a new interface this week -  A screen to review crowdsourced information submissions. Administrators can use this feature to control the information displayed to user. Currently every review item has 3 actions - Approve, Archive or Comment. Out of these, 'Comment' is a new feature which needs to be implemented. It will be helpful for the task force to generate discussions around specific submissions. Miscellaneous After a couple of rounds of refactoring, Grandham got a Code Climate score of 4.0 from 1.61! :)