月別アーカイブ 9月 2019

著者:ym

いまさらnsupdate

今日は BIND 9.11.11 が出たので、冗長構成の半分を更新。ついでに nsupdate 設定です。

SSL 証明書の更新作業が増えてきたので、DV認証をどうするか悩んだ結果、やはり DNS + メールを自動処理するしかないとなりました。当初は PowerDNS でデータベース化して更新を行うことも検討しましたが、既存のシステムとの連動もあり難しそうです。

Web 認証については、.htaccess の書き方やコンテンツによっては失敗する可能性が大きい為使えません。

DNS で SSL の DV 認証する場合は、手動で記述するか、または allow-update で受け入れるかとなるわけですが、nsupdateで受け入れると BIND の jnl ファイルからの反映が嫌いなんだよね。

さていつ完成するのやら。

  • この記事いいね! (0)
asaba 著者:asaba

【android】撮影した画像を即時にフォトアルバムに載せる

もうずいぶん前に作ったのですが、androidで写真を撮った時に速攻でフォト

アルバムに載せる関数について説明します。

androidの写真は、普通に撮影してもすぐには反映されず、撮った写真を

すぐに利用したいときはその弊害をもろに受けます。

こうなればandroidのデータベースに動的に登録してしまおうということで

データベースにアクセスしbitmapからファイルパスを生成して

そのまま保存してしまうことにしました。

<pre>// アンドロイドのデータベースへ登録する
private void registerDatabase(Bitmap bitmap) {
    ContentValues contentValues = new ContentValues();
    ContentResolver contentResolver = GetPictureActivity.this.getContentResolver();
    contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
    File path = new File(MediaStore.Images.Media.insertImage(this.getContentResolver(), bitmap, "Title", null));
    contentValues.put("_data", String.valueOf(path));
    contentResolver.insert(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues);
}</pre>

これで、後はどこかのタイミングでbitmapを設定して写真が保存されていれば

成功です。

  • この記事いいね! (0)
著者:杉浦

オブジェクトのライフサイクルから見たモデルの分割

 プログラミングにおいてモデルを作る時は、大体何か一つのモノを表すモデルを作ります。何か一つというのが曲者でして、含意の広い一つのモノを対象にモデルを作るとコードが肥大することがあります(含意すべてを入れても小さい場合や共通処理から外れない場合があって、そういう時は問題が起きなかったり)。この分割の仕方にライフサイクルの観点から分割する方法があります。 モデルはある範囲のモノを抽象化して表現します。これを具象化してオブジェクトを作成する際、オブジェクトの操作を実行した後に保存する際にそれぞれ処理が入ります。ファイルシステムやデータベースに保存されている情報を表すモデルの場合は特にこれが顕著です。下図はEric Evans. エリック・エヴァンスのドメイン駆動設計 (Kindle の位置No.3058). 翔泳社. Kindle 版. からの引用図です。

 正直、図の完成度が高いです。モデルが肥大する兆候が見えたら図の矢印ごとに分割するだけでかなり整理できます。
 記事が短いので以下例の様なものを書きます。例ではDB(データベース)には既に値があり、保存はDBに行うと考えます。上図の再構成、格納、修正の部分を取り扱います。DBの一語だけであるモデルに関することを全てモデルの一クラスに記述すると破綻しそうなのが想像できます。少なくとも、再構成の際にDBへの問い合わせ方法(FROM table、PDOなど)が必要になり、柔軟な検索条件の取り扱いも高頻度で必要になります。格納の際にもDBで行えないバリデーション、複数の関係するデータについての同期が必要になります。これらの上でモデル自体の振る舞いについても必要になります。分割が必要です。
 DBの例では問い合わせ、格納、振る舞いの三分割ができます。フレームワークが備えていることの多いORM(オブジェクト関係マッピング)においては大体、問い合わせが隠蔽されています。データベース定義とコード内容を分離させたい際にのみ生成に関する追記が必要になるでしょう。格納もDB命令部は隠蔽されがちで関係設定が定義されいれば勝手に同期してくれます。バリデーションのみが必須です。ルールが複雑化する場合、あるルール一つを表すモデルを作るのもいいでしょう。残ったのは振る舞いです。これはアクティブ状態で直に参照できない方が問題の部分であり、インスタンス化されたモデルの本質といっていい部分です。

  • この記事いいね! (1)
村上 著者:村上

【Cordova】画像をリサイズできるプラグイン「cordova-plugin-image-resizer」

カメラプラグインで取得した画像をリサイズするときに使ったプラグイン「cordova-plugin-image-resizer」のご紹介です。
以前は違う方法でリサイズ処理を行っていたのですが、プラグインを探したらこちらの方が簡単!ということで乗り換えました。

今回使用したプラグインの GitHub はこちらから。

GitHub – JoschkaSchulz/cordova-plugin-image-resizer
https://github.com/JoschkaSchulz/cordova-plugin-image-resizer

 

インストールは下記のコマンドを使います。
が、こちらのプラグインはカメラプラグインの導入が必要とのことでしたので、インストールする前に、先にカメラプラグインをインストールしてください。

// カメラプラグイン
cordova plugin add cordova-plugin-camera
// 画像リサイズプラグイン
cordova plugin add https://github.com/protonet/cordova-plugin-image-resizer.git

あとは、下記のコードを追加すればOKです。
なお、サンプルコードはカメラプラグインで画像を取得するところから記述しています。

// カメラプラグインでアルバムから画像取得
var cameraoptions = {
  sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
  quality: 50,
  encodingType: Camera.EncodingType.JPEG,
  destinationType: Camera.DestinationType.FILE_URI
}
navigator.camera.getPicture(function(imageURI) {
  // 画像リサイズ
  let resizeoptions = {
    uri: imageURI,
    folderName: "[任意のフォルダ名]",
    quality: 70,
    width: 1000,
    height: 1000,
    base64: true,
    fit: false
  };
  window.ImageResizer.resize(resizeoptions,
    function(image) {
       // 画像リサイズ成功時の処理
    }, function() {
      // 画像リサイズ失敗時の処理 
    });
}, function(error) {
  // 画像取得失敗時の処理
}, cameraoptions);

10行目からのリサイズオプションで、画像 URI やリサイズ後の高さや幅、画質などを決定しています。
リサイズ後の画像パスは 20行目のファンクションの引数 image で取得できます。

また、環境の都合上、上記のコードでは リサイズ後の画像は base64 形式になっています。
こちらは 16行目で指定しています。

17行目の fit は、リサイズ後の画像を指定した幅・高さに合わせるかどうかを指定します。
こちらは Android のみに反映される設定です。

 

以上、画像のリサイズを行えるプラグイン「cordova-plugin-image-resizer」のご紹介でした。
ご参考になれば幸いです。

  • この記事いいね! (0)
takahashi 著者:takahashi

redisを触ってみる Pub/Sub編

前々回からご紹介しているredisですが、KVS型のDBとしての機能のほかに、もう一つredisが備えている機能があります。

メッセージ配信の仕組みである”Pub/Sub”をredisクライアント間でできる機能です。

Pub/Subとは、メッセージを受信したいユーザーが特定のチャネルを購読(Subscribe)し、配信側はそのチャンネルに対してメッセージを一斉配信(Publish)することで購読側はメッセージを受け取るという仕組みです。

Pub/Subをするために、必ずしもredisを使用する必要はありませんが、自分で実装するとそこそこ大変なのでredisのような既存の仕組みで利用できるのはとてもありがたいです。

今回はredisのPub/Sub機能を実際に試してみたいと思います。

まず、redis-cliクライアントを2つ立ち上げておきます。

片側のredis-cliで、下記のようなコマンドを実行します。

subscribe チャネル名

subscribeしたクライアントは、待機状態になります。

なお、subscribeしている間は他のredisコマンドは実行できなくなるので注意してください。

この状態で、今度はもう片側のredis-cliで下記のようにコマンドを実行します。

publish チャネル名 メッセージ

すると、先程subscribeした側のredis-cliにpublishされたメッセージがリアルタイムで受信されます。

前々回にご紹介した、redisをリモートから接続できるようにしておけば、ネットワーク経由でも送ることができます。

複数クライアントもばっちりです。

redis単体でここまでできるので、あとはプログラムとredisをつないでWebsocketあたりを使えば、簡単にリアルタイムチャットなども実装できそうですね。

・前の記事
redisを触ってみる 基本操作編

  • この記事いいね! (0)
takahashi 著者:takahashi

redisを触ってみる 基本操作編

前回は、redisのインストール・起動方法についてご紹介しました。

今回は、redisを実際に操作して、値を保存する方法をご紹介したいと思います。

値の保存・呼び出し

redisはKVS(Key-Value Store)型のDBなので、データ構造としては、あるキーに対してある値が紐づく、といった概念になります。

redisで値の保存(RDBでいうinsertに相当)を行うには、先日説明したredis-cliを起動し、下記のようにコマンドを入力します。

set キー名 値

こうすると、キー名で指定された名前のキーが作成され、値で指定された値がキーと紐づけられ、redisに保存されます。

キーに保存した値を確認(RDBでいうsekectに相当)するときは

get キー名

とするだけで取得できます。

データ構造の概念が簡単だけあって、コマンドも超簡単で扱いやすいですね。

キー一覧を表示する

先程までの手順で、キーを作成して中に値を登録し、キー内に登録した値を表示するところまではできました。

ではキー名を忘れてしまった場合などに、現時点で作成済みのキーの一覧を見たい、という場合もあるかと思います。

そういう場合は下記のコマンドを実行すると作成したキーの一覧が表示されます。

keys *

ほかにも、変数の型を変更することで一つのkeyに複数の値を挿入したり、値の保存期間を指定したり、といった機能があるそうです。

SQLと比較すると、やはり簡素すぎて代替えにはならないなーという印象ですが、その分非常に扱いやすいうえ動作も軽く、速いので、一時的に値をストックしておく使い方であれば十二分に便利に使えそうです。

導入も簡単ですし、手軽に触れますので、まだredisを触ってないけど興味が出てきたかも…という方はぜひ触ってみてください。

・次の記事
redisを触ってみる Pub/Sub編

・前の記事
redisを触ってみる 初期設定編

  • この記事いいね! (0)
著者:杉浦

【PHP】全く異なる複数クラスを疑似継承する黒魔術

 PHPの継承は常に単一です。これによって知るべき親クラスの情報を単純化してコードの複雑度を上げにくくしてあります。多段継承こそあれ複数経路は作れません。

class Hoge extends Foo // Foo一つを継承することはできる
class Fuga extends Foo,Bar // FooとBarを同時に継承するのはだめ

 やりかたはDI(Dependeny Injection)とマジックメソッドの応用です。

class Foo {
    public function echoFoo() {
        echo 'foo';
    }
    public function selfIntroduction() {
        echo "I'm foo.";
    }
}

class Bar {
    public function echoBar() {
        echo 'bar';
    }
    public function selfIntroduction() {
        echo "I'm bar.";
    }
}

class FooBar {
    public $foo;
    public $bar;
    
    public function __construct($foo, $bar)
    {
        // if コンストラクタでこけるのをいとわないか引数を気にしないなら:
        //     DIせず、ここで$this->foo = new Foo()の様に直接インスタンス化することもできる
        $this->foo = $foo;
        $this->bar = $bar;
    }

   public function __call($name, $arguments)
    {
        method_exists($this->foo, $name)
         ? $this->foo->$name($arguments)
         : $this->bar->$name($arguments);
    }
}

$f = new Foo();
$b = new Bar();
$fb = new FooBar($f, $b);
$fb->echoFoo();// foo
$fb->echoBar();// bar
$fb->selfIntroduction();// I'm foo.

 実行結果はコメントの通りになります。環境によってはセキュリティ問題でWARNINGが出ます。
 このようにするとFooBarインスタンスで未定義のメソッドが呼ばれたとき、DIしたfooのメソッドが存在するか確認し、fooにあればfooから実行、fooにもなければbarのメソッドを探し実行します。同様のやり方でstaticメソッド、プロパティも継承もどきができます。
 この方法を使えば簡単に全てのクラスの役割を持った神クラスを作れますが、もちろんそんな状態は作るべきでありません。複雑さに際限がなくなりコードを追うのも動作を理解するのも大変になります。

  • この記事いいね! (1)
asaba 著者:asaba

【android・bitmp】bitmapからblobを作成する方法

bitmapとして生成したものは直接データベースには保存できません。

送るにはまずbyte配列に変換してblobに対応させる必要が

あります。blobとは、バイナリデータを格納するための型の一つで、

おおよその画像はデータベースに保存される際はblobに格納されます。

 

一般的には、ByteArrayOutputStreamを使って変換することで

データベースに格納できるようになります。


//bitmap imgには画像が入っていると仮定する
<pre>Bitmap img;</pre>
<pre>ByteArrayOutputStream baos = new ByteArrayOutputStream();
img.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] arr = baos.toByteArray();
System.out.println(arr);
values.put("image", arr);</pre>

 

変換が成功すれば後はputで自由に送ることができます。

 

追記:こちらはbitmapからUriを作成する方法です。

new Fileのところは適宜変えても大丈夫そう。

<pre>File path = new File(MediaStore.Images.Media.insertImage(this.getContentResolver(), img, "Title", null));
Uri uri = Uri.parse(String.valueOf(path));</pre>
  • この記事いいね! (0)
村上 著者:村上

【Cordova】iframeで指定した外部サイトが表示されないときの対処法【iOS】

Cordova で iframe を使った際に遭遇した不具合についてまとめ。
外部サイトを iframe で表示しようとしたのですが、iOS でだけ表示ができなかったので、その対処法についてです。
なお、Android では問題なく表示できていました。

参考にしたサイトはこちらから。

ionic3 – iframe内に外部サイトが表示できない – memorandum-plus
https://memorandum-plus.com/2018/12/21/ionic3 – iframe内に外部サイトが表示できない(ios不具合)/

なお、外部サイトを開く方法としては、「cordova-plugin-inappbrowser」プラグインを使うという手もあったのですが、レイアウト的な問題で、iframe を使いました。

 

さて、こちらの対処法ですが、config.xml ファイルに下記の一文を追加するだけでした。

<allow-navigation href="*" />

こちらを使うと、WebView 上で使用できる URL を制御することができます。
* を指定すると、全ての URL を許可します。

上記を追加したら、あとは再ビルドして実行してください。
私の環境では、問題なく表示されました。

 

以上、Cordova の iOS アプリで、iframe で指定した外部サイトが表示されないときの対処法でした。
参考になれば幸いです。

  • この記事いいね! (0)
著者:杉浦

【Vue】Vuexことはじめ

Vuex は Vue.js アプリケーションのための 状態管理パターン + ライブラリです。
Vuex とは何か? | Vuex

 Vuexは上記の様にVue.jsで作成したプログラム中の状態管理を担うライブラリです。乱暴な言い方をするとVuexは管理しやすいグローバル変数を提供してくれます。Vuexのやることはコードと合わせてを見るとわかりやすいです。

// Vuexのストア(状態管理定義)の記述
export const HogeStore:Module<any, any> = {
    // 管理する状態。グローバル変数の本体的なモノ。
    // これを好き勝手弄らせないが、どこからでも参照できるようにする。
    state: { 
        foo: [],
        bar: false,
    },
    // 管理する状態を直接弄ることのできる関数群。ここにある記述以外ではstateを変更できない。
    // store等を介して、commit()関数で呼び出してのみ実行される。
    // 下記の様に思いっきり抽象化すると扱いやすい。
    mutations: {
        setFoo(state, newFoo){// state.fooを変更する
            state.foo = newFoo;
        }
    },
    // 具体的なcommitの内容を記述する。
    // コンポーネント中でstore.dispatch(アクション名)とやると直接commitするより安全安心。
    actions: {
        setFoo(context, newFoo){// state.fooを変更する.mutationsと名前がかぶってもOK
            context.commit('setFoo', newFoo);
        },
        pushFoo(context, newFoo){// state.fooに追記的な
            context.commit('setFoo', newFoo);
        },
        async resetFoo(context){// state.fooをAPI等のリポジトリから取得して改めてセット
            const newFoo = await FooRepository.get();
            context.commit('setFoo', newFoo);
        }
    }
}
// コンポーネント側の記述
// 参照の際には算術プロパティを利用すると便利
computed: {
    foo: {
      get() {
        return store.state.HogeStore.foo;
      },
      set(newFoo) {
        store.dispatch('setFoo', newFoo);
      },
    },
},
methods: {
    async reset() {
        await store.dispatch('resetFoo');// dispatch('アクション名')でactions中のメソッドを呼び出す
    }
}

 公式を読むともっと多彩なことができますが、とりあえず上記のだけでも十分に機能を発揮します。setterが厳格でgetterが自由なグローバル変数な印象を受けました。getterは追記できるため同じリソースを多角的に読みたい際も複雑さがそれほど増しません。
 Vuexを用いるタイミングですが、コンポーネント間のemitが長大になる時でしょう。例えば、あるコンポーネント群(メニューとか検索ボックス)はリソースを取得、あるコンポーネント群(表とかグラフとか)はリソースを表示、あるコンポーネント群(編集モーダルとか)はリソースを加工、とかやりだすと値の変更を4つ5つ越しのコンポーネントに伝播させる必要が出たり、その伝播のルートが3つ股4つ股になったりと煩雑になります。Vuex抜きにこれを整理しようとすると各コンポーネント群の重心であるメインコンポーネント(コンポーネントを呼び出すコンポーネント。App.vueとかPages/Fuga.vueとか)の中に処理が集中しだします。こうなるとメインコンポーネントのやっていることがまさしくVuexのやるべきことになります。
 Vuexはコンポーネント間の依存が直列や一方向の様な整然とした場合は不要ですが、そうでない時は値のやりとり最低限になりすっきりします。また純粋なTypeScriptで記述ができるため動作を明確にしやすいです。先述の例の様にVueアプリが複雑な場合、どこかしらでVuexの役割を既に担おうとしている部分があります。ソースコードが複雑化し、もうどうにもならない時はいっそ後付けでVuexを追加する良いです。

  • この記事いいね! (1)