titanium cli + tishadow by windows7 開発環境update

titanium sdkのバージョンが3.3.0に上がってたので開発環境をupdate
node.jsはそのままのバージョンでtishadow、titanium、alloyをupdate

npm install -g tishadow
npm install -g titanium
npm install -g alloy

このままだとcliしかupdateされないのでsdk update

titanium sdk install          # 最新
titanium sdk install 3.3.0.GA # バージョン指定

いけた
作成から実行の手順も変わらず

titanium create -p android -t app -d . -n app -u http:// --id com.sample.app
cd app
alloy new . 
tishadow run

もちろんあらかじめwindows7androidを同じネットワーク上において
androidへtishadow appのインストールとtishadow serverの起動は必要

参考
dbankier/TiShadow · GitHub
appcelerator/titanium · GitHub
appcelerator/alloy · GitHub

ruby + sinatra + kaminari + mongoid で undefined method current_pageエラーでたけど回避

undefined method `current_page' for #<Mongoid::Criteria:0x29e8a38>

普通に使ってる分には何の問題もなかった
app.rb

get "/" do
  @article = Article.page(params[:page]).per(20)
  erb :index
end

index.erb

<%= paginate @article %>

けどdalli(memcachier)でキャッシュしたらエラーが

get "/" do
  @article ||= cache.fetch("p#{params[:page]}") do
    res = Article.page(params[:page]).per(20)
    cache.set("p#{params[:page]}",res,cachetime)
    res
  end
  erb :index
end

下記参考urlよりpaginateの指定を変更したらいけた

<%= paginate @article.page(params[:page]).per(20) %>

参考
undefined method `current_page' for #<Array: for ruby 2.0.0 and Mongoid · Issue #364 · amatsuda/kaminari · GitHub

git push heroku master で reject されたときの対応

git push heroku master したらrejectされた
先月に続いて2度目なので手順残しておこうかと
まずはgit pull

git pull heroku master

あっさり自動マージされたー
前回はconflictしたので対象ファイルを修正してgit commitしたけど
今回は

git push heroku master

でいけたー

titanium android action bar color 変更

ionicでandroidアプリを作ってみたけど、動作がもっさりしすぎで使えないと判断したため
またtitaniumに戻ってきた

しばらく使ってなかった間にaction barがデフォルト?になってて
けど色の変え方が分らなかったので調べた

1.ジェネレーターで色変えて

Android Action Bar Style Generator

2.作ったzipをダウンロードしてplatform/android/resに展開
3.tiapp.xmlにtheme指定
<android xmlns:android="http://schemas.android.com/apk/res/android">      
    <tool-api-level>14</tool-api-level>
    <manifest>
        <application android:theme="@style/Theme.Example"/>
        <uses-sdk android:minSdkVersion="10"
            android:targetSdkVersion="16"/>
    </manifest>
</android>

いけたー

・・・けどtishadowだと色変わらん・・・
参考
Custom Android Action Bar and Holo Themes in Titanium - adampaxton.com

ionic(モバイルuiフレームワーク)ためしてみた

angularjsからの流れでionicっていうモバイルuiフレームワークにたどり着いたので触ってみた
結論からいうとすごくいい
Getting Started with Ionic - Ionic Framework
getting-startedみるとiosアプリ作る流れになってるけどmacじゃないってことで
ドキュメントのガイドの流れで簡易todoウェブアプリが作ってみた
index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Todo</title>
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">

    <link href="lib/ionic/css/ionic.css" rel="stylesheet">

    <script src="lib/ionic/js/ionic.bundle.js"></script>

<script src="js/app.js"></script>
    <!-- Needed for Cordova/PhoneGap (will be a 404 during development) -->
<!--
    <script src="cordova.js"></script>
-->
  </head>
  <body ng-app="todo" ng-controller="TodoCtrl">
    <ion-side-menus>

<ion-side-menu-content>
  <ion-header-bar class="bar-dark">
    <button class="button button-icon" ng-click="toggleProjects()">
      <i class="icon ion-navicon"></i>
    </button>
    <h1 class="title">{{activeProject.title}}</h1>
    <!-- New Task button-->
    <button class="button button-icon" ng-click="newTask()">
      <i class="icon ion-compose"></i>
    </button>
  </ion-header-bar>
  <ion-content scroll="false">
    <ion-list>
      <ion-item ng-repeat="task in activeProject.tasks">
        {{task.title}}
      </ion-item>
    </ion-list>
  </ion-content>
</ion-side-menu-content>

  <!-- Left menu -->
  <ion-side-menu side="left">
    <ion-header-bar class="bar-dark">
      <h1 class="title">Projects</h1>
      <button class="button button-icon ion-plus" ng-click="newProject()">
      </button>
    </ion-header-bar>
    <ion-content scroll="false">
      <ion-list>
        <ion-item ng-repeat="project in projects" ng-click="selectProject(project, $index)" ng-class="{active: activeProject == project}">
          {{project.title}}
        </ion-item>
      </ion-list>
    </ion-content>
  </ion-side-menu>

    </ion-side-menus>

<script id="new-task.html" type="text/ng-template">
  <div class="modal">

    <!-- Modal header bar -->
    <ion-header-bar class="bar-secondary">
      <h1 class="title">New Task</h1>
      <button class="button button-clear button-positive" ng-click="closeNewTask()">Cancel</button>
    </ion-header-bar>

    <!-- Modal content area -->
    <ion-content>

      <form ng-submit="createTask(task)">
        <div class="list">
          <label class="item item-input">
            <input type="text" placeholder="What do you need to do?" ng-model="task.title">
          </label>
        </div>
        <div class="padding">
          <button type="submit" class="button button-block button-positive">Create Task</button>
        </div>
      </form>

    </ion-content>
  </div>
</script>

  </body>
</html>

app.js

angular.module('todo', ['ionic'])
/**
 * The Projects factory handles saving and loading projects
 * from local storage, and also lets us save and load the
 * last active project index.
 */
.factory('Projects', function() {
  return {
    all: function() {
      var projectString = window.localStorage['projects'];
      if(projectString) {
        return angular.fromJson(projectString);
      }
      return [];
    },
    save: function(projects) {
      window.localStorage['projects'] = angular.toJson(projects);
    },
    newProject: function(projectTitle) {
      // Add a new project
      return {
        title: projectTitle,
        tasks: []
      };
    },
    getLastActiveIndex: function() {
      return parseInt(window.localStorage['lastActiveProject']) || 0;
    },
    setLastActiveIndex: function(index) {
      window.localStorage['lastActiveProject'] = index;
    }
  }
})

.controller('TodoCtrl', function($scope, $timeout, $ionicModal, Projects, $ionicSideMenuDelegate) {

  // A utility function for creating a new project
  // with the given projectTitle
  var createProject = function(projectTitle) {
    var newProject = Projects.newProject(projectTitle);
    $scope.projects.push(newProject);
    Projects.save($scope.projects);
    $scope.selectProject(newProject, $scope.projects.length-1);
  }


  // Load or initialize projects
  $scope.projects = Projects.all();

  // Grab the last active, or the first project
  $scope.activeProject = $scope.projects[Projects.getLastActiveIndex()];

  // Called to create a new project
  $scope.newProject = function() {
    var projectTitle = prompt('Project name');
    if(projectTitle) {
      createProject(projectTitle);
    }
  };

  // Called to select the given project
  $scope.selectProject = function(project, index) {
    $scope.activeProject = project;
    Projects.setLastActiveIndex(index);
    $ionicSideMenuDelegate.toggleLeft(false);
  };

  // Create our modal
  $ionicModal.fromTemplateUrl('new-task.html', function(modal) {
    $scope.taskModal = modal;
  }, {
    scope: $scope
  });

  $scope.createTask = function(task) {
    if(!$scope.activeProject || !task) {
      return;
    }
    $scope.activeProject.tasks.push({
      title: task.title
    });
    $scope.taskModal.hide();

    // Inefficient, but save all the projects
    Projects.save($scope.projects);

    task.title = "";
  };

  $scope.newTask = function() {
    $scope.taskModal.show();
  };

  $scope.closeNewTask = function() {
    $scope.taskModal.hide();
  }

  $scope.toggleProjects = function() {
    $ionicSideMenuDelegate.toggleLeft();
  };


  // Try to create the first project, make sure to defer
  // this by using $timeout so everything is initialized
  // properly
  $timeout(function() {
    if($scope.projects.length == 0) {
      while(true) {
        var projectTitle = prompt('Your first project title:');
        if(projectTitle) {
          createProject(projectTitle);
          break;
        }
      }
    }
  });

});

デザインが秀逸でhtmlとjsファイルだけでここまでできて
cordovaを使ってアプリも作れるとなると
titanium使わなくてもいい気がしてきた

firebaseためしてみた

Firebase - Build Realtime Apps
無料アカウント作って
5 min. tutorial
ってのをすると簡易チャットの出来上がり(下記ソース)

<html>
  <head>
    <script src='https://cdn.firebase.com/js/client/1.0.11/firebase.js'></script>
    <script src='https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js'></script>
  </head>
  <body>
    <div id='messagesDiv'></div>
    <input type='text' id='nameInput' placeholder='Name'>
    <input type='text' id='messageInput' placeholder='Message'>
    <script>
      var myDataRef = new Firebase('https://baxzzmi04ol.firebaseio-demo.com/');
      $('#messageInput').keypress(function (e) {
        if (e.keyCode == 13) {
          var name = $('#nameInput').val();
          var text = $('#messageInput').val();
          myDataRef.push({name: name, text: text});
          $('#messageInput').val('');
        }
      });
      myDataRef.on('child_added', function(snapshot) {
var message = snapshot.val();
displayChatMessage(message.name, message.text);
      });
      function displayChatMessage(name, text) {
        $('<div/>').text(text).prepend($('<em/>').text(name+': ')).appendTo($('#messagesDiv'));
        $('#messagesDiv')[0].scrollTop = $('#messagesDiv')[0].scrollHeight;
      };
    </script>
  </body>
</html>

たしかに簡単
ついでに気になってた
AngularJS + Firebase
でAngularFireってのも
5 min. tutorial
あったのでやってみた

<html ng-app="myapp">
  <head>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.6/angular.min.js'></script>
    <script src='https://cdn.firebase.com/js/client/1.0.11/firebase.js'></script>
    <script src='https://cdn.firebase.com/libs/angularfire/0.7.1/angularfire.min.js'></script>
  </head>
  <body ng-controller="MyController">
    <div id="messagesDiv">
      <div ng-repeat="msg in messages"><em>{{msg.from}}</em>: {{msg.body}}</div>
    </div>
    <input type="text" ng-model="name" placeholder="Name">
    <input type="text" ng-model="msg" ng-keydown="addMessage($event)" placeholder="Message...">
    <script>
      var app = angular.module("myapp", ["firebase"]);
      function MyController($scope, $firebase) {
        var ref = new Firebase("https://gq6zmt4xgt1.firebaseio-demo.com/");
        $scope.messages = $firebase(ref);
        $scope.addMessage = function(e) {
          if (e.keyCode != 13) return;
$scope.messages.$add({from: $scope.name, body: $scope.msg});
          $scope.msg = "";
        };
      }
    </script>
  </body>
</html>

初AngularJSなのでよくわかんないけど
これでjquery版と全く同じ機能
コード量が減って見通しはよくなった?