Rails command generetor を作ってみた
angularJsとbootstrapの練習を兼ねてRailsのgenerate modelのコマンドを出力するサービス(ツール?)を作ってみた。
Rails command Generator - http://rails-command-generator.herokuapp.com/
サービスそのものにはあまり意味はなく、個人的なプログラミングの練習ということで。(個人的にはコマンドをよく忘れるので重宝しますがw)
他のコマンドは時間があれば作りたいな。
以降は使った技術の話
続きを読むangularJSにtypeahead.jsを組み込む
autocomplete機能を実現するライブラリにtwitter社製typeahead
というライブラリがあります。これをangularJSのプラグインとして組み込み・利用する方法を書いてみたいと思います。
プラグイン
探してみるといくつかプラグインがあり、どれも大体同じようなものですが、 今回は Siyfion/angular-typeahead - Github を使います。
インストール
bowerでインストール
$ bower install angular-typeahead
bowerが利用できない場合は、
Githubのプロジェクトからangular-typeahead.js
またはangular-typeahead.min.js
をダウンロードし、適当な位置に配置します。
本家typeahead.jsとjQuery(1.9+)も利用するので同様に配置します。
<script src="angular.min.js" type="text/javascript"></script> <script src="jquery.js" type="text/javascript"></script> <script src="typeahead.js" type="text/javascript"></script> <script src="angular-typeahead.min.js" type="text/javascript"></script> <script src="app.js" type="text/javascript"></script>
基本的な使い方
1.モジュールを生成するときにプラグインを読み込む(DIする)
//app.js var app = angular.module('App', ['siyfion.sfTypeahead']);
2.htmlおよびNgControllerに組み込む
入力部分となるinputタグに. sfTypeahead
, datasets
, NgModel
を設定する
//index.html <input type="text" class="sfTypeahead" datasets="exampleData" ng-model="foo">
3.コントローラに候補データをセットする
//app.js app.controller('MyController', ['$scope', function($scope) { $scope.exampleData = { name: 'items', local: ['java', 'javascript', 'c++', 'ruby', 'perl', 'python' ] }; } ]);
指定する値の詳細は以下のページに書いてあるものと同じです。 twitter/typeahead.js - Github
応用編
上記の例はマニュアルに載っているのそのままなので、もう少し応用した例。
「リストにならんだDOMの中にinputタグがあり、その中にtypeaheadを表示したい。」という場合、どのように実装するか。
まずはHTML。リストデータとなるusersを追加し、NgRepeatでループさせてユーザ一覧を表示。
//index.html <div ng-repeat="u in users"> <useritem user="u" languages="languages" /> </div>
Controllerは前項の構成に、リストデータのusersを追加。
//app.js app.controller('MyController', ['$scope', function($scope) { $scope.users = [{ name: "bill", language:"" }, { name: "luis", language:"" }]; $scope.languages = { name: 'items', local: ['java', 'javascript', 'c++', 'ruby', 'perl', 'python' ] }; } ]);
NgRepeatで出力されたDomに対して、directiveを利用してhtmlを出力していきます。
//app.js app.directive('useritem', function($compile) { var linker = function(scope, element, attr) { element.html('<span>{{user.name}}</span>' + '<input type="text" class="sfTypeahead" ' + ' datasets="languages" ng-model="user.language">'); $compile(element.contents())(scope); }; return { restrict: 'E', replace: true, link: linker, scope: { user: '=', languages: "=" } }; });
ポイントとしてはauto completeの候補データlanguages
を<useritem>
に渡し、directive内で各elementに対してのdatasets
として設定しているところです。当初directiveのscopeへの値の渡し方が理解できず結構悩みました。
今回作ったDemo - http://embed.plnkr.co/Qalhe2oG6gpSr3njF4PQ/preview
angularJSすぐハマるけど、わかってくるとホントによく出来たライブラリだなぁ思います。
Rubyで全角文字列を2バイトとして数えたい
Ruby(1.9以上)でエンコードをUTF-8として利用している場合、
Stringのbytesize
メソッドは基本的にマルチバイトを3バイトして返します。*1
"abc123){*~".bytesize #=>10 "あイ冬".bytesize #=>9
やりたいこと
等幅のフォントを利用して、文字列と空白を組み合わせ固定長のような形式の 文字列にしたい。 そのため、全角文字は2(半角2文字分なので)、半角文字は1として文字列をカウントしたい。
例えば
- "漢字"という文字列は4
- "ab"という文字列は2
- "全角space"という文字列は9
というような具合です。
コード
以下の様なget_exact_size
メソッドを作成しました。
https://gist.github.com/7541358
というような方法で 全角→2、半角→1という方法で取得出来ました。
count_multi_byte
はおまけで作りました。
もっといい方法があればコメント下さい。
参考:マルチバイト文字を含む文字列の表示桁数を合わせる - 紅孔雀
*1:一部4バイトとして返す文字列もあります : http://www.softel.co.jp/blogs/tech/archives/596
bowerでインストールしたファイルの配置を設定するにはgrunt-bower-taskが便利
bowerのファイル構成。デフォルトのbowerでinstallするだけだと、 (デフォルトの設定で)bower_compornentにそのライブラリのディレクトリとファイルが配置されるだけ。
プロジェクトでjs/cssを使いたい場合はその中から特定のファイルを取り出して、プロジェクト用のディレクトリに配置してそこから呼び出すようにしたい。
そこでgruntとgrunt-bower-taskを使っていい感じにjs/cssファイルを配置する方法を調べてみました。
- grunt grunt
- grunt-bower-task yatskevich/grunt-bower-task
grunt-bower-task インストールと設定
grunt-bower-taskのインストールはこちらのGithubのREADMEを参考にしてください。
bower.json
とGruntfile.js
を作成し、以下のコマンドを実行することで
bowerでのインストールと指定したディレクトリへの配置を自動で行ってくれます。
$ grunt bower:install
grunt-bower-taskのoptions.layout
本題はここからで、optionのlayout
によって
targetDir以下のディレクトリ・ファイルの構成を指定ます。
マニュアルにも書いてあるのですが、
種類はbyType
、byComponent
、独自のfunction
の3つがあります。
今回bowerでインストールするライブラリはangularJSとbootstrapとし、bootstrapに依存したjqueryもインストールされます。 bower.jsonを以下のようになりました。
{ //中略 "dependencies": { "angular": "1.2.0", "bootstrap": "‾3.0.2" }, "exportsOverride":{ "angular":{ "js": "**/angular.min.js" }, "bootstrap":{ "js": "**/bootstrap.js", "css": "**/bootstrap.css" }, "jquery":{ "js": "**/jquery.js" } } }
byType
layoutをbyType
にするとbowerで設定されているtypeが親ディレクトリになり、その下に各ライブラリごとのディレクトリが作成されます。
typeは各ライブラリのbower.jsonのexportsOverride
によって設定されたものです。
byComponent
byComponent
は単純に親ディレクトリが各ライブラリのルートになり、その下に各タイプ別のディレクトリが生成され、その下にファイルが作成されます。
独自のfunction
ただ、今回やりたい構成は以下の様なjsファイルとcssファイルをまとめてディレクトリの下に置きたいというもの。
この場合はfunctionを使って独自にレイアウトを定義することができます。
Gruntfile.js
のlayoutの部分を以下の用にします。
layout : function (type, component) { if (type === 'css') { return 'css'; } else { return 'js'; } },
functionの引数のtype
は上記のtypeを、component
は各ライブラリ名になっています。いずれもString型になっています。
戻り値はtargetDir以下のディレクトリ名になります。/
(スラッシュ)を含んだ場合parseされ、ディレクトリ階層になります。
この状態で実行すると以下ようにjs/cssがまとまったフォルダ構成になります。
※exportsOverrideでうまく設定しないと、 js以外のファイルもjsディレクトリに入ってきてしまうので、トライアンドエラーでその辺は調整していきます。
まとめ
一つのコマンドを実行するだけで、js/cssファイルのダウンロード→配置までやってくれるのですごく便利ですねー。 grunt-bower-taskには他にも便利なoptionが色々とあるので是非お試しあれ。
今回作ったgithubはこちら kyohei8/grunt-bower-task_Demo · GitHub