Skip to content

Writting rake task

Lib/tasks/mytask.rake

require "haml/html"

namespace :html2haml do
desc “convert your erb to haml”
task :convert => :environment do
Dir[“#{Rails.root}/app/views/**/*.erb”].each do |file_name|

haml_file_name = file_name.gsub(/erb$/,”haml”)
puts “Converting: #{file_name} to #{haml_file_name}”
if !File.exist?(haml_file_name)
erb_string = File.open(file_name).read
haml_string = Haml::HTML.new(erb_string, :erb => true).render
f = File.open(haml_file_name, “w”)
f.write haml_string
end
end
end

desc “disable erb support for rails”
task :disable_erb => :environment do
Dir[“#{Rails.root}/app/views/**/*.erb”].each do |file_name|
backup_file = file_name.gsub(/erb$/,”erb_backup”)
puts “backing up the #{file_name} to #{backup_file}”
system(“mv #{file_name} #{backup_file} “)
end
end

desc “clean”
task :clean => :environment do
Dir[“#{Rails.root}/app/views/**/*.erb”].each do |file_name|

puts “destroying : #{file_name}”
File.delete(file_name)
end
end

desc “rollback erb support”
task :enable_erb => :environment do
Dir[“#{Rails.root}/app/views/**/*.erb_backup”].each do |file_name|
erb_file = file_name.gsub(/erb_backup$/,”erb”)
puts “backing up the #{file_name} to #{erb_file}”
system(“mv #{file_name} #{erb_file} “)
end
end
end

 

Advertisements

PHP console application – How to get input from console

IO stream in php :

$inputs = fgets(STDIN);
echo “\n Your input was: {$inputs} ” ;

Yii bindParam error with CDbCommand failed to execute the SQL statement: SQLSTATE[23000]: Integrity constraint violation: 1048 Column

I have a project to import data to mysql. When I use $command->bindParam every field did not seem to be set with the value passed appropriately inside the foreach loop . It takes me sometime to figure out the issue. After checking the yii function references  I got the point . CDbCommand::bindParam signature below :

public CDbCommand bindParam(mixed $name, mixed &$value, integer $dataType=NULL, integer $length=NULL, mixed $driverOptions=NULL)

The second param is the value of the variable to be bound to. It must be passed by reference.

for example:

$sql = ” INSERT INTO city (name, code) VALUES(:name, :code) “;

$command = Yii::app()->db->createCommand(|$sql);

I came up with 2 cases :

case 1:

$command->bindParam(“:name”, “Phnompenh”); // is wrong because constant is passed.

$command->bindParam(“:code”, “855”); // is wrong because constant is passed.

case 2:

$cols = array(“name” => “phnompenh”, “code” => “855”);

foreach($cols as $col =>  $value) {

$command->bindParam(“:{$col}”, $value); // is wrong coz $value is not permitted to  be changed in PHP

}

The right way to do it is:

case 1

$name = “phnom penh”;

$code = ” 855″;

…..

$command->bindParam(“:name”, $name);

$command->bindParam(“:code”, $code);

case 2

foreach($cols as $col =>  &$value){ // $value can be changed by the body of foreach loop.

$command->bindParam(“:{$col}”, $value);

}

public CDbCommand bindParam(mixed $name, mixed &$value, integer $dataType=NULL, integer $length=NULL, mixed $driverOptions=NULL)

How to remove Blekko search from my browser

Googling happens alot in my day to day job. Today when I searched for sth in google I got results comming up with Blekko in a way that I am not familiar with.  I got very annoyed with Blekko search result. To get rid of this I had tried many alternatives by going add-on window and removed all un-known add-ons, extensions, plugins,  but no positive result. Then the last option for me to try was to go to clean application data manually.

  • Close your browser
  • Go to C:\Documents and Settings\[your-user]\Application Data\Mozilla\Extensions\. Remove everything inside this folder.
  • Start your browser and try to search. Blekko gone.

Removing everything under C:\Documents and Settings\[your-user]\Application Data\Mozilla\Extensions\         folder   you would loss  your data.
Cleaning the C:\Documents and Settings\[your-user]\Application Data\Mozilla\Extensions\  is not the best solution. but I could not find any other and my time boxing was done So  I chose to do it this way.

If you have the same problem with Blekko and get a better solution please let me know.

 

Phpunit pear channel

PHPUnit PEAR Channel

Registeringthe channel:

pear channel-discover pear.phpunit.de

Listingavailable packages:

pear remote-list -c phpunit

Installinga package:

pear install phpunit/package_name

Installinga specific version/stability:

pear install phpunit/package_name-1.0.0 
pear install phpunit/package_name-beta

Fatal error: Uncaught exception ‘PHPUnit_Framework_Exception’ with message ‘Neither “unit\.php” nor “unit\.php” could be opened

When trying to run :  phpunit unit/  I’ ve got this error :

Fatal error: Uncaught exception ‘PHPUnit_Framework_Exception’ with message ‘Neither “unit\.php” nor “unit\.php” could be opened. After trying many different alternatives I realize that that there is nothing inside the unit/

list of column type in yii migration

The following was extract from the yii CDbSchema::getColumnType. It maps the string value defined in yii migration.

  • pk: an auto-incremental primary key type, will be converted into “int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY”
  • string: string type, will be converted into “varchar(255)”
  • text: a long string type, will be converted into “text”
  • integer: integer type, will be converted into “int(11)”
  • boolean: boolean type, will be converted into “tinyint(1)”
  • float: float number type, will be converted into “float”
  • decimal: decimal number type, will be converted into “decimal”
  • datetime: datetime type, will be converted into “datetime”
  • timestamp: timestamp type, will be converted into “timestamp”
  • time: time type, will be converted into “time”
  • date: date type, will be converted into “date”
  • binary: binary data type, will be converted into “blob”

To create migration:   yiic migrate create target_db_operation

To run migration:  yiic migrate

Note:  you need to configure db connection in  config/console.php.

 

Backup and restoring mssql database with php

Requirement:

mssql sql driver for php enable. In my case I use php_sqlsrv_52_ts_vc6.dll from microsoft with php 5.2 thread safe enabled. for more information for a specific version visit http://sqlsrvphp.codeplex.com/. I don’t use mssql and pdo_mssql driver that comes by default with php 5.2.

Note with bug

The pdo versions(both from php_mssql and php_pdo_sqlsrv) just don’t work. I have tried it.  When restoring database, I ran into a bug with mssql server stack in restoring state.

Code

//ch_debug.php
 <?php
define('CH_TEST', 0) ; // possible value 0,1
define("CH_DEBUG",1) ;
function ch_debug($var,$exit=false,$configable=true){
    $templates[] = <<<EOT
        <div style='text-align:left;border-top:1px solid #ccc;background-color:white;color:black;overflow:auto;' >
            <pre>
                <br /> <strong> line : </strong> {line}
                <br /> <strong> file : </strong> {file}
                <br /> {data}
            </pre>
        </div>
EOT;

    $templates[]= <<<EOT
        \n
        -------------------------------debug ---------------------------
        line : {line}, file : {file}
        output: ->
        {data}
        ----------------------------------------------------------------
        \n\r
EOT;

    if(CH_DEBUG || $exit==true){
        $debug_traces = debug_backtrace();
        $debug_trace=$debug_traces[0];

        $str = strtr($templates[CH_TEST],
            array( "{line}"=>"{$debug_trace['line']}",
                    "{file}" => "{$debug_trace['file']}",
                    "{data}"=> print_r($var, true) //debug_trace['args'][0]
                 ));
        echo $str ;
        if($exit==true)
            exit;
    }
}
//config.php
<?php

    $connOptions = array("Database"=>"master", "UID"=>"sa", "PWD"=>"123456");
    $conn = sqlsrv_connect("WORK-MSSQL", $connOptions); 

    sqlsrv_configure( "WarningsReturnAsErrors", 0 );
    $backup_file = "c:\\backup\\test.bak" ;
 //backup.php
<?php
    require 'ch_debug.php';
    require 'config.php';
    $log_backup_file= "c:\\backup\\last-test-log.bak" ;

    $sql = "BACKUP DATABASE test TO DISK = '$backup_file' ";

    ch_debug($sql);

    $stmt = sqlsrv_query($conn, $sql);

    if($stmt === false)
        ch_debug(sqlsrv_errors());

    else
        ch_debug("Database backed up to $backup_file <br>");

    //Backup log. Put DB into "Restoring..." state.
    $sql = "BACKUP LOG TestDB TO DISK = '$log_backup_file' WITH NORECOVERY";
    ch_debug($sql);
    $stmt = sqlsrv_query($conn, $sql);
    if($stmt === false)
        ch_debug(print_r(sqlsrv_errors()));
    else
        ch_debug( "Transaction log backed up to $log_backup_file");

//restore.php
<?php

    require 'ch_debug.php';
    require 'config.php';

    $sql = "RESTORE DATABASE test FROM DISK = '$backup_file' WITH RECOVERY";
    ch_debug($sql);
    $stmt = sqlsrv_query($conn, $sql);
    if($stmt === false)
        ch_debug(print_r(sqlsrv_errors()));
    else
        ch_debug( "Database restored from $backup_file</br>" );

    //Put DB into usable state.
    $sql = "USE test";
    ch_debug($sql);

    $stmt = sqlsrv_query($conn, $sql);

    if($stmt === false)
        ch_debug(print_r(sqlsrv_errors()));
    else
        ch_debug("Using TestDB</br>");

For more information visit http://blogs.msdn.com/b/brian_swan/archive/2010/07/01/restoring-a-sql-server-database-from-php.aspx

Pretty debug output message in Php (console and html mode)

define('CH_TEST', 0) ; // possible value 0,1
define("CH_DEBUG",1) ;
function ch_debug($var,$exit=false,$configable=true){
$templates[] = <<<EOT
<div style='text-align:left;border-top:1px solid #ccc;background-color:white;color:black;overflow:auto;' >
<pre>
<br /> <strong> line : </strong> {line}
<br /> <strong> file : </strong> {file}
<br /> {data}
</pre>
</div>
EOT;
$templates[]= <<<EOT
\n
-------------------------------debug ---------------------------
line : {line}, file : {file}
output: ->
{data}
----------------------------------------------------------------
\n\r
EOT;

if(CH_DEBUG || $exit==true)
{
$debug_traces = debug_backtrace();
$debug_trace=$debug_traces[0];

$str = strtr($templates[CH_TEST],
array( "{line}"=>"{$debug_trace['line']}",
"{file}" => "{$debug_trace['file']}",
"{data}"=> print_r($var, true) //debug_trace['args'][0]
));
echo $str ;
if($exit==true)
exit;
}
}

Using Monit to monitor delayed_job in Rails 3

I am developing an application using RubyonRails3 . My application need to send alert notification , reminder via sms , email to hundreds of users. To make my application responsive I have to do these tasks in the background process. After exploring many alternatives I see that delayed_job fits my needs.  Delayed_job run a separate process with my rails app.

Delayed Job workers generally have a lifecycle that is equivalent to an application deployment.Because of this, their memory consumption grows over time and may eventually have high swapusage, causing workers to become unresponsive so  I  decide to use a monitoring tool Monit to watch  jobs. Monit can restart them when their memory usage hits a certain point. The good thing I like from monit is when a pre defined condition is matched, Monit can alert my for example by email by telling us what happen so I can take action accordingly.

I am using Ruby 1.9.2, rvm 1.8.6 , rails 3.07 on Ubuntu 10.10.

my application is located at : /var/www/rails3

/var/www/rails/.rvmrc file contains the following content:

rvm use 1.9.2@dyrm --create

Include the following line in you /var/www/rails3/Gemfile

gem "delayed_job"

Then to install delayed_job gem, in your terminal type:

/var/www/rails3$    bundle install

then

/var/www/rails3$ rails g delayed_job
/var/www/rails3$ rake db:migrate
#inserting job in my delayed_job
def self.alert notification
    notification.users.each do |user|
      Delayed::Job.enqueue(EmailJob.new(user, message)) unless user.email.blank?
      Delayed::Job.enqueue(SmsJob.new(user, message)) unless user.phone_number.blank?
    end
  end

My Email job:

  class EmailJob
  def initialize user, message
    @user = user
    @message = message
  end

  def perform
    UserMailer.notify_members(@user, @message).deliver
  end
end
  class SmsJob
  def initialize user, message
    @user = user
    @message = message
  end

  def perform
    Sms.send do |sms|
      sms.to = @user.phone_number
      sms.body = @message
    end
  end
end

To be able to puts your job into delayed_job, you job objects need to response to perform method. because perform method does not require any parameter so I need to pass through the constructor .

Installing Monit

In your terminal :

sudo apt-get install monit

configure monit to start up as daemon by editing the file /etc/default/monit with:

startup=1

Then start the daemon with:

sudo /etc/init.d/monit start

In my case I need to edit file

Some time the monit daemon does not start, however the output from terminal console

telling us the service  already started. I find the command:

sudo monit summary

is very useful to debug this. After all edit the file /etc/monit/monitrc

set alert channa@instedd.org

to set the alert for monit to alert to.

set httpd port 2812 and
#    use address localhost  # only accept connection from localhost
     allow localhost        # allow localhost to connect to the server and
     allow admin:monit      # require user 'admin' with password 'monit'
#    allow @monit           # allow users of group 'monit' to connect (rw)
#    allow @users readonly  # allow users of group 'users' to connect readonly

Use web user interface to monitor my process(on port 2812). Monit comes bundled with a web server using http basic auth.
allow admin:monit to login to web ui with user equal to admin and password monit

include /etc/monit/conf.d/*

I include all my monit script located in side folder: /etc/monit/conf.d

Create a file called notification inside /etc/monit/conf.d. It’s name is not important at all.

check process delayed_job
      with pidfile /var/www/rails/tmp/pids/delayed_job.pid
      stop program  = "/usr/bin/env RAILS_ENV=production  BUNDLE_GEMFILE=/var/www/rails/Gemfile /home/chenseng/.rvm/bin/bundle-ruby-1.9.2-p290@dyrm exec /var/www/rails/script/delayed_job stop"
      start program = "/usr/bin/env RAILS_ENV=production  BUNDLE_GEMFILE=/var/www/rails/Gemfile /home/my_user/.rvm/bin/bundle-ruby-1.9.2-p290@dyrm exec /var/www/rails/script/delayed_job start" 

      if totalmem > 60 MB for 3 cycles then restart
      if cpu usage > 50% for 3 cycles then restart

Here we use rvm wrapper to run delayed_job from a monit process. rvm wrapper give us ability to run any ruby script in context of it’s gemset without cd to it’s own directory.

Create wrapper

   /var/www/rails$ rvm wrapper 1.9.2@dyrm "" bundle

this will create /home/my_user/.rvm/bin/bundle-ruby-1.9.2-p290@dyrm executable.

Debug

Before making sure that monit can start my delayed_job process correctly, I try to run delayed_job with my rvm wrapper independently.
In terminal cd to your home directory:
/home/my_user$ /usr/bin/env RAILS_ENV=production BUNDLE_GEMFILE=/var/www/rails/Gemfile /home/my_user/.rvm/bin/bundle-ruby-1.9.2-p290@dyrm exec /var/www/rails/script/delayed_job start

check the output if nothing go wrong then it is time to restart my monit:

  /home/my_app$ sudo monit stop all
  /home/my_app$ sudo /etc/init.d/monit/restart
  /home/my_app$ sudo monit start all
  /home/my_app$ sudo monit summary

It is quite helpful to check if my monit config files are correctly written with the correct permission. To do this
sudo monit -c /etc/monit/monitrc
sudo monit -c /etc/monit/conf.d/notification

Web interface:

http://localhost:2832