Ginqのwhereの条件に変数を使いたい

最近、不本意ながらPHPでプログラムを書いている。
PHPの配列、めっちゃ辛いじゃん。Linq使いたい。Linqが使いたいんだー。
と思っていたところ、こんな素敵なライブラリがあるのを発見。

github.com

すごく便利そう。

早速つかってみたのですが、whereで変数が使えないのです。

まずはOKパターンから

$result = Ginq::from(array(1,2,3,4,5,6,7,8,9,10))
                ->where(function($x) { return $x % 2 != 0; });

var_dump($result->toArray());

出力はこれ。しゅごい。

array(5) { [0]=> int(1) [2]=> int(3) [4]=> int(5) [6]=> int(7) [8]=> int(9) }

NGパターンから

$param = 2;
$result = Ginq::from(array(1,2,3,4,5,6,7,8,9,10))
        ->where(function($x) { return $x % $param != 0; });

var_dump($result->toArray());

出力はこれ。・・・・Undefined !!!

Undefined variable: param

フォーカス違うもんな・・。しょうがない。
でも、これでは便利に使えない。
どうしよう。

こうしてみた

$param = 2;
if (!function_exists('create_where_predicate')) {
    function create_where_predicate($param)
    {
        return function($x) use ($param){
            return $x % $param != 0;
        };
    }
}
$where_predicate = create_where_predicate($param);
$result = Ginq::from(array(1,2,3,4,5,6,7,8,9,10))
        ->where($where_predicate);

var_dump($result->toArray());

できた。

array(5) { [0]=> int(1) [2]=> int(3) [4]=> int(5) [6]=> int(7) [8]=> int(9) }

もっといい方法はないものか・・。
使い方まちがってるのか?

2017/12/22 追記

他の方法があった。。useってのが使えるらしい。

$param = 2;
$result = Ginq::from(array(1,2,3,4,5,6,7,8,9,10))
->where(function($x) use($param) { return $x % $param != 0; });

だいぶすっきりした。

knockout.jsでjsonをQuery Stringに変換する際にハマった。

knockout.jsを使ってる前提でお話します。
例えば、こんなモデルがあるとして

function BlockSearchConditionModel(){
    this.width = ko.observable("");
    this.height = ko.observable("");
}

これをjQueryajaxでGetのパラメータに含めたい場合、

$.ajax({
    type: "Get",
    url: "/hoge/api/v1/blocks/search.json?widht=" + model.width() + "&height=" + model.height(),
    success: function(data){

        // 成功時

    } 
});

とする方法が考えられるが、
この方法だと条件が増えるたびにパラメータを書き換える必要がある。
なので、data: に$.paramを使いたい。

api.jquery.com

こっから本題です。
jsonにして渡すと

$.ajax({
    type: "Get",
    url: "/hoge/api/v1/blocks/search.json",
        data: $.param(ko.toJSON(model)),
    success: function(data){

        // 成功時

    } 
});

0=%7B&1="&2=w&3=i&4=d&5=t&6=h&7="&8=・・・(略)
と、予想外のパラメータが生成されます。

なぜなら、ko.toJSONで生成されるjsonは "{ "width": "10", "height": "20"}"
のように、外っ側に"が付いているのです。。
OH !!!

わざわざjsonにしないで、object渡しましょう。

$.ajax({
    type: "Get",
    url: "/hoge/api/v1/blocks/search.json",
        data: $.param(model),
    success: function(data){

        // 成功時

    } 
});

というお話しです。
1時間近く考え込んでしまった・・。

vmware fusionを使用してmac上のWindowsでVirtual Boxに64bit OSを指定できない場合の対処法

タイトルがなげー。

mac上のvmware fusionで動作しているWindows 7
Virtual Boxをインストールしている場合、
新規マシンの作成時に64bit OSが選択できない問題があります。

ぐぐると、BIOSの設定で
Intel(R) VirtualizationTechnology
を有効にしろとか出てくるんですよ。

fusionから起動しているWindowsにそんなもん無いんですよ。

その場合、fusionから対象のマシンの設定を開いて プロセッサとメモリ f:id:alocoholic_babay:20151112152627p:plain

からの

この仮想マシンでハイパーバイザーアプリケーションを有効化するにチェック。 f:id:alocoholic_babay:20151112152643p:plain

これで解決!

PowerShellでpecoでcdする

Windows使いの皆さん。こんにちは。
PowerShell使ってますか?
僕は普段はmac使いなので、zshでpecoってるわけです。

Pecoって便利ですよね。

PowerShellでも使いたい。
インストールだけなら、Windows版のHomebrewことChocolateyで可能。

choco install peco  

pecoの選択結果でcdしたい

PowerShellスクリプトも、dosコマンドもよく解らないので
適当に作ってみる。

まず、ユーザのホームディレクトリにバッチを設置する。
C:\Users{UserName}\cdp.bat

@echo off

for /f "delims=" %%i in ('dir /ad/s/b^| peco') do (
    echo cd '%%i'
    break
)

次に、Microsoft.PowerShell_profile.ps1を弄ります。
パスがわからない人は、PowerShell

$PROFILE

とすれば、出てきます。
Microsoft.PowerShell_profile.ps1が見当たらない人は、新規に追加して下さい。
そして、こんなfunctionを追加します。

function cdp(){
        $cd = $(~\cdp.bat)
        if($cd){
                Invoke-Expression "$cd"
        }
}

PowerShellを再起動後、

cdp

コマンドを実行すると・・・ pecoが発動!
日本語パスに問題があるが、ちょっと捗る。

c# WebAPIにajaxでclassをPOSTする(RoutePrefix付き)

c# WebAPIにajaxでclassをPOSTする(RoutePrefix付き)

いつも忘れてしまって何故404?と悩むのでメモ。

まず、WebAPIの引数に渡したいクラスを定義する

適当に。EMail、Nameというプロパティを持ったクラスを用意する。
とりあえず、/Models/Users.csを追加。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WebAPIPostSample.Models
{
    public class User
    {
        public string EMail { get; set; }
        public string Name { get; set; }
    }
}

WebAPIの中身

/Controllers/Api/UsersController.csを追加。
Userを受け取って、何か処理をするという想定。
RoutePrefixを使って、URLにバージョンを埋め込む。
HttpPostを付加しているので、Routeは""になる。
これで
/api/v1/users
にPOSTすると、Postが呼び出される。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using WebAPIPostSample.Models;

namespace WebAPIPostSample.Controllers.Api
{
    [RoutePrefix("api/v1/users")]
    public class UsersController : ApiController
    {
        [HttpPost]
        [Route("")]
        public void Post([FromBody]User value)
        {
            var inputEmail = value.EMail;
            var inputName = value.Name;

            /* Do Anything */
        }
    }
}

ajaxを使用するview

/Views/Home/Index.cshtml
を編集する。

@{
    ViewBag.Title = "Home Page";
}

<div class="row">
    <div class="col-md-12">
        <h2>Ajax Postサンプル</h2>
        <div class="form-group">
            <label for="email">Email address:</label>
            <input type="email" class="form-control" id="email">
        </div>
        <div class="form-group">
            <label for="name">Name:</label>
            <input type="text" class="form-control" id="name">
        </div>
        <div class="form-group">
            <button id="btnDoPost" class="btn btn-primary">送信</button>
        </div>
    </div>
</div>
@section scripts {

<script type="text/javascript">
    $(document).ready(function () {
        $("#btnDoPost").on({
            click: function () {
                var user = { 'EMail': $("#email").val(), 'Name': $("#name").val() };
                $.ajax({
                    type: "post",
                    contentType: "application/json; charset=utf-8",
                    url: "/api/v1/users",
                    data: JSON.stringify(user),
                    cache: false,
                    async: true,
                });

                return false;
            },
        });
    });
</script>

}

ポイント

JSON.stringifyがポイント。
例えば、
data = { EMail: "hoge@fuga.com", "Name": "Hatena太郎" }
なんてしちゃうと、POSTした時に404になってしまうので注意!!

c#でfacebookのAPIを利用してfacebookページに投稿した際に、sandboxモードでハマった話。

ハマったね

タイトルの通り。
APIを使って、facebookページに投稿するのにまずハマりました。
管理者トークンが必要なのね。
それでも、いろんなサイトを見まくって投稿できるところまで行きました。

投稿できたー!
と喜んで、他の人に確認して貰ったところ
APIで投稿したのを確認したハズなのに、他の人のアカウントだと表示されない。

ログアウトしてる場合も、表示されない。

自分しか見えない投稿がPOSTされているのだ。

何故?

サンドボックスモードですって。
My Appの各アプリの名前の横にある緑色の◯ね。
これが、中抜きの◯の場合はサンドボックスモードになっていて
この状態で投稿したPOSTは、世の中に公開されない。
このモードを解除するには、
My Apps → アプリ → Settings で
Contact Emailにメールを登録して、
Status & Review で
Do you want to make this app and all its live features available to the general public?
チェックボックスをONにする必要がある。
気が付かなかった・・・・・。

PowerShellでGitショートカット

GitといえばTerminal

素敵な記事を見かけた。寿命を延ばす事ができるらしい。 postd.cc

しかし、僕はVisual Studio愛好家であり
開発環境はWindowsなのである。(実機はmacだけどね!)

WindowsといえばPowerShell

PowerShellでもエイリアス登録してショートカットすればいいいじゃない!
と思ってた時期がありました。
でも、駄目でした。コマンドラインが渡せませんでした。

Functionにしよう!

というわけで、僕が使っている設定ファイルの一部がこちら。 やたらと使うコマンド達。

remove-item alias:gcm -force
remove-item alias:gl -force
remove-item alias:gp -force
remove-item alias:gps -force

function gs(){ git status }
function ga(){ git add $args }
function gaa(){ git add -A }
function gcm(){ git commit -m $args }
function gcam(){ git commit --amend -m $args }
function gl() { git log }
function glg() { git log --graph --oneline --decorate --all }
function gld() { git log --pretty=format:"%h %ad %s" --date=short --all }
function gls() { git log --stat --decorate }
function glns() { git log --stat --name-status --decorate }
function gls() { git log --stat --decorate --grep=$args }
function gdt() { git difftool $args }
function gp() { git pull $args }
function gps() { git push $args }
function grsh { git reset --soft HEAD^ }
function grhh { git reset --hard HEAD^ }

こいつらを、$profileで出力される設定ファイルに書き込んであげてください。
remove-item aliasをしているのは、組み込みエイリアスと被っちゃうからです。
書き込んだら、.$profileで読み込み直してくださいね。

使用例はこんな感じ

gs
gaa
gcm "コメント"
gps origin master