I'm enthusiastic and passionate about web development and design in all it's forms and love to build application with efficient and simple methods

Tuesday, June 30, 2015

Vagrant: Built Customize Vagrant Box

7:25 PM Posted by Codeinterpreter No comments

Built Customize Vagrant Box

We can make customize box from our vagrant existed box. With this, we can change our environment in existing box and customize it according our need.




Scripting

// In your Vagrant Init file directory
vagrant up
// Get in to your vagrant environment
vagrant ssh

/*
 * Do your custumize in here
 * For example. I will remove my existing ruby version from vagrant box and change it to new one
 */

sudo apt-get update -y

sudo apt-get install build-essential zlib1g-dev libssl-dev libreadline-dev \
git-core curl libyaml-dev libcurl4-dev libsqlite3-dev apache2-dev -y

curl --remote-name http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p194.tar.gz

tar zxf ruby-1.9.3-p194.tar.gz

cd ruby-1.9.3-p194/

./configure

make

sudo make install

// Check if my new ruby version successfully installed
ruby -v

// If succeed quit from vagrant ssh
exit

// Adding your customize box to new box
vagrant package

// Name it
vagrant box add lucid64_with_ruby193 package.box

// Check for your new box
vagrant box list

- lucid32
- lucid64
- lucid64_with_ruby193

// Activate your vagrant 
vagrant init lucid64_with_ruby193





Tuesday, June 23, 2015

Use arsduo/koala in Rails for Facebook Connect

10:44 PM Posted by Codeinterpreter No comments
 Koala is a Facebook library for Ruby, supporting the Graph API (including the batch requests and photo uploads), the REST API, realtime updates, test users, and OAuth validation.

Installation

In Gemfile:
gem "koala", "~> 2.0"
gem 'oauth', '~> 0.4.7'

Never forget to bundle install

Build Callback URL route:
 get '/facebook_callback' => 'facebook#callback', as: :facebook_callback

Facebook Configurations

Get App ID and Secret Key:

  1. Go to https://developers.facebook.com/
  2. In My Apps, add or go to your New App
  3. Get your App ID and App secret

App Configurations

In config/environments/{{your-environments}}  add this line

  ENV["facebook_app_id"] = "{{your-app-id}}"
  ENV["facebook_secret_key"] = "{{your-secret-id}}"
  ENV["facebook_callback"] = "{{your-facebook-callback}}"

REST API With OAUTH

This process will built redirect function to permission page user account in Facebook and return with App Token and App Token Secret. Facebook doesn't recognize localhost with port, if we want to built this connectivity it's better to do it in staging or live servers. Only to get Token and Secret Token Code.
// Connect
facebook_connect = Koala::Facebook::OAuth.new({{your-app-id}},{{your-secret-id}}, {{callback URL}})

// This function will automatically redirecting user to Facebook permission page and redirect it back to your Callback URL
redirect_to facebook_connect.url_for_oauth_code(:permissions => ["publish_actions", "user_posts"])

About Permission can be found in here https://developers.facebook.com/docs/facebook-login/permissions/v2.2

In Return Process built this functions

// Get Token Accces Code
code = facebook.get_access_token(params[:code])

// Get Token Access Secret Code
app_code = facebook.get_app_access_token

// Sample of Get my profile from Facebook
client = Koala::Facebook::API.new(code, {{your -secret-key}})
me = client.get_object("me")

// Save code and app_code to database. This tokens needed for REST API Process

REST API From Facebook Get Status, Profile,etc

Get Status and Profile


// Connect
client = Koala::Facebook::API.new({{ Token Accces }}, {{Token Access Secret}} )
// Get Profile and Feed/Status
facebook_data = client.get_connections("me", "feed", {}, api_version: "v2.0")

Post Status and Comment


// Connect
client = Koala::Facebook::API.new(g{{ Token Accces }}, {{Token Access Secret}})
// Post Status
post_content = client.put_wall_post(params[:description])



Thursday, June 18, 2015

Understanding Rubycritic Smells

9:17 PM Posted by Codeinterpreter No comments
Rubycritic is gem that wraps around static analysis gems such as Reek, Flay and Flog to provide a quality report of your Ruby code.

Because this gem was uses as Audit guidelines code quality in my company, I often faced hard time to adjust, optimizing and refactor my code.

I began to summarize Rubycritic detecting behavior and implement it in my code to avoid Smells and easier get at least Grade C to bare pass.

A few my conclusion things to consider when developing code according Rubycritic :


  1. Don't! Never! Avoid! Duplicity Code. Rubycritic love this think and will give you sudden great high score, enough to drop your Code Rating Grade.
  2. Evade complicated nested logic with multiple if, switch, etc. It's saver to use functions to handle logic rather than nested logic. Fox example

    // Rather than this
     if obj == "a"
       if obj1 == "1" && obj2 == "2"
         // Process
       elsif obj1 == "3" && obj2 == "4"
         // Process
       else
         // Process
       end
     elsif obj1 == "b"
       if obj1 == "1" && obj2 == "2"
         // Process
       elsif obj1 == "3" && obj2 == "4"
         // Process
       else
         // Process
       end
     else
      // Process
     end
    
    // Use this
     if obj == "a"
       process(obj1,obj2)
     elsif obj1 == "b"
       process(obj1,obj2)
     else
      // Process
     end
    
    
  3. Evade complicated nested loops with multiple each, for, etc. It's saver to use functions to handle loops rather than nested loops. Fox example

    // Rather than this
     data_sources.each do |data_source|
      data_source.each do |data|
      end
     end
    
    // Use This
     data_sources.each do |data_source|
      process(data_source)
     end
    
    
  4. If your function using nested hash, redeclare multiple used nested hash using variable.

    // rather than
    if params[:id] == '1'
      user = User.where('id = ?',params[:id])
    end
    
    // Used This
    id = params[:id]
    if id == '1'
      user = User.where('id = ?',id)
    end
    

  5.  To combine Hash uses:  .merge!()

          params_data_assign = {}
          params_data_assign[:password_salt] = BCrypt::Engine.generate_salt
          params_data_assign[:password_hash] = BCrypt::Engine.hash_secret(password, self.password_salt)
          params_data.merge!(params_data_assign)
    


  6. Use method = const_get(method) to change string into Model Constant. (surprisingly isn't it?).

      def myfunction
       my_return = obj == 'User' ? 'User' : 'Member'
       process_my_return(my_return)
      end 
      def process_my_return(my_return)
        method = const_get(my_return)
        data = method.where('id = ?',1)
        // Process
      end
If you have found something more than this or have more effective way. Please, tell us so we can share about this problem more.

Veritrans Rails 4 with dynamic server_key and client_key

1:44 AM Posted by Codeinterpreter No comments
Veritrans is Indonesian Payment Gateway. Veritrans accepts Credit Card, Direct Debit, e-Wallet,Bank Transfer and Convenience Store. That's why this Payment Gateway is famous in Indonesia. Further explanations about Veritrans https://veritrans.co.id/ .

Veritrans has multiple products with different integration method and pricing. About Veritrans Products https://veritrans.co.id/product.html


Veritrans Products:

VT-Link

VT-Link facilitates a payment feature for your online store by redirecting the customer to Veritrans payment page through a link.

VT-Web

VT-Web facilitatess merchant to use Veritrans payment system, by redirecting the customer to the Veritrans payment page.

VT-Direct

VT-Direct is Veritrans product that allows you to use our payment system directly on your website

Integration Tool Kit

  • Rails 4
  • gem veritrans

Configurations

Add gem Veritrans to Gem File and bundle install

    gem 'veritrans';

In Console generate veritrans.yml

rails g veritrans:install

Generate Veritrans Form

rails g veritrans:payment_form

This command will generate controller and view for Veritrans.
Because we will built dynamic key for this integrations. You can keep veritrans.yml configurations like this:

development:
  # Register in sandbox veritrans and get your keys here:
  # https://my.sandbox.veritrans.co.id/settings/config_info
  client_key: ""
  server_key: ""
  api_host: ""

production:
  # Register and get your keys here:
  # https://my.veritrans.co.id/settings/config_info
  client_key: ""
  server_key: ""
  api_host: ""

staging:
  # Register and get your keys here:
  # https://my.veritrans.co.id/settings/config_info
  client_key: ""
  server_key: ""
  api_host: ""

Scripting

VT-Web Integrations

In VT-Web Integrations, you just need to obtain redirect URL to Veritrans . After last check out process, put this function for directing page to veritrans:

@result = Veritrans.charge(
  payment_type: "VTWEB",
  transaction_details: {
    order_id: "order-id",
    gross_amount: 100_000
  }
)
// For Automatically redirect
redirect_to @result.redirect_url

VT-Direct Integrations

VT-Direct Integrations is a little bit complicated because a lot of sensitive data involved in this process.

Preparing The Form

In /views/shared/_credit_card_form   put your last checkout data in here. For example:



<%= form_for @payment, html: {class: "veritrans-payment-form", id:"card_form"} do |f| %>
<% if @settings.client_key.present? && @settings.server_key.present? && @settings.api_host.present? %>
  

Payments Page

<%= render "layouts/notification" %> <%= f.hidden_field :token_id, id:"card_token" %>
<%= label_tag "Length Of Membership" %> <%= number_field_tag :length_of_membership, 1,in: 1..10000 ,size: 5,class:"form-control", id:"length_of_membership",style:"width:10%;float:left;margin-right:10px;" %>
<%= label_tag "Membership Expired" %> <%= text_field_tag :membership_expired, (@company[:membership_expired] + 1.month).strftime('%Y-%m-%d'),size: 5,:readonly => true,class:"form-control", id:"date_expired",style:"width:75%;" %>
<%= f.number_field :amount, id:"gross_amount", size: 25,:readonly => true,class:"form-control",style:"width:75%;" %>
<%= label_tag :credit_card_number %> <%= text_field_tag :credit_card_number, '',:required => true,:placeholder => "4811 1111 1111 1114", name: nil, size: 25,class:"form-control", id:"card_number" %>
<%= label_tag :credit_card_cvv %> <%= text_field_tag :credit_card_cvv, '',:required => true,:placeholder => "123", name: nil,class:"form-control", id:"card_cvc" %>
<%= label_tag :credit_card_expire %> <%= text_field_tag :credit_card_expire, '',:required => true, placeholder: "MM / YY", name: nil,class:"form-control", id:"card_exp" %>
<%= f.label :credit_card_secure, "3D-secure" %> <%= f.check_box :credit_card_secure %>
<%= f.label :notes %> <%= text_area(:notes, :text, class:"form-control", size: "20x30") %>
<%= link_to (image_tag "undo-logo.png", title: :back).html_safe, users_path() %> <%= f.submit "Pay via VT-Direct", class:"btn green-btn" %>
<% else %>
<%= link_to (image_tag "undo-logo.png", title: :back).html_safe, users_path() %>
<% end %> <% end %>

Return Process

In Return Process build this functions

    veritrans_callback = {
      transaction_details: {
        order_id: payment.order_id,
        gross_amount: params[:payment][:amount].presence || @payment.amount
      }
    }
    // Get setting from database
    setting = Setting.first
    // Set key and host for Veritrans
    Veritrans::Config.client_key=(setting.client_key)
    Veritrans::Config.server_key=(setting.server_key)
    Veritrans::Config.api_host=(setting.api_host)

    params[:type] = "Credit Card"
    veritrans_callback[:payment_type] = "credit_card"
    veritrans_callback[:credit_card] = {}
    veritrans_callback[:credit_card][:token_id] = params[:payment][:token_id]
    result = Veritrans.charge(veritrans_callback)

    transaction_params = {}
    transaction_params = {
 order_id:payment.order_id,amounts:result.data[:gross_amount],transaction_status:result.data[:status_message],transaction_id:result.data[:transaction_id],transaction_time:result.data[:transaction_time]
}

    // If Transaction Success
    if result.data[:status_code] == "200"
      // Success Process 
    else
      // Failed Process
    end

That's All. I hope this will help anyone out there. :D



Tuesday, June 16, 2015

Laravel 4 Scheduller with dispatcher

8:31 PM Posted by Codeinterpreter No comments

Dispatcher is a Laravel artisan command scheduling tool used to schedule artisan commands within your project so you don't need to touch your crontab when deploying.

For Futher Information go to this link Dispatcher.


  • Do you hate to touch crontab to add scheduller in laravel?
  • Do you hate with all crontab configuration when add scheduller in different servers?
Congratulations,  Laravel has package to handle this problem using Dispatcher. Everthing become simple and easy with this package. Doubt? Here we go!

Tool Kit

  • PHP 5.3+ or HHVM
  • Laravel 4

Configurations

In your application add this to your "require" :{} composer.json

    "indatus/dispatcher": "1.4.*@dev"

remember to do composer update.
In your app/config/app.php providers array add this line:

'Indatus\Dispatcher\ServiceProvider',

Usage

scheduled
  scheduled:make              Create a new scheduled artisan command
  scheduled:run               Run scheduled commands
  scheduled:summary           View a summary of all scheduled artisan commands

Build scheduled command

php artisan scheduled:make yourCommands

Register scheduled command

In Your app/start/artisan.php add this line depend on Your Command :


Artisan::add(new yourCommands);

Scripting

Go to your command app/command/yourCommands and change 

// my artisan command will be php artisan cron:mycommands
protected $name = 'cron:yourCommands';

// Configure this functions to change schedule time
public function schedule(Schedulable $scheduler)
{
  // Change this function to change time
  return $scheduler->daily();
}

This is Scheduler Changes time function example list:

//every day at 4:17am
return $scheduler->daily()->hours(4)->minutes(17);

//every Monday/Friday at 8:30am
return $scheduler->daysOfTheWeek([
                Scheduler::MONDAY,
                Scheduler::FRIDAY
            ])->hours(8)->minutes(30);

// Using Raw Commands
//every other day at 1:59am, 13:59pm and 23:59pm
return $scheduler->setSchedule(59, [1,13,23], '*/2', '*', '*');

// Every minutes
return $scheduler->everyMinutes();

// Every 20 minutes
return $scheduler->everyMinutes(10);

// Every hours
return $scheduler->everyHours();

Cron Setup

In console add

crontab -e
* * * * * php {{ path to your app}}/artisan scheduled:run 1>> /dev/null 2>&1

Debugging

If your cron not running check this

// Via console, check your mcrypt
php -i | mcrypt.

// Via console
php artisan scheduled:run --debug 
backup:avatars: No schedules were due
     command:name: No schedules were due
     myTestCommand:name: No schedules were due
     cache:clean: /usr/bin/env php /Users/myUser/myApp/artisan cache:clean > /dev/null &
     mail:subscribers: /usr/bin/env php /Users/myUser/myApp/artisan mail:subscribers > /dev/null &

// Via Console
php artisan scheduled:summary
//It works if output something like this:
+----------------+------------------+-----------+--------+------+--------------+-------+-------------+--------+
| Environment(s) | Name             | Args/Opts | Minute | Hour | Day of Month | Month | Day of Week | Run as |
+----------------+------------------+-----------+--------+------+--------------+-------+-------------+--------+
| *              | schedule:test    |           | */5    | *    | *            | *     | *           |        |
+----------------+------------------+-----------+--------+------+--------------+-------+-------------+--------+

Sunday, June 14, 2015

Laravel 4 Queue with Beanstalk and Supervisor

9:06 PM Posted by Codeinterpreter No comments


Queue  is great tools in laravel for implementing delayed job. Queue allowing system to put task in background so it can become faster and make users skip waiting until tasks is finished.
Queue can be implemented to handle big process such as generating reports, image processing, sending email, or even heavy CRUD process.

Tool Kit

Configuration

Installing Queue

In your application add this to your "require" :{} composer.json

    "pda/pheanstalk": "2.0.*"

Scripting

You can create new class or use controller/model/any class to execute function with Queue. Below is function in controller class executed by Queue.

<?php

class ReportsController extends \BaseController {
  function fire($job,$data){
    //Function Process
  }
}

To execute this method with queue use this command

Queue::push('ReportsController', $data);

Other alternative is to execute function without fire method

<?php

class ReportsController extends \BaseController {
  function generateReport($job,$data){
    //Function Process
  }
}

To execute this method with queue use this command

Queue::push('ReportsController@generateReport', $data);

Queue::push() command can be use in Route, Controller, or even Command.

Running Queue

To running Queue we need Beanstalk as a worker. To activate beanstalk running this command in console

  // To fire last job
  php artisan queue:work

  // To fire running job and listen it
  php artisan queue:listen

  // add listener with flag (you can choose or implement all of this)
  php artisan queue:work --timeout=0 --queue="default" --delay=0 --memory=128 --sleep=3 --tries=0

Install and Configure Beanstalk

Install Beanstalk

sudo apt-get update
// Install in Debian or ubuntu
sudo apt-get install beanstalkd

Configure Beanstalk

sudo nano /etc/default/beanstalkd

// Add or uncomment this line
START yes

Start Beanstalk
sudo service beanstalkd start

Configure Beanstalk in Our Laravel App

Set default queue in app to Beanstalk. Go to app/config/queue.php

// Change This
'default' => 'beanstalkd',

// This is default beanstalk configurations
'connections' => array(

    'beanstalkd' => array(
        'driver' => 'beanstalkd',
        'host'   => 'localhost', 
        'queue'  => 'default',
        'ttr'    => 60,
    ),

),

Supervisor

We use php artisan queue:work or php artisan queue:work as listener, but we know that impossible for us to running this command every time we push job to Queue or when we start servers.

To overcome this we use Supervisor to listen all of active worker. Supervisor will listen all of our queue:work --daemon and restart it if failed.

Install Supervisor


// Install Supervisor in Debian or ubuntu
sudo apt-get install supervisor

// Adding configurations
sudo nano /etc/supervisor/conf.d/reportqueue.conf

[program:reportqueue]
command=php artisan queue:work --daemon --env=your_environment
directory=/path/to/MYAPP
stdout_logfile=/path/to/MYAPP/app/storage/logs/myqueue_supervisord.log
redirect_stderr=true
autostart=true
autorestart=true

Add Configuration to Supervisor


sudo supervisorctl
reread # Tell supervisord to check for new items in /etc/supervisor/conf.d/
add reportqueue       # Add reportqueue process to Supervisord
start reportqueue     # Let's Rock

Check Supervisor


// In Console
ps aux | grep php

# You should see some output similarish this:
php artisan queue:work --daemon --env=your_environment
sh -c php artisan queue:work  --queue="default" --delay=0 --memory=128 --sleep --env=your_environment
php artisan queue:work --queue=default --delay=0 --memory=128 --sleep --env=your_environment