<?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: Faisal Shaikh</title>
    <description>The latest articles on DEV Community by Faisal Shaikh (@faisalshaikh8433).</description>
    <link>https://dev.to/faisalshaikh8433</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%2F297845%2F4f289d92-4b85-4a5c-a643-e539c6e9e5ff.jpeg</url>
      <title>DEV Community: Faisal Shaikh</title>
      <link>https://dev.to/faisalshaikh8433</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/faisalshaikh8433"/>
    <language>en</language>
    <item>
      <title>Run artisan command instantly in the background using Symfony process component</title>
      <dc:creator>Faisal Shaikh</dc:creator>
      <pubDate>Mon, 23 May 2022 06:28:19 +0000</pubDate>
      <link>https://dev.to/faisalshaikh8433/run-artisan-command-instantly-in-the-background-using-symfony-process-component-33b5</link>
      <guid>https://dev.to/faisalshaikh8433/run-artisan-command-instantly-in-the-background-using-symfony-process-component-33b5</guid>
      <description>&lt;p&gt;Sometimes we want to optimize an API response time but we can't optimize it because the API has operations that can't be moved to background jobs, we need to perform them in the foreground.&lt;/p&gt;

&lt;p&gt;In this type of situation, the &lt;strong&gt;Symfony process&lt;/strong&gt; component can help.&lt;/p&gt;

&lt;p&gt;When the API is called, we will perform the most important steps like creating/updating main table records, rest of the steps can be moved to an artisan command which will be run instantly in the background using the &lt;strong&gt;Symfony process&lt;/strong&gt; component.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function runBackgroundProcess($command, $data)
{
 $phpBinaryFinder = new PhpExecutableFinder();

 $phpBinaryPath = $phpBinaryFinder-&amp;gt;find();

 $process = new Process ([$phpBinaryPath, base_path('artisan'), $command, $data]); // (['php', 'artisan', 'foo:bar', 'json data'])

 $process-&amp;gt;setoptions(['create_new_console' =&amp;gt; true]); //Run process in background 
 $process-&amp;gt;start();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just call the above function in your regular PHP code flow and we can achieve asynchronous kind of functionality with this approach. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tip: Use a table to track process failure.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>symfony</category>
      <category>asynchronous</category>
    </item>
    <item>
      <title>Vuejs dynamic components</title>
      <dc:creator>Faisal Shaikh</dc:creator>
      <pubDate>Sat, 13 Mar 2021 13:21:19 +0000</pubDate>
      <link>https://dev.to/faisalshaikh8433/vuejs-dynamic-components-4kk2</link>
      <guid>https://dev.to/faisalshaikh8433/vuejs-dynamic-components-4kk2</guid>
      <description>&lt;p&gt;Vue dynamic components enable users to switch between two or more components and even retain the state of data when switching back to the initial component.&lt;/p&gt;

&lt;h3&gt;
  
  
  Some use cases are as follows:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Show or hide nested components based on the application state.&lt;/li&gt;
&lt;li&gt;Tabbed interface like bootstrap tab pill.&lt;/li&gt;
&lt;li&gt;You can even achieve router functionality without using the Vue router &lt;strong&gt;(not recommended for large projects)&lt;/strong&gt;. For eg. on click of the home link, we can load the home component dynamically.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Declaring a dynamic component:
&lt;/h3&gt;

&lt;p&gt;Vue provides a special element to place dynamic components called &lt;strong&gt;'component'&lt;/strong&gt;. You can pass props too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Syntax:&lt;/strong&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;lt;component v-bind:is=”currentComponent” :prop1='foo' :prop2='bar'&amp;gt;&amp;lt;/component&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here &lt;strong&gt;currentComponent&lt;/strong&gt; is the data property that returns the component name which needs to be mounted.&lt;/p&gt;

&lt;p&gt;To maintain the state of the data object of components while switching between them we can use a special element called &lt;strong&gt;'keep-alive'&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Syntax:&lt;/strong&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;lt;keep-alive&amp;gt;
      &amp;lt;component v-bind:is="currentComponent" :prop1='foo' :prop2='bar'/&amp;gt;
&amp;lt;/keep-alive&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Full example:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div id="app"&amp;gt;
    &amp;lt;keep-alive&amp;gt;
      &amp;lt;component v-bind:is="currentComponent" /&amp;gt;
    &amp;lt;/keep-alive&amp;gt;
    &amp;lt;button v-on:click="mountOne"&amp;gt;One&amp;lt;/button&amp;gt;
    &amp;lt;button v-on:click="mountTwo"&amp;gt;Two&amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
import One from './components/One.vue'
import Two from './components/Two.vue'
import Three from './components/Three.vue'
export default {
  name: 'app',
  components: {
    One,
     Two
  },
  data (){
    return {
      currentComponent:'Three'
    }
  },
  methods: {
    mountOne(){
        this.currentComponent = 'One';
    },
    mountTwo(){
        this.currentComponent = 'Two';
    }
  }
}
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>vue</category>
      <category>html</category>
      <category>beginners</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Custom validation error message using Laravel blade component</title>
      <dc:creator>Faisal Shaikh</dc:creator>
      <pubDate>Sat, 09 Jan 2021 06:07:15 +0000</pubDate>
      <link>https://dev.to/faisalshaikh8433/custom-validation-error-message-using-laravel-blade-component-gi</link>
      <guid>https://dev.to/faisalshaikh8433/custom-validation-error-message-using-laravel-blade-component-gi</guid>
      <description>&lt;p&gt;There are multiple ways to display a custom error message for a failed validation in &lt;strong&gt;Laravel&lt;/strong&gt;. We can even use the blade component to achieve this.&lt;/p&gt;

&lt;p&gt;Just put this component below the input you want to validate. Pass the name of the input to the &lt;strong&gt;for&lt;/strong&gt; attribute and your custom message to the &lt;strong&gt;custom-message&lt;/strong&gt; attribute. Boom you are done!!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&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;lt;x-input-error for="foo_name" custom-message="Foo is required" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Component:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@props(['for', 'customMessage'])
@error($for)
&amp;lt;p {{ $attributes-&amp;gt;merge(['class' =&amp;gt; 'text-sm text-red-600 mt-1']) }}&amp;gt;{{ $customMessage ?? $message  }}&amp;lt;/p&amp;gt;
@enderror
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>laravel</category>
      <category>html</category>
      <category>bladecomponent</category>
      <category>php</category>
    </item>
    <item>
      <title>Build an email tracking service using Laravel, AWS SES &amp; SNS services.</title>
      <dc:creator>Faisal Shaikh</dc:creator>
      <pubDate>Sun, 18 Oct 2020 05:41:00 +0000</pubDate>
      <link>https://dev.to/faisalshaikh8433/build-an-email-tracking-service-using-laravel-aws-ses-sns-services-h96</link>
      <guid>https://dev.to/faisalshaikh8433/build-an-email-tracking-service-using-laravel-aws-ses-sns-services-h96</guid>
      <description>&lt;p&gt;&lt;strong&gt;AWS setup:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to the SNS dashboard and &lt;strong&gt;create a new topic&lt;/strong&gt; of which we want to receive notifications. This topic will serve as a bridge between SNS and SES. For example, I have created an &lt;strong&gt;email-notifications&lt;/strong&gt; topic.&lt;/li&gt;
&lt;li&gt;Create a &lt;strong&gt;subscription&lt;/strong&gt; for this topic where we will define our web app's public URL and process the notification data.&lt;/li&gt;
&lt;li&gt;Select the &lt;strong&gt;topic&lt;/strong&gt; we created. The protocol can be https. The endpoint will be our web app's public route. We want a notification in JSON format so no need to enable raw message delivery. As soon as we create the subscription SNS will send a notification for confirmation of the link. We have to visit a &lt;strong&gt;subscription URL&lt;/strong&gt; for confirming the subscription after that we will start receiving the notification. The code for confirming the subscribe URL is done below in the Laravel setup. If we miss confirming the subscription we can request a reconfirm.&lt;/li&gt;
&lt;li&gt;Set up the &lt;strong&gt;SES configuration set&lt;/strong&gt; from the SES dashboard. Add a new configuration set, name it, and then edit it for defining the destination of email notifications like delivery, opened, etc. Select SNS from the add destination option, type the name, select the event types we want SES to send it to SNS, and the topic which we created in the first step. Now set up for SES and SNS is done.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Laravel setup:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;To use the Amazon SES driver for sending mail we have to install the &lt;strong&gt;Amazon AWS SDK&lt;/strong&gt; for PHP, by adding the &lt;strong&gt;"aws/aws-sdk-php": "~3.0"&lt;/strong&gt; to your &lt;strong&gt;composer.json&lt;/strong&gt; file's require section and running the &lt;strong&gt;composer update&lt;/strong&gt; command.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set the default option in your &lt;strong&gt;config/mail.php&lt;/strong&gt; configuration file to SES and in &lt;strong&gt;config/services.php&lt;/strong&gt; add key, secret, region and in options, array add configuration set name which we created in AWS setup.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'ses' =&amp;gt; [
       'key' =&amp;gt; env('AWS_ACCESS_KEY_ID'),
       'secret' =&amp;gt; env('AWS_SECRET_ACCESS_KEY'),
       'region' =&amp;gt; env('AWS_DEFAULT_REGION', 'ap-south-1'),
       'options' =&amp;gt; [
           'ConfigurationSetName' =&amp;gt; env('AWS_SES_CONFIG_SET', 'email-notifications'),
       ],
   ],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Whenever we send an email we will be getting a unique message-id through an &lt;strong&gt;X-SES-message-ID&lt;/strong&gt; header which is added by AWS SES, we have to store this id in the database table for matching it with SNS notification &lt;strong&gt;messageId&lt;/strong&gt;. So I have created an &lt;strong&gt;Amazon Controller&lt;/strong&gt; and &lt;strong&gt;sendEmail&lt;/strong&gt; method for sending the email and persisting the message-id and email details in the &lt;strong&gt;sent_emails&lt;/strong&gt; table.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a public route that we define as an endpoint for our SNS subscription in &lt;strong&gt;web.php&lt;/strong&gt;. We will receive notifications as a post request. I have created an &lt;strong&gt;emailNotifications&lt;/strong&gt; method in &lt;strong&gt;Amazon controller&lt;/strong&gt; for handling this post request.&lt;br&gt;
&lt;strong&gt;Route::post(‘amazon-sns/email-notifications’, ‘AmazonController@emailNotifications’);&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As the data comes as a post request we have to tell our verify csrf token middleware to exclude this route. So in &lt;strong&gt;VerifyCsrfToken.php&lt;/strong&gt; add &lt;strong&gt;‘/amazon-sns/email-notifications’&lt;/strong&gt; in the except array.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We receive 2 types of notifications, a subscription confirmation which is for confirming the URL endpoint when we create a subscription for the first time from the SNS dashboard and the other one is just normal notification with SNS events.&lt;br&gt;
So in the &lt;strong&gt;emailNotifications&lt;/strong&gt; method, we take all the JSON from the request, then check the value of the &lt;strong&gt;‘Type’&lt;/strong&gt; key if it is &lt;strong&gt;‘SubscriptionConfirmation’&lt;/strong&gt; then we get the value of &lt;strong&gt;‘SubscribeURL’&lt;/strong&gt; key and then using &lt;strong&gt;file_get_contents()&lt;/strong&gt; method we visit the URL and confirm the subscription.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the &lt;strong&gt;‘Type’&lt;/strong&gt; key is &lt;strong&gt;‘Notification’&lt;/strong&gt; then we take the value of &lt;strong&gt;‘Message’&lt;/strong&gt; key and decode it to an array, then check the value of &lt;strong&gt;‘eventType’&lt;/strong&gt; key which can be &lt;strong&gt;‘Bounce’, ‘Open’, ‘Delivery’&lt;/strong&gt;, etc. Now we take the &lt;strong&gt;‘Mail’&lt;/strong&gt; key whose value is an array and take the value of &lt;strong&gt;‘messageId’&lt;/strong&gt; key from it and update the &lt;strong&gt;sent_emails&lt;/strong&gt; table records according to the event by using this messageId and persisted messageId.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;JSON data for Subscription confirmation example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;array (
 'Type' =&amp;gt; 'SubscriptionConfirmation',
 'MessageId' =&amp;gt; 'c9f90bc3-6b7a-4ab9-8156-5b27b17797f8',
 'Token' =&amp;gt; '2336412f37fb687f5d51e6e2425f004aee4aa0c75a56575973dba0d4ca2fa9f2d12a4ee88495d74faebbdda39e034e91fc520e03aa05796e452ab5c12cc81a666e25fe99529b3975bb34a500d84d692dbcace3d64cc36273504da5b0464a954b7d48239c61198e2eb161f6cfcfa6304b566c685c407b9c65b7c07d7d2d11da32',
 'TopicArn' =&amp;gt; 'arn:aws:sns:ap-south-1:499826649778:email-notifications',
'Message' =&amp;gt; 'You have chosen to subscribe to the topic arn:aws:sns:ap-south-1:499826649778:email-notifications.
To confirm the subscription, visit the SubscribeURL included in this message.',
 'SubscribeURL' =&amp;gt; 'https://sns.ap-south-1.amazonaws.com/?Action=ConfirmSubscription&amp;amp;TopicArn=arn:aws:sns:ap-south-1:499826649778:email-notifications&amp;amp;Token=2336412f37fb687f5d51e6e2425f004aee4aa0c75a56575973dba0d4ca2fa9f2d12a4ee88495d74faebbdda39e034e91fc520e03aa05796e452ab5c12cc81a666e25fe99529b3975bb34a500d84d692dbcace3d64cc36273504da5b0464a954b7d48239c61198e2eb161f6cfcfa6304b566c685c407b9c65b7c07d7d2d11da32',
 'Timestamp' =&amp;gt; '2020-07-21T11:26:03.334Z',
 'SignatureVersion' =&amp;gt; '1',
 'Signature' =&amp;gt; 'QVIAlzHwf4DkxvtwBpKp9SByF9Z9Yh88t46ksTUkYA3Vr3nqkaKgVDmIE6wjdLn/B3LlkDU27zl9R+O2Sn4X9CSw9TT7B221zFCciEm6lbrQpIAX+KJ81blvaanR45pQY1VH9ageUv+2fk8VJvz1VnXw1+0fNIGx7k67aQbI1OttagbRr9wUIay/bwGq8LlP+rTviU8qg+AWbJgfg0iLhyoYSw5VaVL4aFyu7v5tLACMpRfPRDfIMaejmCJQBRfxWLfSFmALgkWcTIcUcWPllrw1sFEqgP+PzXlFfSfEkCzkcmqdy8++XfzEjME9lHky3kcOqgcaWse8Fs4GTFEsiQ==',
 'SigningCertURL' =&amp;gt; 'https://sns.ap-south-1.amazonaws.com/SimpleNotificationService-a86cb10b4e1f29c941702d737128f7b6.pem',
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;JSON data for Notification of delivery event example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;array (
 'Type' =&amp;gt; 'Notification',
 'MessageId' =&amp;gt; '81d5d58e-7838-5a2a-8fac-821ee35fc2e1',
 'TopicArn' =&amp;gt; 'arn:aws:sns:ap-south-1:499826649778:email-notifications',
 'Subject' =&amp;gt; 'Amazon SES Email Event Notification',
 'Message' =&amp;gt; '{"eventType":"Delivery","mail":{"timestamp":"2020-07-21T07:28:36.625Z","source":"foo@gmail.com","sourceArn":"arn:aws:ses:ap-south-1:499826649778:identity/foo@gmail.com","sendingAccountId":"499826649778","messageId":"0109017370463711-e110c671-cfe4-48d2-9f16-a6ee18b6edad-000000","destination":["bar@gmail.com"],"headersTruncated":false,"headers":[{"name":"Message-ID","value":"&amp;lt;c48ec65d8e3ffcc42020b52f3c28ecb5@127.0.0.1&amp;gt;"},{"name":"Date","value":"Tue, 21 Jul 2020 07:28:36 +0000"},{"name":"Subject","value":"SES TEST"},{"name":"From","value":"Email_Tracker &amp;lt;foo@gmail.com&amp;gt;"},{"name":"To","value":"bar@gmail.com"},{"name":"MIME-Version","value":"1.0"},{"name":"Content-Type","value":"text/html; charset=utf-8"},{"name":"Content-Transfer-Encoding","value":"quoted-printable"}],"commonHeaders":{"from":["Email_Tracker &amp;lt;foo@gmail.com&amp;gt;"],"date":"Tue, 21 Jul 2020 07:28:36 +0000","to":["bar@gmail.com"],"messageId":"0109017370463711-e110c671-cfe4-48d2-9f16-a6ee18b6edad-000000","subject":"SES TEST"},"tags":{"ses:operation":["SendRawEmail"],"ses:configuration-set":["email-notifications"],"ses:source-ip":["103.88.223.122"],"ses:from-domain":["gmail.com"],"ses:caller-identity":["root"],"ses:outgoing-ip":["76.223.180.12"]}},"delivery":{"timestamp":"2020-07-21T07:28:39.465Z","processingTimeMillis":2840,"recipients":["bar@gmail.com"],"smtpResponse":"250 2.0.0 OK  1595316519 r188si12628852pfc.330 - gsmtp","reportingMTA":"c180-12.smtp-out.ap-south-1.amazonses.com"}}
',
 'Timestamp' =&amp;gt; '2020-07-21T07:28:39.537Z',
 'SignatureVersion' =&amp;gt; '1',
 'Signature' =&amp;gt; 'I1OrPbUNXeFM681n6E9K0NlJovNUGTBOpk3OIylVAufwJQCeUF0/Syrn9RlUbDXcfe5z/HaI5T8SGB0Opnh53om7FU7++R5Nte2Zltp/MoC2DCVxGv+ycSlP4Zv4csftHLcrVu/XtXDGRA6JHystxeznY4iUnFY4IKz84d0l+eOAdTi/Z71qb3swMpzhGybLeNBhMUyBzv4FFlSbIYF2z5/gDCCPjDSIkvFE1nm4pl7Gk7YcU3Dyw8zlT05LbRMQRNR8jHzNhTzOXBLCA6Ej+mTZ+F2qWe+7dDRiSSOoVk2nO4NMo+9r0RmdslpRJzAaas/8e8i1uAwz9WskS/aX1A==',
 'SigningCertURL' =&amp;gt; 'https://sns.ap-south-1.amazonaws.com/SimpleNotificationService-a86cb10b4e1f29c941702d737128f7b6.pem',
 'UnsubscribeURL' =&amp;gt; 'https://sns.ap-south-1.amazonaws.com/?Action=Unsubscribe&amp;amp;SubscriptionArn=arn:aws:sns:ap-south-1:499826649778:email-notifications:c4f4e401-f0c6-4643-9fd4-8ba36fe34c8f',
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above JSON, only ‘eventType’ changes according to the event that happens and the rest remains the same.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Link to the source code:&lt;/strong&gt; &lt;a href="https://github.com/faisalshaikh8433/aws-ses-email-app"&gt;aws-ses-email-app&lt;/a&gt;&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>aws</category>
      <category>tutorial</category>
      <category>email</category>
    </item>
    <item>
      <title>Manipulating data object of the Vuejs component through JQuery events</title>
      <dc:creator>Faisal Shaikh</dc:creator>
      <pubDate>Mon, 31 Aug 2020 04:21:53 +0000</pubDate>
      <link>https://dev.to/faisalshaikh8433/manipulating-data-object-of-the-vuejs-component-through-jquery-events-20ih</link>
      <guid>https://dev.to/faisalshaikh8433/manipulating-data-object-of-the-vuejs-component-through-jquery-events-20ih</guid>
      <description>&lt;p&gt;JQuery uses its own event system. We cannot catch events emitted from jQuery with Vuejs, we have to catch them with jQuery and call Vuejs from the handler. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here is the code:&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;In our root Vue component binding the event:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mounted() {
    $("body").on("custom-event", this.methodForSettingDataObject);
},
beforeDestroy() {
    $("body").off("custom-event", this.methodForSettingDataObject);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Trigger event&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var event = jQuery.Event("custom-event");
event.foo = fooArray; 
event.bar = barArray;
$('body').trigger(event);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;It is considered a bad practice to use jQuery with Vuejs but it is not wrong as long as it solves a problem.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>vue</category>
      <category>jquery</category>
      <category>html</category>
    </item>
    <item>
      <title>Recognizing text from an image using Ruby</title>
      <dc:creator>Faisal Shaikh</dc:creator>
      <pubDate>Sat, 01 Feb 2020 07:45:10 +0000</pubDate>
      <link>https://dev.to/faisalshaikh8433/recognizing-text-from-an-image-using-ruby-2nj8</link>
      <guid>https://dev.to/faisalshaikh8433/recognizing-text-from-an-image-using-ruby-2nj8</guid>
      <description>&lt;p&gt;We can recognize the character's from an image using rtesseract gem and tesseract-ocr. So tesseract-ocr is an open-source OCR(optical character recognition) engine and rtesseract gem is a ruby wrapper for using tesseract-ocr.&lt;/p&gt;

&lt;p&gt;To make rtesseract gem work we need tesseract-ocr, leptonica libraries, headers, and a C++ compiler. The tesseract-ocr gem will provide all of this. If you're on a distribution that separates the libraries from headers, remember to install the -dev package. On Debian, you will need to install libleptonica-dev and libtesseract-dev.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installation steps are as follows:&lt;/strong&gt;&lt;br&gt;
First, install tesseract-ocr by using the following command &lt;strong&gt;"gem install tesseract-ocr"&lt;/strong&gt; and check the installation by using &lt;strong&gt;"tesseract --version"&lt;/strong&gt;.&lt;br&gt;
Then install rtesseract gem that's it start using the powerful tesseract for recognizing text in an image.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;For example:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  image = RTesseract.new('my_image.jpg', lang: 'eng') #lang is optional
  image.to_s # Getting the text value
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here RTesseract takes image URL which is required and lang is the type of language we want to scan and the default is eng - English, the "to_s" method returns the text and we can also convert the image into pdf by using "to_pdf" on the image object. It supports many more options and methods you can check it &lt;a href="https://github.com/dannnylo/rtesseract"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The reason I used this gem because I wanted to scan a folder of images and check whether an image consists of "No image" text if yes then move the image to the "no_image" folder.&lt;/em&gt; &lt;br&gt;
&lt;strong&gt;So below is the ruby code of how I achieved this.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;require 'fileutils'
require 'rtesseract'

class ExtractNameFromImage

  def move_images_from_folder(path)
    count = 0
    Dir.glob("#{path}/*") do |file|
      image = RTesseract.new(file)
      text = image.to_s
      count += 1
      if text.include? "No Image" 
        FileUtils.mv(file, 'pathtomove') #/home/user/no_image_folder
        puts "Moved #{file} scanned #{count}"
      else
        puts "Ok #{file} scanned #{count}"
      end
    end
  end
end
puts "Scanning directory #{ARGV[0]}"
extracter = ExtractNameFromImage.new
if File.directory?(ARGV[0])
  extracter.move_images_from_folder(ARGV[0])
else
  puts "No such directory exist, try again"
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Command to run this file &lt;strong&gt;"ruby image_name.rb home/user/pathtoimagefolder"&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Using this set up I can scan thousands of image without manually opening each of them one by one.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Streaming CSV files in Ruby On Rails</title>
      <dc:creator>Faisal Shaikh</dc:creator>
      <pubDate>Wed, 01 Jan 2020 06:58:34 +0000</pubDate>
      <link>https://dev.to/faisalshaikh8433/streaming-csv-files-in-ruby-on-rails-2oda</link>
      <guid>https://dev.to/faisalshaikh8433/streaming-csv-files-in-ruby-on-rails-2oda</guid>
      <description>&lt;p&gt;Here I will show you how to achieve the streaming of CSV files using Ruby On Rails and Postgres. We will use concerns for our model and controllers so that we can include them wherever needed. Model concern file generates the data for CSV and the controller concern file handles the file exporting on the client's end.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Model concern file generate_csv_data.rb contains this code as follows:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  module GenerateCsvData
   extend ActiveSupport::Concern
    class_methods do
     def stream_query_rows(sql_query, options="WITH CSV HEADER")
      conn = ActiveRecord::Base.connection.raw_connection
      conn.copy_data "COPY (#{sql_query}) TO STDOUT #{options};" do
      while row = conn.get_copy_data
       yield row
     end
    end
  end
 end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here stream_query_rows method accepts a query and options and yields the data. COPY (#{sql_query}) TO STDOUT #{options}; is a Postgres command which copies the data return by the query and output it to a specific format (here the format is CSV).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Controller concern file stream_file.rb contains this code as follows:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  module StreamFile
   extend ActiveSupport::Concern
    def stream_file(filename, extension)
     response.headers["Content-Type"] = "application/octet-stream"
     response.headers["Content-Disposition"] = "attachment; filename=# 
     {filename}-#{Time.now.to_i}.#{extension}"
     yield response.stream
   ensure
    response.stream.close
   end
  end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here stream_file method accepts a filename and extension of the file and then yields the response and sends the file as an attachment to the client.&lt;br&gt;
&lt;em&gt;We can then include our concerns wherever needed.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;We want all the data from the product's table into a CSV file and send the file as an attachment to the client. We will include the model concern in the product model and controller concern in products controller respectively:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Product Model:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  class ProductMaster &amp;lt; ApplicationRecord
   include GenerateCsvData
  end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Product Controller:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  class ProductsController &amp;lt; ApplicationController
   include StreamFile
   def export
    respond_to do |format|
    format.csv { stream_csv_report }
   end
  end

  private
  def stream_csv_report
    query = Product.some_query(query_params).to_sql
    query_options = "WITH CSV HEADER"
    # Note that if you have a custom select in your query
    # you may need to generate the header yourself. e.g.
    # =&amp;gt; stream.write "Name,Created Date,Price,# of Products"
    # =&amp;gt; query_options = "WITH CSV" # note the lack of 'HEADER'
    stream_file("products", "csv") do |stream|
      Product.stream_query_rows(query, query_options) do |row_from_db|
       # row_from_db will be ordered according to the select
       # e.g.
       # =&amp;gt; Given: "COPY (SELECT product.name as name, price, created_at 
            FROM sales INNER JOIN ...) TO STDOUT WITH CSV"
       # =&amp;gt; row_from_db will look like 'Bag, 500,2010-05-11 
            13:27:58.580456'
       stream.write row_from_db
      end
    end
   end
 end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generating CSV using a gem and ActiveRecord for large data of more than 1 lakh records would take lots of minutes and slow down the server until it finishes the process but with Postgres, we can achieve this under 2-3 minutes.&lt;/li&gt;
&lt;li&gt;Postgres is fast generating large data in CSV.&lt;/li&gt;
&lt;li&gt;Data is immediately downloaded on the client-side no need to save anywhere if you don't want to.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>postgres</category>
    </item>
  </channel>
</rss>
