Elixir Amazon Linux2 へのインストール方法

2020年3月10日 Posted by PURGE

$ sudo yum install elixir
読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
パッケージ elixir は利用できません。
エラー: 何もしません
[ec2-user@ip-10-0-1-175 src]$ 
$ sudo amazon-linux-extras install -y epel

Erlang Amazon Linux2 へのインストール方法

2020年3月10日 Posted by PURGE

$sudo yum install git autoconf gcc gcc-c++ glibc-devel make ncurses-devel openssl-devel unixODBC unixODBC-devel java-1.8.0-openjdk-devel 

$sudo git clone https://github.com/erlang/otp.git

$sudo chown ec2-user:ec2-user -R otp/
$cd otp
$sudo ./otp_build autoconf
$sudo ./configure #--prefix=/usr/local/erlang
$sudo make
$sudo make install

vi ~/.bash_profile
PATH=$PATH:/usr/local/erlang/bin

#sudo git clone https://github.com/elixir-lang/elixir.git
#sudo chown ec2-user:ec2-user -R elixir/
$make clean test

Flutter MaterialApp と Scaffold

2020年1月2日 Posted by PURGE

Flutter を勉強し始めた。

そこで少しハマったところを覚え書きとして記載しておく。

下記のコードでも両方動作する。

Widget build(BuildContext context) {
  return MaterialApp(
    home: Scaffold(
      appBar: AppBar(
        title: const Text('Sample Page'),
      ),
    ),
  );
}
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text('Sample Page'),
    ),
  );
}

上記2つは動作するのだが、その違いは大きい。例えば、前画面から上記のページを下記にて呼んだ場合、前者はナビゲータバーの戻るボタンが表示されない。つまり、ページのスタックに積まれるのはAppレベルではないため階層が異なる。

Navigator.push(context, MaterialPageRoute(builder: (context) => NextPage()));

少しづつだが理解を深めたいと思う。

Phoenix – React 連携

2019年12月2日 Posted by PURGE

Phoenix Project 作成

$ mix phx.new ProjectName --app project_name --no-ecto

npm モジュールインストール

$ cd ProjectName/assets/node_modules/
$ npm install --save @babel/preset-react
$ npm install --save @babel/polyfill
$ npm install --save react react-dom redux react-redux
$ npm install --save react-router-dom
$ npm install --save connected-react-router history
$ npm install --save redux-thunk
$ npm install --save axios
$ npm install --save redux-form react-hook-form
$ npm install --save react-bootstrap
$ npm install --save history
$ npm install redux-saga --save

.babelrc 設定

assets/.babelrc
{
"presets": [
"@babel/preset-env",
"@babel/react"
]
}

エントリポイント(index.js)の変更

$mv assets/js/app.js assets/js/index.js
index.js

import React from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(
<div>
Hello React!!
</div>,
document.getElementById('root')
);

webpack.config.js

entry: {
'./js/index.js': glob.sync('./vendor/**/*.js').concat(['./js/index.js'])
},
output: {
filename: 'index.js',
path: path.resolve(__dirname, '../priv/static/js')
},

index.eex の変更

lib/project_name_web/templates/page/index.eex

<section class="row">
<article class="column">
<div id="root"></div>
</article>
</section>

index.jsパスの変更

lib/project_name_web/templates/layout/app.eex

<script type="text/javascript" src="<%= Routes.static_path(@conn, "/js/index.js") %>"></script>

Elixir Timex のフォーマット

2019年6月11日 Posted by PURGE

Timex を使用した時の、現在時間フォーマット。

Timex.format!(Timex.now("Asia/Tokyo"), "%Y/%m/%d %H:%M:%S", :strftime)

GCP VMインスタンスにElixir をインストールする

2019年5月19日 Posted by PURGE

GCP VMインスタンスをCentOSで構築しようとした。あまりGCPについて詳しくないまま、インスタンスを立ち上げた。

どうも、必要なライブラリが何も入っていないのでメモ書き。

OS環境の構築

$ sudo yum install gcc
$ sudo yum install ncurses-devel
$ sudo yum install autoconf

Erlang のインストール

$ sudo ./otp_build autoconf
$ sudo ./configure
$ sudo make
$ sudo make install

インストールしたErlangのバージョンの確認

$ erl -v
Erlang/OTP 23 [DEVELOPMENT] [erts-10.4] [source-fe2b132] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [hipe]

Eshell V10.4 (abort with ^G)

Elixir で縦持ちデータ⇒横持ちデータへフォーマット変換

2019年4月30日 Posted by PURGE

ファイルのデータ構造を、縦持ちから横持ちに使用と思い、大量データなのでExcelでは無理、Pandasを使用しようと思ったが挫けた。そこで、久しぶりにElixirで処理を書いてみた。

元ファイル(.tsv)

1	Bob	Elixir
1	Bob	Java
1	Bob	Ruby
2	Tom	Elixir
2	Tom	C#
3	Dave	Python
3	Dave	Java
3	Dave	Ruby
4	Jane	Python

整形後ファイル (.tsv)

1	Bob	Elixir	Java	Ruby
2	Tom	Elixir	C#	
3	Dave	Python	Java	Ruby
4	Jane	Python		
defmodule FormatTsv do
  def convert do
    headers = [:id, :name, :lang]
    out_file = "out.tsv"
    result = "data.tsv"
      |> File.stream!
      |> CSV.decode(separator: ?\t, headers: headers)
      |> Enum.map(&(elem(&1, 1)))
      |> Enum.group_by(fn(x)-> x[:id] end)
      |> Enum.map(fn {id, values} -> 
                    "#{id}\t#{Enum.at(values, 0)[:name]}\t#{Enum.at(values, 0)[:lang]}\t#{Enum.at(values, 1)[:lang]}\t#{Enum.at(values, 2)[:lang]}\n"
                  end)
    File.write(out_file, result)
  end
end

できてしまうと、お気軽で楽しいElixirである。

Elixir の Enum.group_by

2019年4月29日 Posted by PURGE

Elixir の Enum.group_by の使用方法にもやもやしていたので覚え書き。

["Elixir","Java","C#","Python","Ruby"]
  |> Enum.group_by(fn(x)-> String.length x end)


iex(1)> FormatTsv.test
%{2 => ["C#"], 4 => ["Java", "Ruby"], 6 => ["Elixir", "Python"]}

出力例を見てわかるように、リストの要素に対して、関数 fn で 返却した値で、グループ化している。

select プルダウンの書き換え

2019年2月18日 Posted by PURGE

3年に1度は必ず実装する必要がある技術。
覚え書きです。

<html>
<head>
<title>JS</title>
    <script
        src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous">
    </script>
</head>
<body>

<select name="item" id="item">
    <option value="">りんご</option>
    <option value="">イチゴ</option>
    <option value="">バナナ</option>
</select>

<script>
    $(function(){
        $('#item').change(function(){
            $.ajax({	
        		url:"/data.json",
        		type:"POST",
                data:$("#form1").serialize(),
		        dataType:"json",
		        timespan:1000
    		}).done(function(data1,textStatus,jqXHR) {
				console.log(jqXHR.status);
				console.log(textStatus);

                console.log(data1);
                console.log(data1["data"][0].name);
				
                var data2 = JSON.stringify(data1);
				console.log(data2); 
				
                var data3 = JSON.parse(data2);
				console.log(data3);

                $("#item option").remove();
                $("#item").append("<option></option>");
                $.each(data3["data"], function(key, value){
                    console.log(key + ':' + value);
                    $("#item").append($("<option>").val(value.id).text(value.name));
                });
            }).fail(function(jqXHR, textStatus, errorThrown ) {
                console.log(jqXHR.status);
                console.log(textStatus);
                console.log(errorThrown);
                console.log('Failed');
            }).always(function(){
                console.log("complete");
            });
        });
    });
</script>
</body>
</html>
{"data" : [
    {
        "id" : "1",
        "name" : "太郎",
        "age" : "12"
    },
    {
        "id" : "2",
        "name" : "花子",
        "age" : "14"
    },
    {
        "id" : "3",
        "name" : "金太郎",
        "age" : "32"
    },
    {
        "id" : "4",
        "name" : "桃太郎",
        "age" : "47"
    },
    {
        "id" : "5",
        "name" : "赤太郎",
        "age" : "23"
    }
]}

RxSwiftのシンプルな説明

2018年8月9日 Posted by PURGE

RxSwiftのシンプルな説明

Swiftで簡単なアプリを写経するのは簡単なのであるが、やはり実用的なアプリを作成するには、レスポンシブでないと役な立たない(お客さん受けしない)よねということで、RxSwiftを学んでみた。

正直、3日間くらい、泣きながら、挫けそうになりながら、禿げそうになりながら食らいついていた。

はっきりいって理解するのがキツイ。

■ 開発環境
OS : MacOS High Sierra Version 10.13.6
Xcode : Version 9.4.1

■ サンプリアプリ
ボタンを押すとカウントアップするだけのアプリ。

スクリーンショット 2018-08-09 14.11.12.png

■ ソースコード解説
ViewController.swiftのコードを説明する。

まずは、必要なライブラリをimportする。ここでは、RxSwiftを利用する。

import UIKit
import RxSwift

先に、ラベルとボタンを配置する。
StreatBoardでも良いのであるが、敢えてコードで記述。

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Label
        let countLbl = UILabel()
        countLbl.text = "0"
        countLbl.textAlignment = .center
        countLbl.textColor = UIColor.blue
        countLbl.frame = CGRect(x: (self.view.frame.width-110)/2, y: 150, width: 110, height: 21)

        // Button
        let countUpBtn = UIButton()
        countUpBtn.frame = CGRect(x: (self.view.frame.width-100)/2, y: 200, width: 100, height: 30)
        countUpBtn.layer.borderWidth = 1.0
        countUpBtn.layer.borderColor = UIColor.blue.cgColor
        countUpBtn.layer.cornerRadius = 5.0
        countUpBtn.setTitleColor(UIColor.blue, for: .normal)
        countUpBtn.setTitle("カウントUP", for: .normal)
        countUpBtn.addTarget(self, action: #selector(ViewController.countUp(_:)), for: UIControlEvents.touchUpInside)

        self.view.addSubview(countLbl)
        self.view.addSubview(countUpBtn)
}

次に、RxSwiftの肝であるクラスを作成する。

class RxSwiftSample {

}

RxSwiftSampleクラスには、private宣言されたsubjectPublishSubject<Int>()でインスタンス化して保持しておく。それと、そのsubjectをObservableとして返すeventを定義する。
そして、実際の処理を外部から呼べる myFunc()メソッドを定義する。その中で、onNextとかいうイベントを発行する。

これが基本的な雛形という感じかな?

class RxSwiftSample {
    private let subject = PublishSubject<Int>()

    var event : Observable<Int>{
        return subject
    }
    
    func myFunc(){
        // 処理
        print("myFuncが呼ばれました。")
        // イベント発行
        subject.onNext(self.data)
    }
}

次に、このRxSwiftSampleクラスの使い方なのであるが、ViewControllerから利用できるように、RxSwiftSampleをモデルとしてmodelで宣言しておく。また、後で利用するdisposeBagも宣言しておく。

private let model = RxSwiftSample()
private let disposeBag = DisposeBag()

上記を、ViewControllerから利用する。
先ずは、順を追ってわかりやすく、ボタンに対して、countUp(_ sender: UIButton)が呼ばれるように記述する。これは特に問題はないはず。
重要なのは、ここからmodelmyFunc()を呼び出すことである。

    override func viewDidLoad() {
     //ボタンへイベント登録    
        countUpBtn.addTarget(self, action: #selector(ViewController.countUp(_:)), for: UIControlEvents.touchUpInside)
    }

    @objc func countUp(_ sender: UIButton){
        print("カウントアップ")    
        //Modelの関数呼び出し
        model.myFunc()
    }

ここから、理解が進むと思うが、model.myFunc()で処理を行うと、事前に登録されているsubscribeで通知される。そして、 subject.onNext(self.data)で渡されたパラメータも、value で受け取れる。

        //Reactive処理
        model.event.subscribe(
                onNext: {value in
                    print("ここで通知")                
                    countLbl.text = String(value)
                })
                .disposed(by: disposeBag)

これで、ようやく頭の中で処理シーケンスがつながった。
それでも理解できない場合は、私と同じように1日悩んで、print()仕掛けて、処理を追ってみると良いと思う。

やはり、このようなフレームワークやデザインパターンの理解は正直キツイ。それでも、時間を掛けて手を動かすのが、ベストプラクティスだと思う。

その助けになればと祈る。情報がちょっと時代遅れ感はあるのだが・・・。
始めたのが遅いので仕方ない。w

■ 最後に

ここに記したコードは、自分がRxSwiftの構造を理解するために作成したコードです。間違い等がございましたらご指摘願います。

下記、全ソースコードです。

import UIKit
import RxSwift


private let model = RxSwiftSample()
private let disposeBag = DisposeBag()

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Label
        let countLbl = UILabel()
        countLbl.text = "0"
        countLbl.textAlignment = .center
        countLbl.textColor = UIColor.blue
        countLbl.frame = CGRect(x: (self.view.frame.width-110)/2, y: 150, width: 110, height: 21)

        // Button
        let countUpBtn = UIButton()
        countUpBtn.frame = CGRect(x: (self.view.frame.width-100)/2, y: 200, width: 100, height: 30)
        countUpBtn.layer.borderWidth = 1.0
        countUpBtn.layer.borderColor = UIColor.blue.cgColor
        countUpBtn.layer.cornerRadius = 5.0
        countUpBtn.setTitleColor(UIColor.blue, for: .normal)
        countUpBtn.setTitle("カウントUP", for: .normal)
        countUpBtn.addTarget(self, action: #selector(ViewController.countUp(_:)), for: UIControlEvents.touchUpInside)

        self.view.addSubview(countLbl)
        self.view.addSubview(countUpBtn)

        //Reactive処理
        model.event.subscribe(
                onNext: {value in
                    countLbl.text = String(value)
                })
                .disposed(by: disposeBag)
    }

    @objc func countUp(_ sender: UIButton){
        //Modelの関数呼び出し
        model.myFunc()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

}

class RxSwiftSample {
    private let subject = PublishSubject<Int>()
    private var data = 0

    var event : Observable<Int>{
        return subject
    }

    func myFunc(){
        // 処理
        data = data + 1

        // イベント発行
        subject.onNext(self.data)
    }
}

Lovly Swift!!!