Author's Posts

こんにちは!

最近、Ruby気持ちいい!!!って思ってるたがみです。 Ruby触りたいけどちょっと・・・とかSeleniumもいじってみようかなぁ・・・と思っている人が、簡単に、手早く、ぱぱっと動かしたい人向けの記事になってます。

それではいってみましょう!

Seleniumを動かす環境をつくる

それでは実際にSeleniumを動かしていきましょう。

Rubyはインストールしてある前提で書いていきます。

Seleniumを動かすためのgemをインストールします。

$ gem install selenium-webdriver

あとはFirefoxをインストールしておいてください。 Chromeでも大丈夫そうですが、自分の環境ではうまく動かなかったので。

これだけです! なんとも簡単!それでは軽く動かしてみましょう!!

実際に動かしてみる

それでは実際にSeleniumでFirefoxを動かしてみましょう。

ここではTwitterのトップページに飛んでみます。

といってもとても簡単で以下のコードで動きます。

twitter.rb

#coding: utf-8

require 'rubygems'
require 'selenium-webdriver'

driver = Selenium::WebDriver.for :firefox
driver.navigate.to "http://twitter.com"

たったこれだけです!なんということでしょう〜〜

これだけだとつまんないので今のTwitterのトップページからログインしてみようと思います。

以下のコードでログインすることが出来ます。

id = driver.find_element(:id, "signin-email")
pass = driver.find_element(:id, "signin-password")

id.send_keys("TwitterのID")
pass.send_keys("Twitterのパスワード")

driver.find_element(:class, 'password-signin').find_element(:tag_name, 'button').click

コードもとても直感的で、

  • IDとパスワードを入力する入力欄を取得する
  • 入力欄に対して文字列を流し込む
  • ログインボタンをクリックする

という流れです。どうですか?Rubyだとこんなに簡単に、直感的に書けるんだなぁと改めて感じました。

最後に

超簡単な流れでしたがどうでしたか? 軽くいじれることがわかったかと思います。 他にもデータを取得したり、スクロールしたりすることも出来るので色々触ってみてください。

参考URLは以下になります。

RubyでSeleniumを使ってスクレイピング selenium-webdriverドキュメント

そろそろ僕もRubyを学ばなければならないようです。

たのしいRuby 第4版
たのしいRuby 第4版
posted with amazlet at 14.01.03
高橋 征義 後藤 裕蔵
ソフトバンククリエイティブ
売り上げランキング: 29,228
Read more

まだまだあけましておめでとうございます。 年始をいかがお過ごしでしょうか。

私はいつものように、日常と変わらない生活をしています。

さてさて、ユニットテストの件ですが、以前更新して随分時間が経ってしまいましたが、書いていこうかなぁと思います。

今回はバリデーションをテストするための方法を書こうと思います。 前回の routes.php に対するテストの記事は以下になります。 CakePHP2でユニットテスト 〜route.php編〜

バリデーションを適応していく

今回はUserモデルに対してnamenotEmptyを、telに対して独自のバリデーションであるcheckNotEmptynumericOnlyを適応していると仮定します。

User.php

App::uses('AppModel', 'Model');

class User extends AppModel {
    public $validate = [
        'name' => [
            'rule' => ['notEmpty'],
            'message' => '名前を入力して下さい。'
        ],
        'tel1' => [
            'notEmpty' => [
                'rule' => ['checkNotEmpty'],
                'message' => '電話番号を入力して下さい。'
            ],
            'numericOnly' => [
                'rule' => ['numericOnly'],
                'message' => '数字のみ入力して下さい。'
            ]
        ]
    ];

    public function checkNotEmpty(){
        if(!empty($this->data[$this->alias]['tel1']) && 
           !empty($this->data[$this->alias]['tel2']) && 
           !empty($this->data[$this->alias]['tel3'])) {
            return true;
        } else {
            return false;
        }
    }

    public function numericOnly(){
        // 数字のみ許可
        $pattern = '/^[0-9]+$/';
        $tel1 = preg_match($pattern, $this->data[$this->alias]['tel1']);
        $tel2 = preg_match($pattern, $this->data[$this->alias]['tel2']);
        $tel3 = preg_match($pattern, $this->data[$this->alias]['tel3']);
        if(empty($tel1) && empty($tel2) && empty($tel3)){
           return true;
        } else {
           return false;
        }
    }
}

こういうモデルに対してテストを書いていこうと思います。

バリデーションに対するモデルを書く

テストを書いていきます。

Test/Case/Model/UserTest.php

App::uses('User', 'Model');

class UserTest extends CakeTestCase {

    public function setUp() {
        parent::setUp();
        $this->User = ClassRegistry::init('User');
    }

    public function tearDown() {
        unset($this->User);
        parent::tearDown();
    }

    public function testUserValidations(){
        $baseCase = [
            'name' => '佐藤'
            'tel1' => '090'
            'tel2' => '0088'
            'tel3' => '8800'
        ];

        $testCases = [
            true => [
                ['name' => '谷'],
                ['tel1' => '03', 'tel2' => '1111', 'tel3' => '2222']
            ],
            false => [
                ['name' => ''],
                ['tel1' => ''],
                ['tel2' => -1]
            ]
        ];

        foreach($testCases as $expected => $cases){
            foreach($cases as $case){
                $testCase = array_merge($baseCase, $case);
                $this->User->set($testCase);
                $result = $this->Entry->validates();
                if((boolean)$expected){
                    $this->assertTrue($result);
                } else {
                    $this->assertFalse($result);
                }
            }
        }
    }

}

こんな感じでテストを書いていきます。 このやり方であればテストケースを変更するのも簡単だし、trueとfalseで固まっているのでわかりやすいかと思います。

最後に

いかがでしたでしょうか。

今回もroutes.phpのテストと同じく、直感的でわかりやすかったかと思います。 ユニットテストは自分が安心するのもありますし、機能毎の詳細な仕様書にもなります。 なのでしっかりテストを書いていきましょう。(面倒くさいけど)

CakePHPで新しい本が出てました。読まねば。

Webアプリ開発を加速する CakePHP2定番レシピ119
長谷川 智希
秀和システム
売り上げランキング: 22,052
Read more

みなさんあけましておめでとうございます! 2ヶ月くらい更新してなかったですが、ブログは書き続けてたほうがいいなぁと思っていたので新年からまた書き始めます!

それでは早速書いていきましょう。

最近Composerを使ってCakePHPでFacebookログインを実装したので、そこまでの流れをまとめておこうと思います。

Composerで必要なものをインストールする

composer.jsonから作っていきましょう。

CakePHPFacebook PHP SDKをインストールするので以下のように書けばインストール出来ます。

{
    "name": "facebook-login",
    "repositories": [
        {
            "type": "pear",
            "url": "http://pear.cakephp.org"
        }
    ],
    "require": {
        "pear-cakephp/cakephp": "2.4.4",
        "facebook/php-sdk": "dev-master"
    }
}

composer.pharをダウンロードしてパッケージをインストールしていきます。

$ curl -s http://getcomposer.org/installer | php
$ php composer.phar install

Bakeでプロジェクトを作成します。

$ vendor/bin/cake bake project $PWD --empty

これでブラウザからアクセスすると、いつもの緑画面が出てくると思います。

ここまでで大方終了しましたが忘れちゃいけないので CAKE_CORE_INCLUDE_PATH を書き換えること。

3箇所書き換えていきましょう。

webroot/index.php

define('CAKE_CORE_INCLUDE_PATH', ROOT . DS . APP_DIR . DS . 'vendor' . DS . 'pear-pear.cakephp.org' . DS . 'CakePHP');

webroot/test.php

define('CAKE_CORE_INCLUDE_PATH', ROOT . DS . APP_DIR . DS . 'vendor' . DS . 'pear-pear.cakephp.org' . DS . 'CakePHP');

Console/cake.php

$ds = DIRECTORY_SEPARATOR;
$dispatcher = 'Cake' . $ds . 'Console' . $ds . 'ShellDispatcher.php';

if (function_exists('ini_set')) {
    $root = dirname(dirname(__FILE__));

    // the following line differs from its sibling
    // /app/Console/cake.php
    ini_set('include_path', $root . $ds . 'vendor' . $ds . 'pear-pear.cakephp.org' . $ds . 'CakePHP' . PATH_SEPARATOR . ini_get('include_path'));
}

if (!include $dispatcher) {
    trigger_error('Could not locate CakePHP core files.', E_USER_ERROR);
}
unset($paths, $path, $dispatcher, $root, $ds);

return ShellDispatcher::run($argv);

最後にデータベースをbakeして終了っと!

$ Console/cake bake db_config

実装前の準備をする(Facebookアプリ作成、SDKの読み込み、データベース等)

次にFacebookアプリやFacebookSDKの読み込み、データベースの作成等を行っていきます。

以下のURLに飛び、Facebookアプリを「新規作成」し、アプリIDとシークレットをゲットしておいてください!

次にcomposerでいれたFacebook PHP SDKを読み込んでいきます。 PagesController.php で読み込んでいきましょう。

PagesController.php

<?php App::uses('AppController', 'Controller');
App::import('vendor', 'facebook/php-sdk/src/facebook');

最後にデータベースです。 今回は Admin テーブルを作成しその中にログインに必要な情報を事前に入れておこうと思います。 実際に試す場合は自分のFacebookIDを入れておいてください。

CREATE TABLE IF NOT EXISTS `admin` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `facebook_id` varchar(128) NOT NULL,
  `created` datetime NOT NULL,
  `modified` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

INSERT INTO `admin_user` (`id`, `facebook_id`, `created`, `modified`) VALUES
(1, '自分のFacebookID', NOW(), NOW());

最後の最後に! routes.php 内でPagesControllerのルーティングが定められているのでそれをコメントアウトしておきます。

    // Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));

これで終了です。やっと本題にいきましょう!

Facebookログインを実装していく

さて、やっと本題です。 ログインの流れとしては、

  • ログインボタンクリック
  • Facebook側で認証をする
  • 認証後リダイレクト先でFacebookIDが取れ、データベース内にそのIDがあればログインを完了させマイページに飛ばす

こんな感じでやっていこうと思います。

一気にいきます。PagesController.phpにがばっと書いていきます。

PagesController.php

 [
            'authenticate' => [
                'Form' => [
                    'userModel' => 'Admin'
                ]
            ],
            // ログインページ
            'loginAction' => ['controller' => 'pages', 'action' => 'index'],
            // ログイン後リダイレクトページ
            'loginRedirect' => ['controller' => 'pages', 'action' => 'my'],
            // ログアウト後リダイレクト先
            'logoutRedirect' => ['controller' => 'pages', 'action' => 'index'],
            // エラーメッセージ
            'authError' => 'Admin Only'
        ]
    ];

    public function beforeFilter(){
        $this->facebook = new Facebook([
            'appId' => '取得したAppId',
            'secret' => '取得したAppSecret',
            'cookie' => true
        ]);
        $this->Auth->allow('index', 'login');
    }

    protected function _authFacebook(){
        $login_url = $this->facebook->getLoginUrl(['redirect_uri' => Router::fullBaseUrl() . Router::url(['controller'=>'pages', 'action'=>'login'])]);
        return $this->redirect($login_url);
    }

    public function login(){
        $this->autoRender = false;
        $fb_id = $this->facebook->getUser();
        $login_info = ClassRegistry::init('Admin')->find('first', ['conditions' => ['Admin.facebook_id' => $fb_id]]);
        if(isset($login_info)){
            if($this->Auth->login($login_info['Admin'])){
                return $this->redirect(['action' => 'my']);
            } else {
                return $this->redirect(['action' => 'index']);
            }
        } else {
            return $this->redirect(['action' => 'index']);
        }
    }

    public function logout(){
        $this->Auth->logout();
        return $this->redirect(['action' => 'index']);
    }

    public function index(){
        if($this->Auth->loggedIn()){
            return $this->redirect(['action' => 'my']);
        }
        if($this->request->is('post')){
            $this->_authFacebook();
        }
    }

    public function my(){

    }

}

わからなければ質問なり公式ドキュメントを参照してください!!!

Modelのフォルダ内に Admin.php を下記のような感じで作成します。

<?php App::uses('AppModel', 'Model');

class Admin extends AppModel {

    public $useTable = 'admin';

}

Viewは index.ctpmy.ctp を作ります。

index.ctp

Form->create('Admin', ['method' => 'post']);?>

Form->button('Facebookログイン');?>

my.ctp

マイページ

Html->link('ログアウト', ['controller'=>'pages', 'action'=>'logout']);?>

これでFacebookログインが実装できました!!

最後に

いかがでしたでしょうか。 なんとなくの流れは理解出来たかなぁと思います。 何かわからない点がありましたらコメントやTwitterで聞いていただければと思います!

CakePHP本が続々出ていますね。

Webアプリ開発を加速する CakePHP2定番レシピ119
長谷川 智希
秀和システム
売り上げランキング: 15,164
Read more

こんにちは! 最近流行り?のComposerを使ってCakePHPを導入していましたが、色々使いにくいなぁと思っていたのですが、それは僕が使い慣れてないだけだったので、これからCakePHPをComposerで導入しようと思っている人向けにやるべき初期設定を書こうと思います。

それでは始めましょう

composer.jsonの設定

composer.jsonの設定は以下のような感じです。 本当に最低限のインストールしかしない設定になっています。

{
    "name": "test-app",
    "repositories": [
        "type": "pear",
        "url": "http://pear.cakephp.org"
    ],
    "require": {
        "pear-cakephp/cakephp": "2.3.*"
    }
    "config": {
        "vendor-dir": "Vendor/"
    }
}

このあとにcomposer.pharを用いてインストールを行います。 ここらへんは公式ドキュメントが詳しいのでそちらを参照下さい。

編集すべき部分と編集内容

アプリを作成することが出来たら、.htaccessなど、変更する部分はあると思いますが、composerでインストールしたときの編集すべき特有な部分は3つあります。

  • app/webroot/index.php
  • app/webroot/test.php
  • app/Console/cake.php

それぞれのファイルの変更点は以下に書きます。

app/webroot/index.php CAKE_CORE_INCLUDE_PATH部分

define('CAKE_CORE_INCLUDE_PATH', ROOT . DS . 'Vendor' . DS . 'pear-pear.cakephp.org' . DS . 'CakePHP');

app/webroot/test.php CAKE_CORE_INCLUDE_PATH部分

define('CAKE_CORE_INCLUDE_PATH', ROOT . DS . 'Vendor' . DS . 'pear-pear.cakephp.org' . DS . 'CakePHP');

app/Console/cake.php

if (function_exists('ini_set')) {
    $root = dirname(dirname(dirname(__FILE__))).$ds.'Vendor'.$ds.'pear-pear.cakephp.org'.$ds.'CakePHP';

    // the following line differs from its sibling
    // /app/Console/cake.php
    ini_set('include_path', $root . PATH_SEPARATOR .  $ds . 〜〜));
}

これを書いてあげることで、どの環境でも設定を変更することなく、動作するようになります。 僕は、ROOT定数を使うという発想がなかったので、各環境においてそれぞれの絶対パスを全て打ち込んでいました。プログラマーとしてまだまだですね。。。

最後に

公式ドキュメントにも同じようなことが書いてありますが、明示的に3つ編集すべきだよ!っていう記事があればさらに便利だなーと思ったのでこんな記事を書いてみました。 僕はまだまだcomposerを使いこなすことが出来ていませんが、もし3つ編集するんじゃなくて、別の方法があるよ!っていうことがあれば教えてくださると助かります!

CakePHPをやるのであればこの本は持っていて損はないです!よく訳に立ってます!

CakePHP2 実践入門 (WEB+DB PRESS plus)
安藤 祐介 岸田 健一郎 新原 雅司 市川 快 渡辺 一宏 鈴木 則夫
技術評論社
売り上げランキング: 17,808
Read more

みなさんこんにちは

最近Facebookを見ていて、以下の画像のように、今までの画像サイズとは違うものがよく流れてくるようになってました。

398×208!?!? んーよくわからん。 確かに前のOGP変更で推奨画像サイズが1500×1500になりましたが全部の記事に1500×1500の画像を貼るわけにはいかない!てか貼れない!!

ということで最低どのくらいのサイズがあれば上記の画像の大きい画像を出すことが出来るのかを色々作って調べてみました。 既に調べている記事も発見したので参考記事としてリンク貼っておきますね。

参考:FacebookのOGP画像サイズはどんなサイズがいいの

調べた画像は全部下に貼っておきますね

多少ネタバレ感のある画像ですが、とりあえず検証検証♪

検証

300×150の画像

表示すらされない・・・orz

400×200の画像

うーん

300×300の画像

お腹減ってきません?

350×300の画像

最近のおすすめは食パンです

400×300の画像

コンビニで売ってる8枚切りがおすすめです・・・ってきたー!

結論

ってことで、Facebookで最近出てきてる大きな画像を出すためには、最低400×300くらいの大きさがあれば表示されることがわかりました。(13年9月11日現在) もうちょっと1ピクセル単位で出せばいいのかもしれませんが、まぁ大体わかれば満足ですよね?(僕が)

てことで、みなさん。最近タイムラインに流れてきている大きな画像を出すためには400×300以上の大きさの画像を使いましょうってことで。 また仕様変更がかかるかもしれませんが、とりあえずの対処としてはこれで十分なんではないでしょうか。 Facebookの推奨は1500×1500ですからね・・・

やっぱり売れてる本は面白かったです

フェイスブック 若き天才の野望 (5億人をつなぐソーシャルネットワークはこう生まれた)
デビッド・カークパトリック
日経BP社
売り上げランキング: 13,327
Read more

みなさんこんにちは。 今回はCakePHP2でユニットテストをする方法を書いていきます。 僕は最近やっとCakePHPを使い始めて1年経過しましたが、多少大きな開発になるとやはりテストを書いたほうが早く開発が出来ますね。

また、やはりなんといってもテストがあるととにかく安心する!←これ大事

開発を進めていくにあたって、安心というものは最高に重要ですね。 僕は普段忙しくても、routeのテスト、モデルのテストは必ず書くようにしています。 最低限ここらへんのテストが正常であれば動くので。

viewとcontrollerは変更が激しいのでなかなか書かないんですけどね。。。

さて、前置きはこれくらいにして、これから何回かにわけて

  • route.phpのテスト
  • Modelのテスト
  • Controllerのテスト
  • Viewのテスト

を書いていきたいと思います。

それでは今回はroute.phpのテストを書いていきます。

適当にroute.phpに記述しよう

まずはCakePHPをインストールしてください。

インストール直後のroute.phpには以下の記述があるだけだと思います。

route.php

Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));

これだけでも十分テストを書いていけるのですが、もう1つくらいパターンの違うものを書いておきましょう。 route.phpに以下のコードを追加してください。

Router::connect('/circle', array(
        'controller' => 'pages',
        'action' => 'circle',
        'tag' => 'circle'
    ));

これで準備は出来ました。次はこのroute.phpに対するテストを書いていきましょう。

記述したroute.phpに合わせてテストを書こう

現在route.phpには以下の3つのRouterが設定されていると思います。

route.php

Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
Router::connect('/circle', array(
        'controller' => 'pages',
        'action' => 'circle',
        'tag' => 'circle'
    ));

これらのroute.phpに対してテストを書いていきます。 app/Test/Case以下に ‘AppRoutesTest.php’ファイルを作成しファイルに以下の内容を書き込んでください。

AppRoutesTest.php

App::uses('Router', 'Routing');

class AppRoutesTest extends CakeTestCase {

    public function setUp(){
        parent::setUp();
        require APP . 'Config' . DS . 'routes.php';
    }

    public function tearDown(){
        Router::reload();
        parent:tearDown();
    }

    // ここからテスト!!
    public function testTopPage(){
        $expects = array(
            'controller' => 'pages',
            'action' => 'display'
        );
        $url = Router::parse('/');
        $this->assertEqual($expects['controller'], $url['controller']);
        $this->assertEqual($expects['action'], $url['action']);
    }

    public function testPagesAll(){
        $expects = array(
            'controller' => 'pages',
            'action' => 'display',
            'pass' => array(1)
        );
        $url = Router::parse('/pages/1');
        $this->assertEqual($expects['controller'], $url['controller']);
        $this->assertEqual($expects['action'], $url['action']);
        $this->assertEqual($expects['pass'], $url['pass']);
    }

    public function testCirclePage(){
        $expects = array(
            'controller' => 'pages',
            'action' => 'circle',
            'tag' => 'circle'
        );
        $url = Router::parse('/circle');
        $this->assertEqual($expects['controller'], $url['controller']);
        $this->assertEqual($expects['action'], $url['action']);
        $this->assertEqual($expects['tag'], $url['tag']);
    }
}

これでテストを書くことが出来ました! コードの中身の説明ですが・・・

setUp()はテストが行われる前に実行される関数、tearDown()はテストが完了したあとに実行される関数です。 またそれぞれのテストケースですが、まず最初に$expects変数の中に、正しくルーティングが設定してあれば返ってくるであろう配列を書いておきます。 そしてRouter::parse()でURLをパースします。パースすることによって、route.phpに書いてあるルーティングに従って、CakePHPがcontrollerやactionを割り当てます。 その結果が$urlに入っているので、あとはPHPUnitのassertEqual()で正しいかどうかを調べています。

3番目のテストケース「testCirclePage」のときのように、少し特殊なルーティングを行っている場合、以下のようにすればどのような値が$urlにわたっているか調べることが出来ます。

$url = Router::parse('/circle');
debug($url);

こうやって調べてテストを書くことによって、どんなルーティングにも対応出来ているテストケースを書くことが出来ます!

テストを動かそう

それでは最後にテストを動かしましょう。 インストールしたディレクトリの最後に「test.php」と打てばGUIでテストを実行出来るページが表示されます。 こんな感じで↓

AppRoutesをクリックし、全てがグリーンであればテストは全て成功しています! こんな感じで↓

また、先ほどのRouter::parse()の中身を見る方法は、この画面の赤い枠で囲まれた部分をクリックするとdebug結果を見ることが出来ます 赤枠をクリック!

debug結果が表示される

これでroute.phpのテストはなんでも書けるはず!!

最後に

いかがでしたでしょうか。 route.phpに対するテストは、CakePHPのテストの中でも1番簡単なので、これをまずは理解しましょう。 もし何かわからないことがあれば、@DAI199までリプライください!

テストに関しては以下の本が1番詳しく書いてあると思いました。

CakePHP2 実践入門 (WEB+DB PRESS plus)
安藤 祐介 岸田 健一郎 新原 雅司 市川 快 渡辺 一宏 鈴木 則夫
技術評論社
売り上げランキング: 17,808
Read more

みなさんこんにちは。

最近はやっとJavaScriptをがっつりいじることが出来そうになったので、Backbone.jsに入門してみました。 また、CoffeeScriptも便利だと聞いたのでこれも勉強してみました。

勉強のためにドットインストールで公開されているBackbone.js入門の完成品を参考に、JavaScriptのコードをCoffeeScriptで書きなおしました。

これからCoffeeScriptを勉強しようと思っている人に少しでも役に立てればと思います。

CoffeeScriptもやり始めて1日くらいしかたってないので、ここはCoffeeだとこんな感じに書けるよ!とかあれば教えていただけると幸いですー ドットインストール便利!いつもお世話になってます!

また、動作環境は以下になります。

CoffeeScript v1.6.3
Backbone.js v1.0.0
jQuery v1.8.3
underscore.js v1.4.3

app.coffeeのコード

以下が今回書きなおしたCoffeeScriptのコードです! コンパイルすればapp.jsが生成されるのでそれを下のindex.htmlに読みこめば使えるはずです。

app.coffee

jQuery ->

    class Task extends Backbone.Model

        defaults:
            title: 'do something'
            completed: false

        validate: (attrs) ->
            if _.isEmpty attrs.title
                'title must not be empty!'

        initialize: ->
            @on 'invalid', (model, error) ->
                $('#error').html error

    class Tasks extends Backbone.Collection
        model: Task

    class TaskView extends Backbone.View

        tagName: 'li'

        initialize: ->
            @model.on 'destroy', @remove, @
            @model.on 'change', @render, @

        events:
            'click .delete': 'destroy'
            'click .toggle': 'toggle'

        toggle: ->
            @model.set 'completed', !@model.get 'completed'

        destroy: ->
            if confirm 'are you sure?'
                @model.destroy()

        remove: ->
            @.$el.remove()

        template: _.template($('#task-template').html())

        render: ->
            template = @template @model.toJSON()

            @.$el.html template
            @

    class TasksView extends Backbone.View

        tagName: 'ul'

        initialize: ->
            @collection.on 'add', @addNew, @
            @collection.on 'change', @updateCount, @
            @collection.on 'destroy', @updateCount, @

        addNew: (task) ->
            taskView = new TaskView model: task
            @.$el.append taskView.render().el
            $('#title').val('').focus()
            @updateCount()

        updateCount: ->
            uncompletedTasks = @collection.filter( (task) ->
                !task.get 'completed'
            )
            $('#count').html uncompletedTasks.length
            @

        render: ->
            @collection.each (task) ->
                taskView = new TaskView model:task
                @.$el.append taskView.render().el
            , @
            @updateCount()

    class AddTaskView extends Backbone.View
        el: '#addTask'
        events:
            'submit': 'submit'

        submit: (e) ->
            e.preventDefault()
            task = new Task 
            if task.set( {title: $('#title').val()}, {validate: true} )
                @collection.add task
                $('#error').empty()

    tasks = new Tasks([
        {
            title: 'task1'
            completed: true
        }
        {
            title: 'task2'
        }
        {
            title: 'task3'
        }
    ])

    tasksView = new TasksView collection: tasks
    addTaskView = new AddTaskView collection: tasks

    $('#tasks').html tasksView.render().el

index.htmlのコード

index.htmlのコードは以下です! jqueryとかbackboneとかunderscoreは上のほうにバージョン番号が書いてあるのでそれに合わせて読み込んでくださいー!

index.html

&lt;!DOCTYPE html&gt;
&lt;html lang="ja"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;title&gt;Backbone.js sample&lt;/title&gt;
    &lt;style&gt;
    .completed {
        text-decoration: line-through;
        color: gray;
    }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

    &lt;h1&gt;Tasks&lt;/h1&gt;

    &lt;form id="addTask"&gt;
        &lt;input type="text" id="title"&gt;
        &lt;input type="submit" value="add"&gt;
        &lt;span id="error"&gt;&lt;/span&gt;
    &lt;/form&gt;

    &lt;div id=&quot;tasks&quot;&gt;&lt;/div&gt;
    &lt;p&gt;Tasks left: &lt;span id=&quot;count&quot;&gt;&lt;/span&gt;&lt;/p&gt;

    &lt;script type=&quot;text/template&quot; id=&quot;task-template&quot;&gt;
        &lt;input type=&quot;checkbox&quot; class=&quot;toggle&quot; &lt;%= completed ? 'checked' : '' %&gt;&gt;
        &lt;span class=&quot;&lt;%= completed ? 'completed' : '' %&gt;&quot;&gt;
        &lt;%- title %&gt;
        &lt;/span&gt;
        &lt;span class=&quot;delete&quot;&gt;[x]&lt;/span&gt;
    &lt;/script&gt;
    &lt;script src=&quot;js/underscore.js&quot;&gt;&lt;/script&gt;
    &lt;script src=&quot;js/jquery.js&quot;&gt;&lt;/script&gt;
    &lt;script src=&quot;js/backbone.js&quot;&gt;&lt;/script&gt;
    &lt;script src=&quot;js/coffee.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;

app.coffeeに書きなおす際に困ったこと

今回Coffeeの文法をやったあとに書きなおしてみたんですが、困ったことと言えば

  • jQueryの関数の()を省略しちゃって動かない
  • jQueryでDOMをいじったあとに「@」を書かないと動かない

ってことくらいです。それ以外は結構さらさら書けました。

Coffeeだと()が省略出来るからといって、jQueryの関数まで省略しちゃダメです(´;ω;`) 具体的には35〜37行目の部分とか39〜40行目の部分とかです。

35〜37行目

destroy: ->
    if confirm 'are you sure?'
        @model.destroy()

39〜40行目

remove: ->
    @.$el.remove()

また、Coffeeだと関数内で最後に評価されたものがreturnされてしまうので、DOMをいじったあとそのままにしちゃうとそのDOMをreturnしちゃうのでそこで謎のエラーが起きるってことがありました。 具体的には65〜69行目の部分。

updateCount: ->
    uncompletedTasks = @collection.filter( (task) ->
        !task.get 'completed'
    )
    $('#count').html uncompletedTasks.length
    @

最後に

やっぱCoffeeScriptって便利ですね! 書きなおした際も、元のapp.jsだと200行程度になるんですが、CoffeeScriptで書きなおすと100行程度におさまりました。 あとCoffeeで書いたほうが見やすい! これは癖になるのもわかります。 これからBackbone.jsとかCoffeeScriptとかもっと勉強していこーと思います! 質問やこうしたほうがいいよーっていうのがあれば@DAI199までリプライお願いします!

Read more

ブログ1周年おめでとう( ・ิω・ิ)

ブログ1周年おめでとう( ・ิω・ิ)

みなさんおはようございますこんにちはこんばんは。

実は2013年7月14日にブログ1周年を迎えていましたが華麗にスルーしたあげく、なかったことにしようかと思ってた@DAI199でございます。

さきほどあったバルス祭りも完全に乗り遅れてましたので、乗り遅れ癖がついちゃってるのかもしれません

[blackbirdpie url=”http://twitter.com/DAI199/statuses/363306225343008770“]

誰もお前のブログ1周年とか聞いてねーよバーローって人もいないくらいだとは思いますが、なんだかんだで今では毎月1万人以上の方が私のブログを見て様々な課題を解決してくれてるので、皆様にはとても感謝してます。

最近はなかなかブログを更新せず申し訳ないです。 色々新たな発見があったりするのですが、新たな発見というのは連鎖するもので、一気に頭がクリアになる感じ、みなさんもあると思います。 あれを記事にするというのは結構大変な作業でして、まぁ何が言いたいのかというと頭舞い上がったまま記事書いてないってことですね。

今後はもうちょっと更新頻度をあげて、気軽な話題などもポストしていくつもりなので応援よろしくお願いします。 出来れば右バナーにもあるFacebookページにいいね!を押していただいたり、Twitter(@DAI199)をフォローしていただくとなんだかんだでテンションがあがります。 何かわからない点、これやってみたけど動かないんだけど?みたいなものはどんどんTwitterでリプライ送っていただければ丁寧にお応えしておりますのでお気軽にどうぞ!

それではこのブログを2年、3年とどんどん長くやっていければいいなぁと思いながら1年おめでとう!と言いたいです。

それではまた!

Read more

みなさんこんにちは

最近はgitlab立ちあげてjenkinsでCI構築したりして社内環境を整備したりしてるたがみです。環境構築って結構楽しかったりしますよね。苦痛なことも多いですが。。

さて、みなさんはもちろんgitを使っていますよね? そのgitに補完機能を付け加えてもっと便利に使っちゃおう!っていうのが今回の記事の主旨です

やることは超簡単!3分クッキング!

まずはgitの補完機能を実装しているソースコードをダウンロードしてきましょう。 以下のURLがgithub上に上がっているgitの補完機能コードです こちらからダウンロード

適当な場所に保存しましょう( ~/.git-completion.bash )

保存出来たら以下のコマンドを入力しましょう。(保存したファイルへのパスを書きましょう!)

 source ~/.git-completion.bash

また、.bash_profile とかに上記のコマンドを書き込んでおいて、次回以降も自動で読み込まれるようにしておきましょう(ここでも保存したファイルへのパスを書きましょう!)

.bash_profile

source ~/.git-completionbash

これでgitの補完機能を実装出来ました!何か適当にコマンドを打って確認してみてください。

この記事を読んでいるあなたにおすすめ!

gitのおすすめ本。僕もこの本からgitに手を付け始め、ちゃんと出来るようになりました。

入門git
入門git
posted with amazlet at 13.06.20
Travis Swicegood
オーム社
売り上げランキング: 71,644
Read more

みなさまこんにちは。

今日は僕がタイピングをマスターしたときのことをつらつらと書こうかな、なんて思ったり思わなかったりしてます。 タイトルは釣りでもなんでもなくて実際にこうやってたらタイピングめちゃくちゃ早くなったよっていう感じです。

とりあえず参考にしてみてください。何か参考になるかも。

僕がタイピングをし始めたのは、タイトルにもある通り、小学2年生のころです。 僕は1990年生まれなので2000年にもなってないころですね。

当時はアルファベットなんて書けず、ローマ字なんてものも全くわからない状態でした。 ただ、なぜいきなりタイピングをやり始めるようになるかというと、家にワープロが届いたことでした。

うちのおじいちゃんはとても若く、何か新しいものを導入するハードルがめちゃくちゃ低い人なのですが、なぜか突然ワープロを買ってきました。中古の。

なんで買ってきたの?と聞くと、「ただ単に安かったから」と全力の笑顔を返されたのでまぁしょうがないな、と思ったことを覚えています。

ワープロが届いたものの、誰かが使うはずもなくただ放置されていました。なので僕がもらいました。

ワープロの打ち方も全くわからず、何からすればいいのかわからなかったのですが、ワープロに入ってた唯一のゲームがタイピングゲームでした。 でもこれ、ゲームって言っていいのかわからないくらい低性能で、日本語を打つのではなくただひたすらアルファベットを打つゲームでした。しかも何かの単語になっているわけではなく、本当にただひたすらランダムなアルファベットを打つ感じ。下のようなもの

uqkzluqnszxuaqeiwoexcbheuqlkmneudioooqnshhhjkeizhqnahsedi chqheexcbheuqlkmioooqhhhjnshhhjkeizoooqnshhhjkeqnszxuaqei ooqnoienzhdxcbheuqluqnszxiwoexcbheuqlkmjkeizoooqnshhhjkeq 以下続く…

こんなランダムな文字列を10分間に2000文字打て、というゲームでした。もちろん当初の僕は何もわからず、10分間で100文字も打てれば上出来。10分間も集中力が持つことなんてほぼなかったですが。。

このゲームをしたときに思ったのは、「ただひたすら悔しい」でした。 なのでここから僕のタイピングを習得する旅は始まったのです(ドドーン

それではここから本題。以下にやったことを書いていきます。ローマ字覚えたとかそういうのは省きますね。

1, キーボードを頭の中に入れた

まず最初にやったことは、頭の中にキーボードを入れたことです。 キーボードを丸々覚えちゃったってことですね。 暇さえあれば、左上の「Q」から右下の「L」までずっとぶつぶつ言ってました。 色々な方向からキーボードを順番に言っていって、とにかく頭の中にキーボードをインプットしました。これが1週間もかからなかったくらい。人間本気になればすぐ覚えられるものです。

2, 「F」と「J」のとこにあるブツブツの必要性を噛み締める

タイピングは正しい指の動きが出来るかどうかが結構大切だと思います。 独自の指の動きを作ってもいいのですが、やっぱり「正しい」と言われてるだけあって、色々便利なんですね。

ここで便利なのが「F」と「J」のブツブツ。ここに両手の人差し指を置きましょう。どんなことがあっても人差し指をブツブツの上にのせましょう。もう何度でも。 そしたらそのまま素直にそれぞれの指を1つのキー毎にまっすぐ置いていきましょう。これが正しいポジションです。 あとはそれぞれの指で叩くキーまでも決まっているのでそれを覚えてしまいましょう。 以下の画像の通り手を置いてみるといいですよ。

ちゃんとキーボードの上に手を置けたらそれぞれのキーは正しい指でしか押しちゃダメです。右手中指で「P」を押すなんてダメです。ダメダメです。 とにかく正しいポジションを身につけましょうね。

3, とにかく叩く!叩く!叩く!!

2の正しい指のポジションをしっかり覚えたら、とにかく打つしかないです。 寿司打とかe-typingとか勧められることが多いと思いますが、1つのタイピングゲームをとにかくやるよりも、色々な文章をとにかく打つことが大切だと思います。

僕が小学2年生のときにやってたのは、もちろんネットが繋がっていなかったので上記のようなゲームは出来ず、その代わり

  • 好きな歌の歌詞
  • 好きな本の写し
  • 日記

などをとにかくタイプしてました。 この練習法のいいところは、日本語変換も早くなることなんですよね。 歌詞を正確にタイプしようとすると漢字変換やひらがな、カタカナ、アルファベット全てが混ざってくるんですよね。 実際の文章は全てが混ざっていることがほとんどなのでこれはすごいいい練習になりました。

自分の好きなものをコピーするってのはいいことですね。

さて、ここまでが僕の練習法でした。

ちなみに、タイピングを練習し始めたとき、1番最初に紹介したクソゲー(アルファベットだけのやつ)は10分間で100文字いくかいかないか、くらいだったのですが、1〜3の練習法を自分で編み出し、実践した結果、1ヶ月半後くらいには5分間程度で2000文字余裕で叩けるようになってました。

もちろん5分間で2000文字叩けるようになっても完全なブラインドタッチはまだ出来なかったのですが、1でキーボードを覚えていたおかげで2ヶ月もするとブラインドタッチも出来るようになってました。

タイピング習得しなきゃいけないけどなかなか習得出来ない!寿司打の得点を上げたい!って人は参考にしてみてはいかがでしょうか。 自慢することでもないですが、今では寿司打で1万コースで23000円くらいは食えるようになってます。実際にこんくらい食えたら幸せですね。

それでは何か質問等あれば下のコメント欄にどうぞ!

Read more