ひとりまとめ

もろもろのメモ

Drupal7でProfile2の編集画面のテンプレートをなんとかしたい!

Drupalで画面をごにょごにょする場合、「xxx.tpl.php」というパスに合わせたファイル名のテンプレートでなんとかします。

ところが、便利モジュールである「Profile2(Profile 2 | Drupal.org)」の編集画面には、そのルールが通用しません。/editというパスで表示されるものの、そういう名前のテンプレートを配置しても読み込んでいるわけではなさそうです。

なーんかやりようはあるっぽいのですけど・・・さくっとやっちゃいたい!

 

ということで、完全お手軽・手抜きな「Profile2の編集画面を弄る方法」を思いついたので、忘れないようにメモ。

 

こういう作戦でいきます。

1)空のViews画面を用意

2)Viewsのテンプレートを作成

3)テンプレートの中で、Profiile2のフォームをレンダリング

4)保存ボタン押した後を調整

 

1)空のViews画面を用意

Viewsとはこちらのモジュール(Views | Drupal.org)。ノードなどをあれこれ選んで表示するのがラクになるものです。

これでとりあえず showするのをUsersとして適当に作ります。適当なのですが、1つでも要素がないとエラーが出ちゃうようなので、なんか出しておきます。あとで非表示にするので、本当になんでもいいです。

 

2)Viewsのテンプレートを作成

Viewsモジュールのをベースにして、今回の画面用のテンプレートを作ります。

元にするのはこのファイル。

/sites/all/modules/views/theme/views-view.tpl.php

これを自分が使用しているテーマのtemplates以下においてリネームします。

views-view--(表示されるパス)--.tpl.php

パスの「/」をハイフン2つの「--」で置き換えるところが、地味にはまりポイントかも。

 

3)テンプレートの中で、Profiile2のフォームをレンダリング

今作ったテンプレートの中で、次のように記述します。

// フォームの情報を取得
module_load_include('inc','profile2_page','profile2_page');

global $user;

$profile2 = profile2_by_uid_load($user->uid,'該当Profile2のMachine name');

$entity_form = entity_ui_get_form('profile2', $profile2, 'edit');

// レンダリング

print drupal_render($entity_form);

 

 

なお、空のページで残ってしまっていた要素は、テンプレートの中の「$rows」をprintしないことで表示回避することができました。

 

4)保存ボタン押した後を調整

このままだとSaveボタンを押したらデフォルトのProfile2画面へ行ってしまうので、それじゃあ都合が悪いという場合に、Rules(Rules | Drupal.org)を使って遷移先を変更します。

ひとまずEventsで「After updating an existing profile」とし、Conditionsは「Execute custom PHP code」でURLをみて判定。Actionsで「Page redirect」で任意の場所を指定することで、回避することはできました。

 

 

 いろんなページをViewsで作るんなら、もういっそ・・・ということで、強引回避な方法でした。

iPadをMacBookProのサブディスプレイにするアプリを比較してみた

Appleの社員さんが作ったというDuetDisplayの登場で、なんだかこの界隈が盛り上がっている様子。そこで、これまで買って試してきたものも含めて3つのアプリを比較してみたいと思います。

 

公式動画もありますが、せっかくなのでもうちょっと変わったことに挑戦してみました。iPad含めた3画面で比較!!

 

メインマシン:

MacBookPro Retina 13inch (Late 2013)

画面は最適(Retina)の1280 X 800にしています。

 

セカンドディスプレイ:

iiyama ProLite E2410HDS

24型のFull HD(1920 x 1080)をHDMIで接続しました。

 

iPad(第3世代):

Retina (2048 x 1536)ですが、以下の動画では1024 x 768で表示しています。

接続ケーブルは30ピンです。

 

 

■Duet Display

ふれこみ通りの滑らかさ。3画面であっても問題なしです。

マウスの移動などの操作では、ほんのちょっとラグを感じます。

Duet Display側の画面解像度を変更することはできませんが、Retinaの補完をして画像を滑らかにするモードはあります。ただし、これにすると動画はもたついてしまいますので、通常はRegularで使うのが良いかと思います。

f:id:g2_girichan:20141220121527p:plain

Duet Display

Duet Display

  • Rahul Dewan
  • 仕事効率化
  • ¥1,000

 

 

■TwomonUSB

同じくUSBでつないでサブディスプレイ化するアプリです。

正式対応をしているのはWindowsなのですが、OSX用のα版が公開されています。

http://easynlight.com/twomonusb/다운로드/

あくまでα版での動作ということで。

 

このアプリでは3画面共有ができませんでした。(メインとセカンドディスプレイ、セカンドディスプレイとiPadなど、いずれかがミラーリングになってしまう)

また、画面を認識した時点で、メインマシン側も動画がもたつき始めました。

 

なお、接続したiPadの解像度を細かく変えることができました。

f:id:g2_girichan:20141220123230p:plain

f:id:g2_girichan:20141220123244p:plain 

TwomonUSB - USB モニタ,デュアルモニタ, Twomon

TwomonUSB - USB モニタ,デュアルモニタ, Twomon

  • DEVGURU Co., Ltd.
  • 仕事効率化
  • ¥1,000

 

■DisplayPad

最後はWi-Fiで共有するDisplayPadです。

こちらは3画面での描画が可能でした。

やはり動画はキツイです。カクカクして、まとまって動いたりします。静止画も回線状態によってはもたつきが発生します。

DisplayPad

DisplayPad

  • Clean Cut Code
  • ユーティリティ
  • ¥300

こちらも解像度を自由に選べました。 さらに、DisplayMenuという、ツールバー常駐の解像度変更アプリからも選択が可能です。

f:id:g2_girichan:20141220130806p:plain

Display Menu

Display Menu

  • Milch im Gemüsefach
  • ユーティリティ
  • 無料

 

 

■総評

やはり、速度などの面でDuetDisplayが飛び抜けています。

ただ、値段も一番高いので利用頻度次第ですかね。

iPad でサブディスプレイというのを体験してみたい!という場合は、一番安価なDisplayPadが手軽でいいかと思います。TwomonUSBは、費用を抑えつつも安定したい場合でしょうか。

 

それぞれのアプリの今後のアップデート次第ですが、2014年暮れでは確実にDuetDisplayがオススメです!

プログラマーなら読んどけ!な本を、電子書籍で読みたい!!

最近よく「プログラムするなら読んどけ!」の本の紹介がされてる気がします。

ちまちま自分の範囲でやってる自分としては、そういった知識が(も)乏しいので、そういった本を読んでみたいと思っております。

 

プログラムなどの技術系の本って、分厚いのが多い。ちょっとでもかさばらず読みやすい方法・・・となると、これこそ電子書籍の出番かなと。

ということで、電子書籍で買えるプログラム関連の本を探してみました。なおKindleとBookLive!がありますが、BookLive!はたまに20%オフセールなどをやってるのでその時を狙うのがいいのかなと思います。

 

まずは、たいてい最初に書かれていることが多いのが、この本でした。

 BookLive!版  BookLive!版

これだけで上下合わせて1200ページを超えるボリューム!!EPUBなので、文字サイズ変更できますね。

 

続いて、開発手法な本。

 BookLive!版  BookLive!版

 BookLive!版  BookLive!版はナシ

アジャイル開発とスクラム」は、アジャイルスクラム?なにそれ??という状態で読み始めるにもいいなーという本で、「アジャイルなゲーム開発」は、いわゆるWebサービスとは違うプロジェクトに使う場合に役立ちそうな内容でした。

ドメイン駆動設計」「アジャイルサムライ」は、見つけたぞ&読んでみよう!な本です。

 

swift出てきたけど、iPhoneをいじってるのでやっぱりこちら。

 BookLive!版

 

本棚に並べてムフフと眺めるのも一興なのですが、総勢3000ページ以上の本たちをiPadなどに潜ませて持ち運んじゃうのも、なかなかのものですよね。

 

秋の夜長に。

はてなブログの自分の記事を、いろんな言語に翻訳してみたい!

Google翻訳ツールを使ってみる。タグを埋め込むだけで、いろんな言語に翻訳するボタンが追加されると言うけど、本当かなあ?

 ・・・ほんとだった!

Googleアカウントでログインしてここにアクセス。

https://translate.google.com/manager/website/suggestions

 

変更したい言語を選んで表示方法も決めます。

最後のページで出てくるコードのうち、「ページ上にウェブサイト翻訳ツール プラグインを表示する位置にこのスニペットを配置してください」の方をコピーして、はてなブログの記事を「HTML編集」で開いて、記事の一番下にペーストします。すると、この記事のように下に翻訳ボタンが出ましたー。

 

 ※もし記事の編集中に翻訳ボタンが意図しない位置で表示されるようになってしまったら、同じくHTML編集を開いて、「<div id="google_translate_element"></div>」がどこに挿入されているかをチェックします。この場所にボタンが表示されるっぽげ。

 

UITextViewで自動保存とかやってみたい!

いまどきのアプリなら、やっぱりいちいち「保存」ボタンとか押さない。勝手に保存しちゃうはず。ましてや3.5インチのフロッピーをアイコンにしないはず!

ということで、ひとまずフォーカスを失うごとに内容を保存させるメモ。カスタムにつくったTableViewのCellでハマったのでそこを重点的に。

 

基本はDelegate

手順としてはこんな感じ。

1:ViewにUITextViewを配置

  StoryBoardでぱっと。Viewのクラスにアウトレットを繋いでおきます。

2:Viewの.hでDelegateを宣言

  <UITextViewDelegate>を忘れずに。

3:Delegateを設定

  .mの中でUITextViewのdelegate = selfを書いちゃう。

4:イベントをとる

  「UITextViewの編集終わり」ということで、こちらを指定。

  -(void)textViewDidEndEditing:(UITextView *)textView

  ここで、テキストの値をCoreDataなりParseなりに保存します。

 

普通(?)ならこれでOKなんですが、同じ心づもりで自作したCellのTableViewでやったら、なぜかイベントが取れない!?delegateに指定もされてるはずなのに・・・。

で、よくよく見たところ、ワタクシ、

- initWithStyle:style reuseIdentifier:reuseIdentifier

の中でdelegate=selfしてました。これを

- awakeFromNib

の中に変更したところ、無事にイベントがとれました。

 

忘れていつかまたやりそう。

ParseのCloud Codeでsaveとかしたい!

簡単お手軽にアプリのサーバサイドを担当してくれるParse.com。単に保存するだけならアプリから適当にデータを投げるだけなのですが、「いいね!の数をカウントアップする」みたいな、クライアント側でがんばるよりもサーバでうまいことやってもらった方が良い処理もあったりします。

そんなことを可能にするのがCloudCodeらしい・・・。

 

ということで、自分なりに調べてみた結果をメモ。

参考にしたのは、こちらの公式ページです。

Cloud Code Guide | Parse

 

toolのインストール

大好きなGUIはなく、基本的にコマンドラインでカタカタやるしかないようです。

まずはターミナルを起動して次のコマンドを使ってtool一式をインストール。

Macの場合

curl -s https://www.parse.com/downloads/cloud_code/installer.sh | sudo /bin/bash

このときPasswordを聞かれますが、これはマシンにインストールしようとしてるので管理者のパスワードですね。 Installing....とか出たあと終わります。

 

セットアップ

引き続き、次のように打ち込む。「MyCloudCode」というのはParse.comで設定しているAppに対応したCloudCodeの作業をするディレクトリの名前として使われます。なので、もしAppを登録していなければ先にParse.comのサイトで作っておいた方が良いです。

$ parse new MyCloudCode

ユーザーのディレクトリの中に、このMyCloudCodeというディレクトリが作られます。(中に3つのディレクトリ&3つのファイルも)

ディレクトリなどを作り終わったら、EmailとPasswordを聞かれます。これはParse.comのを入れます。ログインできたら、自分が登録しているアプリの一覧が表示されます。今回のCloudCodeに紐づけたいアプリを選択すると終了です。

ごっそり作られたディレクトリとファイルですが、configは触らなくてOK。publicは静的コンテンツをアップする場所らしく、実際にコードを書くのはcloud以下にあるmain.jsだそうです。なお、文字コードUTF-8がよさげ。

 

実行タイミングについて

いくつかイベントが設定されてるぽい。どのタイミングで実行させるかによって、書き方が異なります。それぞれの名前は、アプリから叩くときの名前として使われます。

そのコードを叩かれた時に実行

いわゆる普通のやつ。

Parse.Cloud.define(“名前”, function(request, response){

}

 

Parseのデータが変更された時に実行

アプリからParseのデータを操作すると、それを感知して実行されるらしい。

セーブ前に呼び出される

Parse.Cloud.beforeSave(“名前”, function(request, response){

}

 

セーブ後に呼び出される

Parse.Cloud.afterSave(“名前”, function(request){

}

 

削除前に呼び出される

Parse.Cloud.beforeDelete(“名前”, function(request, response){

}

 

削除後に呼び出される

Parse.Cloud.afterDelete(“名前”, function(request){

}

 

バックグラウンドで実行

時間がかかる処理など。

Parse.Cloud.job("名前", function(request, status){

}

 

書き方

結局はParseをJavaScriptで読み書きするのでここの文法に沿って書けば良いのだけど、自分がよく使う内容だけ抜粋。memberというClass(いわゆるテーブル)にname、ageというCol(いわゆるフィールド)がある体。

Classesの指定

var query = new Parse.Query("member");

 

リクエストについた引数の取得

アプリから投げるときにnameという名前でTaroとか送ってきたというイメージ。変数にはTaroがはいります。

var targetName = request.params.name;

 

クエリーに抽出条件を設定

たとえばこんな感じで。

query.equalTo("name",targetName);

query.greaterThan("age",18);

 

 

抽出

成功失敗それぞれの処理を書いておく。抽出できたとき、結果はfunctionの( )の中に書いた変数へ納められる。複数あるときはそれが配列になっていて、result[i]とかで取り出せる。

query.find(

   success: function(results){

      // 成功時の処理 resultsに結果が入っている

   },

   error: function(error){

      // 失敗時の処理 error.codeでエラーコードが拾える

   }

);

 

値の取得、書き換え

上の例のresultsが配列で、それの1つめを操作する場合。

取り出す

var tmpName = results[0].get("name");

書き換える

results[0].set("name","Jiro");

インクリメント

results[0].increment("age");

 

値の保存

これも成功と失敗の処理を用意しておく。

results[0].save({

   success: function(){

      // 成功時の処理

   },

   error: function(error){

      // 失敗時の処理

   }

});

 

 

レスポンスを返す

ここでは文字列を固定で返してますが、もちろん計算結果や抽出結果など返してOK。

成功時

response.success("成功!");

失敗時

response.error("失敗・・・");

 

スクリプトのアップロード

これまたコマンドです。

$ parse deploy

 

実行

とりあえずターミナルから確認するにはこんな感じ。URLは「実行するタイミング」のところで書いた名前を記述。

curl -X POST \

-H "X-Parse-Application-Id: {Application ID}" \

-H "X-Parse-REST-API-Key: {REST API Key}" \

-H "Content-Type: application/json" \

-d '{}' \

https://api.parse.com/1/functions/hello

{ }の中身はそれぞれみんな違っていて、簡単に参照するには

Cloud Code Guide | Parse

にアクセスして、値を参照するのが手っ取り早げ。

 

「ParseをJavaScriptで操作するようにかけばいいんだった!」と気がつくのに、少々時間がかかりました・・・。

 

iOSアプリ テスト自動化入門

iOSアプリ テスト自動化入門

 

 次はテストに挑戦したい。

MagicalRecordで保存したつもりが、アプリ再起動すると消える!?

完全にハマりました。お手上げ気味でした。

起きていた症状はこんな感じ。

・MagicalRecordを使ってるiOSアプリ

・MagicalRecordを使ってデータを保存する

・アプリが起動している間は、読み書き自由

・アプリを再起動すると、保存できていたはずのレコードが消えてる

・他の箇所では、同様の方法でも正常に保持されてる

 

原因を端的に言うと、「この処理だけ別スレッドで実行してた」というものです。データを保存する際、NSManagedObjectContextを指定して保存しますが、それを何も考えず

context = [NSManagedObjectContext defaultContext];

とやってました。defaultContextを指定すればええんでしょ?てなもんです。

これを

context = [NSManagedObjectContext contextForCurrentThread];

としたところ、無事に再起動後も保存完了!

 

もちろん、狙いがあって別のスレッドで明確に分ける場合はそれぞれでNSManagedObjectContextを指定する必要があると思いますが、まとめたいのに分かれちゃった場合は要注意ですね。そもそもこの組み方いいの??っていう問題もありそうですので。

 

あぶないところでした。

 

iOSアプリ テスト自動化入門

iOSアプリ テスト自動化入門