May01

Skenarionya begini, katakanlah kita mempunyai 3 tabel, sellers, products dan orders, relasi antar tabelnya di definisikan di setiap model sebagai berikut :

file : app/models/seller.rb
	
class Seller < ActiveRecord::Base
  has_many :products
end
	
file : app/models/product.rb
	
class Product < ActiveRecord::Base
   belongs_to :seller
   has_many :orders
end
	
file : app/models/order.rb
	
class Order < ActiveRecord::Base
   belongs_to :product
end

nah suatu saat, kita ingin menampilkan data-data pesanan beserta nama penjualnya, di controller kita definisikan seperti ini :

def index
  @orders = Order.find(:all)
end

lalu di view kita menulis seperti ini

	
< % @orders.each do |order| -%>
   Order  Date : < %= order.created_at %> <br />
   Product Name : < %= order.product.name %> <br />
   Seller Name : < %= order.product.seller.name %> <br />
   <hr />
< % end %>
	

lalu, ketika anda refresh browser, data pun sudah bisa ditampilkan seperti yang kita inginkan, namun apabila kita cermati isi log, kode seperti ini akan memakan resource memory, karena query dieksekusi lebih dari 1 kali, semakin banyak orders semakin banyak pula query dieksekusi

nah, pertanyaanya bagaimana caranya untuk mengoptimasi proses ini ?, bisa tidak sebanyak apapun jumlah order-nya, query hanya dieksekusi satu kali saja, solusinya telah saya tulis pada judul di atas, menggunakan include bersarang, caranya, method index pada controller diubah menjadi seperti ini

def index
  @orders = Order.find(:all,:include => [{:product=>:seller}])
end

VOILA !!!, silahkan refresh browser, lalu cek log, querypun hanya akan dieksekusi sekali saja

Apr02

Hal-hal di bawah ini adalah cara saya mempraktekan DRY (don’t repeat yourself) di Ruby on Rails

  • pertama, pertimbangkan untuk menyimpan kode di model
  • kedua, pertimbangkan lagi untuk menyimpan kode di model
  • ketiga, pertimbangkan lagi untuk menyimpan kode di model
  • kelima, kalo benar-benar nggak bisa, pertimbangkan tuk disimpan sebagai render partial
  • keenam, kalo gak bisa dijadikan render partial pertimbangkan tuk disimpen di helper
  • ketujuh, kalo nggak bisa disimpan di helper silahkan simpan di controller

Tambahan, ada 2 hal lagi tempat penyimpanan kode yang khusus di Ruby on Rails, di lib dan vendor directory, jika anda ingin membuat fungsi spesifik yang bisa tersedia di semua model atau controller atau view, anda bisa membuat module atau class dibawah directory lib, nah module atau class ini nantinya bisa anda include-kan di Controller, Model atau Helper sesuai dengan keinginan anda

Dan bilamana anda merasa lib tersebut layak dipublikasikan kepada umum, anda juga bisa mendistribusikannya sebagai ruby on rails plugin atau rubygem yang nantinya bisa disimpan di directory vendor

Jadi, begitulah cara saya mempraktekan konsep DRY secara praktis, tentang teorinya dan mengapa harus begitu silahkan cari saja artikelnya banyak bertebaran di internet

Oct27

Nginx (baca : Engine-X) adalah web server buatan Igor Sysoev, seorang Rusia, digunakan sebagai alternatif dari Apache Web Server, salah satu keunggulan yang menarik dari nginx adalah, nginx relatif lebih kecil dalam memakan resource memory ketimbang Apache, nginx juga sangat cepat dalam menangani file statis (javascript, html, image , css file). Di dunia Rails, nginx seringkali digunakan dalam mode production sebagai Frontend Web Server/Load Balancer

Di artikel ini saya akan mencoba menuliskan bagaimana cara untuk mengcompile,menginstall, mengkonfigurasi dan menjadikan nginx sbg web server untuk Aplikasi Ruby on Rails yang sudah support dengan SSL di Fedora 9/CentOS 5

Install SSL dan PCRE

yum install pcre pcre-devel openssl openssl-devel

Download nginx 0.6.2 (versi Stable terakhir)

wget http://sysoev.ru/nginx/nginx-0.6.32.tar.gz

Ekstrak, konfigurasi, compile lalu install

tar -xzf nginx-0.6.32.tar.gz
cd nginx-0.6.32
./configure –with-http_ssl_module –with-http_dav_module
make
sudo make install

setelah itu kita perlu generate SSL key, supaya situs kita support protokol https

openssl genrsa -des3 -out server.key 1024 #akan menghasilkan server.key

command di atas akan menanyakan passphrase, jangan lupa untuk mengingat passphrase ini

openssl req -new -key server.key -out server.csr

comand tsb akan akan menghasilkan server.csr dengan sebelumnya menanyakan bbrp pertanyaan spt ini

Country Name (2 letter code) [GB]:IN
State or Province Name (full name) [Berkshire]:Cihanjuang
Locality Name (eg, city) [Newbury]:Bandung
Organization Name (eg, company) [My Company Ltd]:Prawirasoft
Organizational Unit Name (eg, section) []:IT
Common Name (eg, your name or your server’s hostname) []:Prawirasoft.com
Email Address []:contoh@contoh.com

lalu terakhir, generate file crt

openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

copy ketiga file di atas ke direktori tempat konfigurasi nginx berada

sudo cp server* /usr/local/nginx/conf/

setelah itu kita mesti konfigurasi beberapa setting nginx, di bawah ini adalah konfigurasi umum bagaimana nginx yang support ssl bekerja, referensi dasar berasal dari konfigurasi yang dibuat oleh akang Ezra Zygmuntowicz

Buka file /usr/local/nginx/conf/nginx.conf dengan editor kesayangan anda sebagai super user/sudoers, lalu masukan konfigurasi dibawah ini lalu save (sebaiknya melakukan backup terlebih dahulu)

#user  nobody;
worker_processes  2; #jumlah nginx instance
	
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
	
#pid        logs/nginx.pid;
	
events {
    worker_connections  1024;
}
	
http {
    include       mime.types;
    default_type  application/octet-stream;
	
    #log_format  main  '$remote_addr - $remote_user [$time_local] $request '
    #                  '\"$status\" $body_bytes_sent \"$http_referer\" '
    #                  '\"$http_user_agent\" \"$http_x_forwarded_for\"';
	
    #access_log  logs/access.log  main;
	
    sendfile        on;
	
    #keepalive_timeout  0;
    keepalive_timeout  65;
	
   # These are good default values.
    tcp_nopush        on;
    tcp_nodelay       off;
	
    # output compression saves bandwidth
    gzip            on;
    gzip_http_version 1.0;
    gzip_comp_level 2;
    gzip_proxied any;
    gzip_types      text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;
	
    # this is where you define your mongrel clusters.
    # you need one of these blocks for each cluster
    # and each one needs its own name to refer to it later.
    upstream thin {
      server 127.0.0.1:3001; #port di mana server backend anda running, bisa lebih dari satu server+port, bisa memakai thin atau mongrel web server
    }
	
    # the server directive is nginx's virtual host directive.
    server {
      # port to listen on. Can also be set to an IP:PORT
      listen 80;
	
      # Set the max size for file uploads to 50Mb
      client_max_body_size 50M;
	
      # sets the domain[s] that this vhost server requests for
      server_name prawirasoft.com www.prawirasoft.com; #nama domain anda, ubah sesuai dengan kebutuhan
	
      # doc root
      root /home/aditya/webapp/prawirasoft/trunk/public; #public RAILS_ROOT, direktory public di mana file2 statis aplikasi rails berada
	
      # vhost specific access log
      access_log  /var/log/nginx.vhost.access.log ;
	
     # this rewrites all the requests to the maintenance.html
     # page if it exists in the doc root. This is for capistrano's
     # disable web task
     if (-f $document_root/system/maintenance.html) {
       rewrite  ^(.*)$  /system/maintenance.html last;
       break;
     }
	
     location / {
       # needed to forward user's IP address to rails
       proxy_set_header  X-Real-IP  $remote_addr;
	
       # needed for HTTPS
       proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header Host $http_host;
       proxy_redirect false;
       proxy_max_temp_file_size 0;
	
       # If the file exists as a static file serve it directly without
       # running all the other rewite tests on it
       if (-f $request_filename) {
         break;
       }
	
       # check for index.html for directory index
       # if its there on the filesystem then rewite
       # the url to add /index.html to the end of it
       # and then break to send it to the next config rules.
       if (-f $request_filename/index.html) {
         rewrite (.*) $1/index.html break;
       }
	
      # this is the meat of the rails page caching config
      # it adds .html to the end of the url and then checks
      # the filesystem for that file. If it exists, then we
      # rewite the url to have explicit .html on the end
      # and then send it on its way to the next config rule.
      # if there is no file on the fs then it sets all the
      # necessary headers and proxies to our upstream mongrels
      if (-f $request_filename.html) {
        rewrite (.*) $1.html break;
      }
	
      if (!-f $request_filename) {
        proxy_pass http://thin;
        break;
      }
    }
	
      error_page   500 502 503 504  /500.html;
      location = /500.html {
        root   /home/aditya/webapp/prawirasoft/trunk/public; #public RAILS_ROOT, direktory public di mana file2 statis aplikasi rails berada
      }
    }
	
    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;
	
    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}
	
    # HTTPS server
    #
      # This server is setup for ssl. Uncomment if
  # you are using ssl as well as port 80.
  server {
    # port to listen on. Can also be set to an IP:PORT
    listen 443;
	
    # Set the max size for file uploads to 50Mb
    client_max_body_size 50M;
	
    # sets the domain[s] that this vhost server requests for
    server_name prawirasoft.com www.prawirasoft.com; ## nama host, ubah sesuai kebutuhan
	
    # doc root
    root /home/aditya/webapp/prawirasoft/trunk/public; #public RAILS_ROOT, direktory public di mana file2 statis aplikasi rails berada
	
    ssl on;
	
    # path to ssl cert
    ssl_certificate server.crt;
    # path to ssl key
    ssl_certificate_key server.key;
	
    # vhost specific access log
    # access_log  /var/log/nginx.vhost.access.log  main;
	
    # this rewrites all the requests to the maintenance.html
    # page if it exists in the doc root. This is for capistrano's
    # disable web task
    if (-f $document_root/system/maintenance.html) {
      rewrite  ^(.*)$  /system/maintenance.html last;
      break;
    }
	
    location / {
      # needed to forward user's IP address to rails
      proxy_set_header  X-Real-IP  $remote_addr;
	
      # needed for HTTPS
      proxy_set_header X_FORWARDED_PROTO https;
	
      proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_redirect false;
      proxy_max_temp_file_size 0;
	
      # If the file exists as a static file serve it directly without
      # running all the other rewite tests on it
      if (-f $request_filename) {
        break;
      }
	
      # check for index.html for directory index
      # if its there on the filesystem then rewite
      # the url to add /index.html to the end of it
      # and then break to send it to the next config rules.
      if (-f $request_filename/index.html) {
        rewrite (.*) $1/index.html break;
      }
	
      # this is the meat of the rails page caching config
      # it adds .html to the end of the url and then checks
      # the filesystem for that file. If it exists, then we
      # rewite the url to have explicit .html on the end
      # and then send it on its way to the next config rule.
      # if there is no file on the fs then it sets all the
      # necessary headers and proxies to our upstream mongrels
      if (-f $request_filename.html) {
        rewrite (.*) $1.html break;
      }
	
      if (!-f $request_filename) {
        proxy_pass http://thin;
        break;
      }
    }
	
    error_page   500 502 503 504  /500.html;
    location = /500.html {
      root   /home/aditya/webapp/prawirasoft/trunk/public;
    }
  }
	
}

setelah itu pastikan port 80,445 dan 3001 kosong, port 80 dan 445 biasanya dipakai oleh web server apache, oleh karena itu sebaiknya matikan apache-nya dulu, (atau kalou mau, pastikan apachenya ganti port - tapi kalo saya, melakukan hal ini lum pernah berhasil he he)

matikan apache

sudo /sbin/service httpd stop

setelah itu test apakah konfigurasi nginx-nya sudah benar

sudo /usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf

konfigurasi yang benar akan memunculkan pesan seperti ini

Enter PEM pass phrase:
2008/10/27 01:07:33 [info] 14294#0: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
2008/10/27 01:07:33 [info] 14294#0: the configuration file /usr/local/nginx/conf/nginx.conf was tested successfully

setelah itu, silahkan nyalakan nginx-nya

sudo /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

lalu, yang terakhir, nyalakan backend servernya di port 3001 (saya memakai thin), masuk ke direktory RAILS_ROOT, dalam kasus saya berada terletak di /home/aditya/webapp/prawirasoft/trunk/ lalu ketik

thin start -p 3001 -d

lebih lanjut tentang thin bisa dilihat juga di sini

tunggu selama 10-20 detik supaya thin selesai loading, lalu buka browser dan masukan url host yang tadi telah dimasukan ke file konfogurasi nginx, dalam kasus saya ke http://www.prawirasoft.com atau https://www.prawirasoft.com