2014年12月23日火曜日

Capistrano3 本番ビルドでdeploy:assets:precompileエラー。

Capistrano3を使ったrailsアプリのビルドで3時間くらいはまったのでメモ。

環境

  • rails(ruby2.1.0, rails4.1.6)
  • さくらvps

Capistrano3でビルドをすると、deploy:assets:precompileで必ずエラーになってしまう現象が発生した。
vagrantを使った開発環境では何の問題もなかった。

しばらく調査をしたところ、さくらvpsのsyslogにメモリが不足しているというログが見つかった。
どうやらvpsサーバーだと、rake assets:precompileでスワップメモリが不足し、失敗とみなされてしまうようだ。

解決方法は単純で、Capistrano3配置時にdeploy:assets:precompileを行わなければよい。
rake assets:precompileはローカルで行えばよい。

Capistrano3でdeploy:assets:precompileを実行しないようにするには、deploy.rbを以下のように変更する。


namespace :deploy do

  namespace :assets do

    Rake::Task['deploy:assets:precompile'].clear_actions
    
    desc "Precompile assets"
    task :precompile do
      puts "-----nothing-------"
    end
  end

end

Rake::Task['deploy:assets:precompile'].clear_actionsを書き忘れてしばらくはまってしまいました。ご注意を。

それにしてもcapistranoは学習コストが高過ぎると思うのは、私だけだろうか。
結局ソースコードを読まないと解決できないということが多すぎる気がする。


山情報&登山SNSアプリ「マウンテンチャンネル」を公開しました。よろしくです!

マウンテンチャンネル公式サイト

Android app on Google Play
参考サイト

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2014年12月17日水曜日

swift基礎 Alamofireでhttp接続

swiftの基礎まとめ。
HTTP接続でAPIからデータ取得する実装です。Alamofireライブラリを利用してみます。

環境

  • Xcode Version 6.1 (6A1052d)

AlamofireのDL

CocoaPodsで管理できないので、gitで直接取得します。


// プロジェクトフォルダへ移動
cd /Users/{username}/Documents/swiftworkspace/projectfolder

// サブモジュールとして取得する
git submodule add https://github.com/Alamofire/Alamofire.git

// xcode6.1でLink Binary With Libraries機能を利用して、Alamofire.frameworkを追加する。

上記の手順を踏むと、Libraryとして利用できるようになるので、公式サイトに説明されている通りに実装します。


import Alamofire

        Alamofire.request(.GET, "http://test/api/v1/tests", parameters: ["offset": 0, "limit": 1, "test_id": 1])
            .responseJSON { (request, response, JSON, error) in
                if (response?.statusCode == 200) {
                    println("success")
                    println(JSON)
                } else {
                    // error
                    println(error)
                }
        }

上記のように記述することで、APIを使ってjsonを取得することができます。

jsonのパースはSwiftyJSONが一般的なようです。SwiftyJSONの導入方法と使い方はまた別記事で。
以上

参照

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

MT.CHANNELアプリ リリース

1週間ほど前に、MT.CHANNEL(マウンテン・チャンネル、マウントチャンネル)というandroidアプリをリリースしました。

山情報と登山用SNSを融合したアプリです。

このアプリを作成した目的は、自分自身の趣味でもある登山で利用できるアプリが欲しかったのと、最近登山者がやたらと増えているので登山専用のSNSアプリが欲しいと思ったからです。

ユーザー同士が山に関する情報交換をすることで、色々と山の事故なども減らせたらと思い作成しました。

まだデータは少ないですが、徐々に増やしていくので、来年の登山シーズンからでも是非ご利用ください。(もちろん今すぐ利用できるので、今年の真冬の登山からでも利用できます)

アプリ機能紹介

投稿は山単位で可能です。

地図や山の情報を確認できます。google mapと連携も可能です。

噴火警戒レベルが指定されている山では、噴火警戒レベルが表示されます。

ログインアカウント認証では、twitterを利用しています。

言語は日本語、英語、中国語の3ヶ国語が利用可能です。

twitter公式アカウント

twitter公式アカウントの作成をしました。山に関する気になるニュースや、アプリの更新情報についてお知らせします。

以上
アプリの宣伝でした。
でわ。

PS.
facebookページとか、その他のサイトをまだ用意していないので、 「こういう機能が欲しい!」とか「〇〇山のデータを作って!」みたいな要望はとりあえずこのblogのコメント欄にお願いします。

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2014年12月15日月曜日

git 過去のコミットにタグをつける

gitでタグをつけわすれたときに、過去に遡ってtagを付加する場合は以下の方法で行う。

ハッシュとコメントのログを閲覧


git log --pretty=oneline

上記で対象のハッシュを見つけたら、tagを付加する。


git tag release1.0.0 b7b

タグをリモートリポジトリにpushする。


git push origin --tags

以上

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2014年12月13日土曜日

swift基礎 storyboardなしでTableViewを実装

swiftの基礎まとめシリーズ。
アプリ作成には避けて通れないTableViewの使い方です。

環境

  • Xcode Version 6.1 (6A1052d)

tableviewの実装

前回と同じように、storyboardを使わない実装方法です。
といってもobjective-c版とほとんど変化はありません。


import UIKit

class TestsViewController: UITableViewController {
    
    // tableviewで表示する配列
    var tests = [Test]()
    
    // testdata load
    func test() {
        // Do any additional setup after loading the view, typically from a nib.
        // self.navigationItem.leftBarButtonItem = self.editButtonItem()
        
        //let addButton = UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: "insertNewObject:")
        //self.navigationItem.rightBarButtonItem = addButton
        
        if tests.isEmpty {
            println("empty");
        } else {
            println("not empty");
        }
        
        var obj = Test(id: 1, testCode: "001", testName: "英語", imagePath: "asasa")
        tests.append(obj)
        
        var obj2 = Test(id: 2, testCode: "002", testName: "数学", imagePath: "asasa")
        tests.append(obj2)

        
        if tests.isEmpty {
            println("empty");
        } else {
            println(tests.count);
        }
        
        
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.test()
        tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier:"testcell")
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }
    
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return tests.count
    }
    
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        var cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier:"testcell")
        let test = tests[indexPath.row] as Country
        
        cell.textLabel.text = test.testName
        return cell;
    }
    
    override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        // Return false if you do not want the specified item to be editable.
        return true
    }
    
    
    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        let test = tests[indexPath.row]
        let resultViewController = ResultViewController()
        navigationController!.pushViewController(resultViewController, animated: true)
        
    }
    
    override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if editingStyle == .Delete {
            //objects.removeObjectAtIndex(indexPath.row)
            //tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        } else if editingStyle == .Insert {
            // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
        }
    }

}


objective-cのテーブルviewより随分とスッキリした短いコードになっています。
一番のポイントは tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier:"testcell") です。
storyboardを使わない場合は、表示に利用するcellをviewDidLoadメソッドで登録しておく必要があります。カスタムセルを利用する場合も同様です。

参照

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2014年12月12日金曜日

android studio1.0.0の変更点

android studio1.0.0にupdateしたら色々と変更されていました。
なので、以下に記録を残しておきます。

環境

  • andoid studio 1.0.0
  • mac Yosemite

sdkのパスを移動する

まず最初に、sdkを移動させるように警告されます。
デフォルト配置の場所はsdkを配置する場所じゃないよ!のようなエラーが出ます。

私は以下のようにユーザーフォルダ以下に配置しました。


mv /Applications/Android\ Studio.app/sdk /Users/{username}/

sdkを移動して再起動すると、sdkのpathを聞かれるので配置した場所を設定します。
0.99 → 1.0.0の順番の更新になるので、画面の説明にしたがって更新を進めていきます。

また、途中でandroid studioが開かなくなることがあるかもしれません。
Android Studioに設定してあるjavaのバージョンがMacのデフォルト設定と異なっていて利用できないのが原因です。 なので、Info.plistの以下の部分を変更します。


☓ JVMVersion → 1.6*
◯ JVMVersion → 1.6+

上記のように指定すると、java1.6でなく、java1.6以上で起動するようになります。

gradleの設定を変更

gradleの設定が色々と変更されているので、おそらく変更が必要になると思います。
以下の属性名称を利用している場合は、変更が必要になります。


runProguard => minifyEnabled
zipAlign => zipAlignEnabled
jniDebugBuild => jniDebuggable
renderscriptDebug => renderscriptDebuggable

上記の左の属性を設定している場合は、右に変更してください。
以上です。

p.s jenkinsサーバーの設定も変更しないとダメかもしれません。jenkinsも動作しないようなら、また追記します。

参考サイト

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2014年12月10日水曜日

swift基礎 storyBoardを利用しない画面遷移

swiftの基礎まとめ。
storyBoardを利用しないで画面遷移を実装する方法です。

環境

  • Xcode Version 6.1

最初のページへの画面遷移を作成する

AppDelegate.swiftに処理を記載します。 よくありがちなパターンとして、splash画面に遷移させます。splash画面は、SplashViewControllerというクラスにします。


@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow!

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        window = UIWindow(frame: UIScreen.mainScreen().bounds)
        window.backgroundColor = UIColor.whiteColor()
        window.rootViewController = UINavigationController(rootViewController: SplashViewController())
        window.makeKeyAndVisible()
        return true
    }

}

windowオブジェクトをForced Unwrappingで宣言しています。
Optional Chainingでも実装可能ですが、エラーはコンパイルでつぶす方向が良いと思います。まあ、好みなのでどちらでも良いと思います。

次のページへの画面遷移を作成する

slash画面では、こにょごにょ処理をやって初期化とかデータを取得したらログイン画面に遷移するのもよくありがちなパターンですね。以下のような感じです。


class SplashViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // something doing
        self.mvLoginView()
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    func mvLoginView() {
        println("go loginView")
        let loginViewController = LoginViewController()
        navigationController!.pushViewController(loginViewController, animated: true)
    }
    
}

そのまんまの処理です。
mvLoginView関数を呼び出して次のログイン画面に遷移させています。letは定数宣言。直接実体化してもこのサンプルなら問題なし。
navigationControllerは、Forced UnwrappingでpushViewControllerを呼び出します。ここもOptional Chainingでも動きます。

printlnはデバッグ用の関数です。
swiftではデバッグにNSLogではなく、printlnが推奨されています。
NSLogより10倍くらい速いらしいです。

とりあえず画面遷移はこんな感じで記載していくとよいでしょう。swiftは本当にコード量が少なくてスッキリ書けますね。

参照

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2014年12月7日日曜日

jenkins git unable to unlink old

jenkinsでandroidアプリのビルドをしたら発生した。

  • jenkins

facebookのSDKをimportしたら発生。原因は最初のgit commitの時に、buildフォルダまでコミットしてしまって、 それ以降のbuild時もbuildフォルダを見てapkが作成されていたのに、最新のソースではbuildフォルダをdeleteしてcommitしたから。

対応方法は簡単で、エラーを起こしているフォルダを削除すれば良い。


// gitで利用しているworkspaceに移動
/var/lib/jenkins/workspace/{project}/libraries/facebook

// buildフォルダを削除
sudo rm -rf build

これでbuildしてやるといつもどおりbuildが走った。

参考

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2014年12月6日土曜日

エンジニアのための仕事用Gmail設定

ここ最近は、毎日の振り返りの他に、3ヶ月に1回くらい大きく仕組みづくりの見直しをしています。
おかげで仕事量は増えているのに、ミスも少なく、時間にも余裕ができ、勉強や趣味に時間を回せています。
結局、仕組みと習慣と考え方で人生が大きく変わるんだと実感してます。

環境

  • Gmail

1.ショートカットを有効に

設定でonに。

これまで無効にしてたけど、覚えることにした。

2.返信時のデフォルトの動作:

「全員に返信」に設定

仕事用のメールの9割以上が全員に返信なので、デフォルト設定に変更。個人のやりとりはチャットやSNSになってしまった。

3.重要マーク

「マークを表示しない」に設定

自動振り分けは役に立たなすぎるので解除

4.送信取り消し設定

Labで設定

zでキャンセル可能になる。

5. google IMEを導入

会社のmacに入れたので、自宅でも同期させた。便利。

6. 返信定型文を導入

仕事メールの返信パターンはだいたい同じなので導入した。

あとはテンプレやフィルターのチューニングは週に1,2くらいで行っています。参考までに。
以上

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

vagrantでdockerを利用する

dockerを導入してみました。
最終的にはサーバーのCIを可能にすることですが、まずは基本から学習していきます。

環境

  • vagrant1.6.5

CoreOSをinstall

dockerを使うならCoreOSが良いとのことなので導入する


// vagrantのCoreOsを取得
git clone https://github.com/coreos/coreos-vagrant.git
cd coreos-vagrant

vagrantを起動してログインする


// 起動
vagrant up

// ログイン
vagrant ssh

ログインしたらdockerのバージョンを確認する


docker version
Client version: 1.3.2
Client API version: 1.15
Go version (client): go1.3.2
Git commit (client): 50b8feb
OS/Arch (client): linux/amd64
Server version: 1.3.2
Server API version: 1.15
Go version (server): go1.3.2
Git commit (server): 50b8feb

centosを取得


sudo docker pull centos

centos:latest: The image you are pulling has been verified
511136ea3c5a: Pull complete 
5b12ef8fd570: Pull complete 
34943839435d: Pull complete 
Status: Downloaded newer image for centos:latest

imagesを表示


sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos              latest              34943839435d        2 days ago          224 MB

コンテナを起動し、shellに入る


// -i → コンテナーの標準入力を開く。
// -t → ttyを確保する。
sudo docker run -it centos:latest /bin/bash

vimをinstallしてみる


// vimをinstall
yum install vim-enhanced

// 確認
which vim
/usr/bin/vim

コンテナから抜けて、コンテナの状態を確認する


// コンテナから抜ける
exit

// コンテナの状態を確認する
sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                          PORTS               NAMES
93cb268664fe        centos:latest       "/bin/bash"         33 minutes ago      Exited (0) About a minute ago                       sad_kowalevski      
49f86c04bc74        centos:latest       "/bin/bach"         34 minutes ago

コンテナから抜けて、コンテナの状態を確認する


// docker imageを作成する
sudo docker commit 49f86c04bc74 viminstall

imageが作成されていることを確認する


sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
viminstall          latest              4e047b5e2d39        16 seconds ago      224 MB
centos              latest              34943839435d        2 days ago          224 MB

上記で作成したDocker Imageを実行


sudo docker run -it viminstall

// 確認
which vim
/usr/bin/vim

vimが入っているのを確認

その他


dockerのコンテナを全て削除

docker rm `docker ps -a -q`

dockerのimageを削除

sudo docker rmi REPOSITORY

ひとまず概要は理解できました。今度はDockerfileとかDocker Hubを使ってみよう。

参考

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2014年12月5日金曜日

railsでtwitter風の時間表示を返す

  • ruby 2.1.2
  • rails 4.1.6
  • grape

アプリでユーザーの投稿時間を返す文字列をtwitter風にする実装のメモです。
「1時間前」とか、そういう表示のパターンですね。
結論から言うと、railsで用意されているAction View Date Helpersを使えば良いです。でも、今回はmodelでView Date Helpersを呼ぶ必要があったので、少し工夫が必要でした。
結局、以下のように呼び出しました。

 

    # coding: utf-8
    class TestModel < ActiveRecord::Base 
      include ActionView::Helpers::NumberHelper

      // something

      ApplicationController.helpers.time_ago_in_words(test.created_at)
    end

    

デフォルトだと英語なので、他の言語にしたい場合は引数にlocalを設定してあげればOK。

 

    # coding: utf-8
    class TestModel < ActiveRecord::Base 
      include ActionView::Helpers::NumberHelper

      // something

      ApplicationController.helpers.time_ago_in_words(test.created_at,{ :locale => 'ja' })
    end

    

便利ですねえ。やっぱvoltよりrailsのほうが良いですね。

参考

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

server spec2

server spec2を導入したらrspecが3以上の対応になっていたのでコードを修正しました。

  • ruby 2.1.2
  • serverspec 2.3.1

変更前

 

    describe command('nginx -v') do
      it { should match /nginx version: nginx\/1\.6\.2/ }
    end

    

変更後

 

    describe command('nginx -v') do
      its(:stdout) { should match /nginx version: nginx\/1\.6\.2/ }
    end

    

公式サイトをみればわかりますが、ずいぶんと分かりやすくコードを書けるようになりました。ただ、rspc3の学習は必須です。
以上

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加
Related Posts Plugin for WordPress, Blogger...