Pages

12/13/2012

Ruby's Symbol-To-Proc

Here is how symbol-To-Proc works, explained in reduction steps.

First, I'll just create a variable 'words' as an array of strings, so we can have something to work with.
words = %w{test hello world}

Starts to use this symbol, '&' = symbol-to-proc
words.map(&:upcase)

'&' is symbol-to-proc character, which means it interprets the following symbol(':upcase') with .to_proc()
words.map(&:upcase.to_proc)

If you look into the source code of Symbol.to_proc ('to_proc' method in 'Symbol' class), you'll find it returns something like this back.
words.map(&proc{|obj,*args| obj.send(:upcase,*args)})

Then, '&' convert the proc into a block (notice the braces).
words.map{|obj,*args| obj.send(:upcase,*args)}

Since, '.map' only provides one argument for a block. The *args is neglected.
words.map{|obj| obj.send(:upcase)}

'.send' is similarly called directly with the symbol.
words.map{|obj| obj.upcase}

The result is
=> ["TEST", "WORLD", "HELLO"]

Now, let's try it with a method with 2 arguments, such as '.inject'

Here are the normal ways that we can write inject with.
(1..10).inject(:+)  #only with Ruby 1.9
(1..10).inject(&:+)
(1..10).inject(0,:+)  #only with Ruby 1.9
(1..10).inject(0,&:+)
(1..10).inject{|result,element| result+element}
(1..10).inject(0){|result,element| result+element}
*whereas 0 is initial value of the summation

Now, the reduction of the '.inject'.

Starting from the basic one.
(1..10).inject(&:+)

with Symbol-to-proc, it interprets this symbol (':+') as it is a proc (or called with .to_proc)
(1..10).inject(&:+.to_proc)

What .to_proc does with a symbol is
(1..10).inject(&proc{|obj,*args| obj.send(:+,*args)})

Then, this proc becomes a block for .inject
(1..10).inject{|obj,*args| obj.send(:+,*args)}

Since '.inject' can have a block that takes 2 arguments, I'll rename the arguments as
(1..10).inject{|result,element| result.send(:+,element)}

So then, '.send' can be substituted with a direct call
(1..10).inject{|result,element| result.+(element)}

Or with out using dot (only for operators)
(1..10).inject{|result,element| result + element}

Finally, the result is
=> 55

** remark: every code line is syntactically correct.

Suggest For Further Watching/Readings:
 - http://www.youtube.com/watch?v=aISNtCAZlMg
 - http://phrogz.net/symbol-to-proc-with-multiple-arguments
 - http://www.potstuck.com/2011/08/06/ruby-symbols-instead-of-blocks/

12/12/2012

Comparing TDD/BDD Framework for PHP

Comparing TDD/BDD Framework for PHP
 - TDD = Test Driven Development
 - BDD = Behavior Driven Development

This comparison focusing on unit-testing (testing at class/method level).
Browser integration feature is not in this scope

Type PHPUnit PHPUnit-Story PHPSpec PHPSpec2 Spectrum
Syntax
assertEquals('word', $wrapper->wrap('word', 5));
	$this->given('New game')
	     ->when('Player rolls', 5)
	     ->and('Player rolls', 5)
	     ->and('Player rolls', 3)
	     ->then('Score should be', 16);

	but actually use this internally:
		$this->assertEquals($arguments[0], $world['game']->score());
$this->spec($this->_bowling->score)->should->equal(0);
$this->getPayment()->getType()->shouldReturn(“visa”);
verify($person->firstName, '==', 'Bob');
Example Code Block from http://www.phpunit.de/manual/3.3/en/phpunit-book.html Example 13.1
<?php
require_once 'PHPUnit/Framework.php';
require_once 'BankAccount.php';
 
class BankAccountTest extends PHPUnit_Framework_TestCase
{
    protected $ba;
 
    protected function setUp()
    {
        $this->ba = new BankAccount;
    }
 
    public function testBalanceIsInitiallyZero()
    {
        $this->assertEquals(0, $this->ba->getBalance());
    }
 
    public function testBalanceCannotBecomeNegative()
    {
        try {
            $this->ba->withdrawMoney(1);
        }
 
        catch (BankAccountException $e) {
            $this->assertEquals(0, $this->ba->getBalance());
 
            return;
        }
 
        $this->fail();
    }
 
    public function testBalanceCannotBecomeNegative2()
    {
        try {
            $this->ba->depositMoney(-1);
        }
 
        catch (BankAccountException $e) {
            $this->assertEquals(0, $this->ba->getBalance());
 
            return;
        }
 
        $this->fail();
    }
}
?>
from http://sebastian-bergmann.de/archives/738-Support-for-BDD-and-Stories-in-PHPUnit-3.3.html
<?php
require_once 'PHPUnit/Extensions/Story/TestCase.php';
 
require_once 'BowlingGame.php';
 
class BowlingGameSpec extends PHPUnit_Extensions_Story_TestCase
{
    /**
     * @scenario
     */
    public function scoreForOneSpareIs16()
    {
        $this->given('New game')
             ->when('Player rolls', 5)
             ->and('Player rolls', 5)
             ->and('Player rolls', 3)
             ->then('Score should be', 16);
    }
 
    public function runGiven(&$world, $action, $arguments)
    {
        switch($action) {
            case 'New game': {
                $world['game']  = new BowlingGame;
                $world['rolls'] = 0;
            }
            break;
 
            default: {
                return $this->notImplemented($action);
            }
        }
    }
 
    public function runWhen(&$world, $action, $arguments)
    {
        switch($action) {
            case 'Player rolls': {
                $world['game']->roll($arguments[0]);
                $world['rolls']++;
            }
            break;
 
            default: {
                return $this->notImplemented($action);
            }
        }
    }
 
    public function runThen(&$world, $action, $arguments)
    {
        switch($action) {
            case 'Score should be': {
                for ($i = $world['rolls']; $i < 20; $i++) {
                    $world['game']->roll(0);
                }
 
                $this->assertEquals($arguments[0], $world['game']->score());
            }
            break;
 
            default: {
                return $this->notImplemented($action);
            }
        }
    }
}
?>
from https://github.com/phpspec/phpspec
<?php
class DescribeNewBowlingGame extends \PHPSpec\Context
{

    private $_bowling;

    public function before()
    {
        $this->_bowling = new Bowling;
    }

    public function itShouldScore0ForGutterGame()
    {
        for ($i=1; $i<=20; $i++) {
            $this->_bowling->hit(0); // someone is really bad at bowling!
        }
        $this->spec($this->_bowling->score)->should->equal(0);
    }

}
from http://phpspec.net/
<?php

namespace spec;

use PHPSpec2\ObjectBehavior;

class Markdown extends ObjectBehavior
{
    function it_should_be_initializable()
    {
        $this->shouldHaveType('Markdown');
    }

    function it_converts_plain_text_to_html_paragraphs()
    {
        $this->toHtml("Hi, there")->shouldReturn("<p>Hi, there</p>");
    }

    public function toHtml()
    {
        return "<p>Hi, there</p>";
    }
}
from https://bitbucket.org/mkharitonov/spectrum/overview
<?php
require_once __DIR__ . '/spectrum/init.php';

describe('AddressBook', function(){
    beforeEach(function(){
        world()->addressBook = new AddressBook();
    });

    context('"MySql" driver', function(){
        beforeEach(function(){
            world()->addressBook->setDriver(new drivers\MySql());
        });
    });

    context('"Files" driver', function(){
        beforeEach(function(){
            world()->addressBook->setDriver(new drivers\Files());
        });
    });

    it('Should find person by first name', function(){
        $person = world()->addressBook->findPerson('Bob');
        verify($person->firstName, '==', 'Bob');
    });

    it('Should find person by phone number in any format', array(
        '+7 (495) 123-456-7',
        '(495) 123-456-7',
        '123-456-7',
    ), function($phoneNumber){
        $person = world()->addressBook->findPerson($phoneNumber);
        verify($person->phoneNumber, '==', '+74951234567');
    });
});

\spectrum\RootDescribe::run();
Matchers from phpunit/PHPUnit/Framework/Assert/Functions.php
  • any()
  • anything()
  • arrayHasKey($key)
  • assertArrayHasKey($key, array $array,
  • $message = '')
  • assertArrayNotHasKey($key, array $array,
  • $message = '')
  • assertAttributeContains($needle,
  • $haystackAttributeName, $haystackClassOrObject, $message = '', $ignoreCase = FALSE, $checkForObjectIdentity = TRUE)
  • assertAttributeContainsOnly($type,
  • $haystackAttributeName, $haystackClassOrObject, $isNativeType = NULL, $message = '')
  • assertAttributeCount($expectedCount,
  • $haystackAttributeName, $haystackClassOrObject, $message = '')
  • assertAttributeEmpty(
  • $haystackAttributeName, $haystackClassOrObject, $message = '')
  • assertAttributeEquals($expected,
  • $actualAttributeName, $actualClassOrObject, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE)
  • assertAttributeGreaterThan($expected,
  • $actualAttributeName, $actualClassOrObject, $message = '')
  • assertAttributeGreaterThanOrEqual(
  • $expected, $actualAttributeName, $actualClassOrObject, $message = '')
  • assertAttributeInstanceOf($expected,
  • $attributeName, $classOrObject, $message = '')
  • assertAttributeInternalType($expected,
  • $attributeName, $classOrObject, $message = '')
  • assertAttributeLessThan($expected,
  • $actualAttributeName, $actualClassOrObject, $message = '')
  • assertAttributeLessThanOrEqual($expected,
  • $actualAttributeName, $actualClassOrObject, $message = '')
  • assertAttributeNotContains($needle,
  • $haystackAttributeName, $haystackClassOrObject, $message = '', $ignoreCase = FALSE, $checkForObjectIdentity = TRUE)
  • assertAttributeNotContainsOnly($type,
  • $haystackAttributeName, $haystackClassOrObject, $isNativeType = NULL, $message = '')
  • assertAttributeNotCount($expectedCount,
  • $haystackAttributeName, $haystackClassOrObject, $message = '')
  • assertAttributeNotEmpty(
  • $haystackAttributeName, $haystackClassOrObject, $message = '')
  • assertAttributeNotEquals($expected,
  • $actualAttributeName, $actualClassOrObject, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE)
  • assertAttributeNotInstanceOf($expected,
  • $attributeName, $classOrObject, $message = '')
  • assertAttributeNotInternalType($expected,
  • $attributeName, $classOrObject, $message = '')
  • assertAttributeNotSame($expected,
  • $actualAttributeName, $actualClassOrObject, $message = '')
  • assertAttributeSame($expected,
  • $actualAttributeName, $actualClassOrObject, $message = '')
  • assertClassHasAttribute($attributeName,
  • $className, $message = '')
  • assertClassHasStaticAttribute(
  • $attributeName, $className, $message = '')
  • assertClassNotHasAttribute($attributeName,
  • $className, $message = '')
  • assertClassNotHasStaticAttribute(
  • $attributeName, $className, $message = '')
  • assertContains($needle, $haystack,
  • $message = '', $ignoreCase = FALSE, $checkForObjectIdentity = TRUE)
  • assertContainsOnly($type, $haystack,
  • $isNativeType = NULL, $message = '')
  • assertCount($expectedCount, $haystack,
  • $message = '')
  • assertEmpty($actual, $message = '')
  • assertEqualXMLStructure(DOMElement
  • $expectedElement, DOMElement $actualElement, $checkAttributes = FALSE, $message = '')
  • assertEquals($expected, $actual, $message
  • = '', $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE)
  • assertFalse($condition, $message = '')
  • assertFileEquals($expected, $actual,
  • $message = '', $canonicalize = FALSE, $ignoreCase = FALSE)
  • assertFileExists($filename, $message = '')
  • assertFileNotEquals($expected, $actual,
  • $message = '', $canonicalize = FALSE, $ignoreCase = FALSE)
  • assertFileNotExists($filename, $message =
  • '')
  • assertGreaterThan($expected, $actual,
  • $message = '')
  • assertGreaterThanOrEqual($expected,
  • $actual, $message = '')
  • assertInstanceOf($expected, $actual,
  • $message = '')
  • assertInternalType($expected, $actual,
  • $message = '')
  • assertJsonStringEqualsJsonString(
  • $expectedJson, $actualJson, $message = '')
  • assertJsonStringNotEqualsJsonString(
  • $expectedJson, $actualJson, $message = '')
  • assertJsonStringEqualsJsonFile(
  • $expectedFile, $actualJson, $message = '')
  • assertJsonStringNotEqualsJsonFile(
  • $expectedFile, $actualJson, $message = '')
  • assertJsonFileNotEqualsJsonFile(
  • $expectedFile, $actualFile, $message = '')
  • assertJsonFileEqualsJsonFile(
  • $expectedFile, $actualFile, $message = '')
  • assertLessThan($expected, $actual,
  • $message = '')
  • assertLessThanOrEqual($expected, $actual,
  • $message = '')
  • assertNotContains($needle, $haystack,
  • $message = '', $ignoreCase = FALSE, $checkForObjectIdentity = TRUE)
  • assertNotContainsOnly($type, $haystack,
  • $isNativeType = NULL, $message = '')
  • assertNotCount($expectedCount, $haystack,
  • $message = '')
  • assertNotEmpty($actual, $message = '')
  • assertNotEquals($expected, $actual,
  • $message = '', $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE)
  • assertNotInstanceOf($expected, $actual,
  • $message = '')
  • assertNotInternalType($expected, $actual,
  • $message = '')
  • assertNotNull($actual, $message = '')
  • assertNotRegExp($pattern, $string,
  • $message = '')
  • assertNotSame($expected, $actual, $message
  • = '')
  • assertNotSameSize($expectedCount,
  • $haystack, $message = '')
  • assertNotTag($matcher, $actual, $message =
  • '', $isHtml = TRUE)
  • assertNull($actual, $message = '')
  • assertObjectHasAttribute($attributeName,
  • $object, $message = '')
  • assertObjectNotHasAttribute(
  • $attributeName, $object, $message = '')
  • assertRegExp($pattern, $string, $message =
  • '')
  • assertSame($expected, $actual, $message =
  • '')
  • assertSameSize($expected, $actual,
  • $message = '')
  • assertSelectCount($selector, $count,
  • $actual, $message = '', $isHtml = TRUE)
  • assertSelectEquals($selector, $content,
  • $count, $actual, $message = '', $isHtml = TRUE)
  • assertSelectRegExp($selector, $pattern,
  • $count, $actual, $message = '', $isHtml = TRUE)
  • assertStringEndsNotWith($suffix, $string,
  • $message = '')
  • assertStringEndsWith($suffix, $string,
  • $message = '')
  • assertStringEqualsFile($expectedFile,
  • $actualString, $message = '', $canonicalize = FALSE, $ignoreCase = FALSE)
  • assertStringMatchesFormat($format,
  • $string, $message = '')
  • assertStringMatchesFormatFile($formatFile,
  • $string, $message = '')
  • assertStringNotEqualsFile($expectedFile,
  • $actualString, $message = '', $canonicalize = FALSE, $ignoreCase = FALSE)
  • assertStringNotMatchesFormat($format,
  • $string, $message = '')
  • assertStringNotMatchesFormatFile(
  • $formatFile, $string, $message = '')
  • assertStringStartsNotWith($prefix,
  • $string, $message = '')
  • assertStringStartsWith($prefix, $string,
  • $message = '')
  • assertTag($matcher, $actual, $message =
  • '', $isHtml = TRUE)
  • assertThat($value,
  • PHPUnit_Framework_Constraint $constraint, $message = '')
  • assertTrue($condition, $message = '')
  • assertXmlFileEqualsXmlFile($expectedFile,
  • $actualFile, $message = '')
  • assertXmlFileNotEqualsXmlFile(
  • $expectedFile, $actualFile, $message = '')
  • assertXmlStringEqualsXmlFile(
  • $expectedFile, $actualXml, $message = '')
  • assertXmlStringEqualsXmlString(
  • $expectedXml, $actualXml, $message = '')
  • assertXmlStringNotEqualsXmlFile(
  • $expectedFile, $actualXml, $message = '')
  • assertXmlStringNotEqualsXmlString(
  • $expectedXml, $actualXml, $message = '')
  • at($index)
  • atLeastOnce()
  • attribute(PHPUnit_Framework_Constraint
  • $constraint, $attributeName)
  • attributeEqualTo($attributeName, $value,
  • $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE)
  • classHasAttribute($attributeName)
  • classHasStaticAttribute($attributeName)
  • contains($value, $checkForObjectIdentity =
  • TRUE)
  • containsOnly($type)
  • equalTo($value, $delta = 0, $maxDepth =
  • 10, $canonicalize = FALSE, $ignoreCase = FALSE)
  • exactly($count)
  • fileExists()
  • greaterThan($value)
  • greaterThanOrEqual($value)
  • identicalTo($value)
  • isEmpty()
  • isFalse()
  • isInstanceOf($className)
  • isNull()
  • isTrue()
  • callback($callback)
  • isType($type)
  • lessThan($value)
  • lessThanOrEqual($value)
  • logicalAnd()
  • logicalNot(PHPUnit_Framework_Constraint
  • $constraint)
  • logicalOr()
  • logicalXor()
  • matches($string)
  • matchesRegularExpression($pattern)
  • never()
  • objectHasAttribute($attributeName)
  • onConsecutiveCalls()
  • once()
  • returnArgument($argumentIndex)
  • returnCallback($callback)
  • returnSelf()
  • returnValue($value)
  • returnValueMap(array $valueMap)
  • stringContains($string, $case = TRUE)
  • stringEndsWith($suffix)
  • stringStartsWith($prefix)
  • throwException(Exception $exception)
same as PHPUnit
  • be($expected)
  • equal($expected)
  • beEqualTo($expected)
  • beAnInstanceOf($expected)
  • beSet($expected)
  • beArray($expected)
  • beObject($expected)
  • beString($expected)
  • beInt($expected)
  • beFloat($expected)
  • beEmpty($expected)
  • beNull($expected)
  • beFalse($expected)
  • beTrue($expected)
  • beGreaterThanOrEqualTo($expected)
  • beGreaterThan($expected)
  • beLessThanOrEqualTo($expected)
  • beLessThan($expected)
  • containText($expected)
  • haveKey($expected)
  • customMatcher($expected)
  • predecate - ex. beClass,beAClass,beAnClass,haveName,haveAName,haveAnName
  • throwException
In src/PHPSpec2/Matcher
  • BasicMatcher.php
    • positiveMatch($name, $subject, array $arguments)
    • negativeMatch($name, $subject, array $arguments)
    • matches($subject, array $arguments)
    • getFailureException($name, $subject, array $arguments)
    • getNegativeFailureException($name, $subject, array $arguments)
  • ComparisionMatcher.php
    • beLike($subject, array $arguments) : { $subject==$arguments[0]}
  • CountMatcher.php
    • haveCount($subject, array $arguments) : {$arguments[0] === count($subject)}
  • IdentityMatcher
    • return($subject, array $arguments) : {$subject === $arguments[0]}
    • be($subject, array $arguments) : {$subject === $arguments[0]}
    • equal($subject, array $arguments) : {$subject === $arguments[0]}
    • beEqualTo($subject, array $arguments) : {$subject === $arguments[0]}
  • InlineMatcher.php
  • MatchersCollection.php
  • ObjectStateMatcher.php
    • beAbstract
    • beSimple
    • beUserDefined
    • beFinal
    • haveProperty
    • haveAnything
    • haveMethod
    • haveProperty
  • ScalarMatcher.php
    • is_bool
    • beInt
    • beFloat
    • beString
    • beBoolean
  • ThrowMatcher.php
    • throw
  • TypeMatcher.php
    • beAnInstanceOf($subject, array $arguments) : {(null !== $subject) && ($subject instanceof $arguments[0])}
    • returnAnInstanceOf($subject, array $arguments) : {(null !== $subject) && ($subject instanceof $arguments[0])}
    • haveType($subject, array $arguments) : {(null !== $subject) && ($subject instanceof $arguments[0])}
    • implement($subject, array $arguments) : {(null !== $subject) && ($subject instanceof $arguments[0])}
  • eq
  • false
  • gt
  • gte
  • ident : (use ===)
  • instanceofMatcher
  • lt
  • lte
  • null
  • throwException
  • true
Installation
  • PEAR:
    pear config-set auto_discover 1
    pear install pear.phpunit.de/PHPUnit
  • Composer: "phpunit/phpunit" : "3.7.10"
    {
        "require-dev": {
            "phpunit/phpunit": "3.7.*"
        }
    }
  • PHP Archive(PHAR)
    wget http://pear.phpunit.de/get/phpunit.phar
    chmod +x phpunit.phar
Last Update
(from 2012-12-12)
2012-12-10 2012-10-05 2012-09-08 2012-10-08 2012-11-13
Documentation/Example Document: http://www.phpunit.de/manual/3.7/en/index.html (English, French, Japanese) Document/Example: http://www.phpunit.de/manual/current/en/behaviour-driven-development.html (English, French, Japanese) No online document! (To read it compile it from /doc from source from github) Document: http://phpspec.net/#manual Document: http://mkharitonov.net/spectrum/ (old and only russian)
Example: http://spectrum-framework.org/ (English+Live Result)

12/10/2012

ติดตั้ง Naver Line ให้ใช้ภาษาไทยได้บน Linux

วิธีการติดตั้ง Line บน Ubuntu Linux ผ่าน Wine

  1. ต้องมี Wine ติดตั้งอยู่แล้ว  ถ้ายังไม่มีให้ไปติดตั้งใหม่ก่อน .. แนะนำว่าให้ใช้ Line version ใหม่ๆ, ตอนเขียนลง wine 1.5.19, wine-mono0.0.8)
  2. Download ตัวติดตั้ง Line สำหรับ Windows (http://dl.desktop.line.naver.jp/naver/LINE/win/LineInst.exe)
  3. สั่งติดตั้ง Line ตามปกติ ( double click ตัวที่เพิ่งดาวน์โหลดมา หรือสั่ง wine [pathไปหาไฟล์นั้น])
  4. หลังจากติดตั้งเสร็จแล้ว  แก้ภาษาไทยใน Line โดย
    1. copy fonts สำหรับ Windows ติดตั้งลงใน Wine ก่อน
      1. สำหรับ font ที่จะใช้จริงๆ คือ Tahoma (ดาวน์โหลดได้ ที่นี่ หรือจะดึงจาก windows เครื่องอื่นๆก็ได้)  และจะติดตั้ง font ตัวอื่นๆจาก Windows ด้วยก็ได้
      2. พอได้ฟอนต์แล้ว (ไฟล์ .ttf) ให้ copy ไปวางไว้ใน C:\Windows\fonts ของ Line ซึ่งโดยทั่วไปจะอยู่ที่  ~/.wine/drive_c/windows/fonts
    2. รันคำสั่งนี้ใน command เพื่อไปแก้ไขให้ Line เปลี่ยน font ไปใช้เป็น tahoma ทั้งหมด
    3. (คำสั่งนี้ใช้กับถ้าติดตั้ง Line แบบทั่วๆไปที่จะมี path ของ C:\ อยู่ที่ ~/.wine/drive_c/ )
      
      
      บน Linux x86:
      
      sed -i "s/font-family:[^;]*;/font-family:'tahoma';/g" ~/.wine/drive_c/Program\ Files/Naver/LINE/res/skin/basic/css/*
      
      บน Linux x64:
      
      sed -i "s/font-family:[^;]*;/font-family:'tahoma';/g" ~/.wine/drive_c/Program\ Files\ \(x86\)/Naver/LINE/res/skin/basic/css/*
      
  5. ถ้าเปิด Line อยู่ให้ปิดก่อน แล้วทำการเปิดโปรแกรม Line เพื่อเล่น ตามปกติ





 Thanks to Xcode Devil สำหรับวิธีในการทำ