OmniAICreator/Qiita-1.07M huggingface dataset:
PhoenixでStatic Fileをサーブする

　Phoenixをお手軽なWebサーバとして使い、いろいろな検証や実験にも使って行きたいと考えました。そんな用途にはnodeとか使ってきたのですが、切り替えていきたいと思っています。Elixir Cowboyを直に使ってもいいのですがね。


# １．PhoenixでStatic Fileをサーブする

　とりあえずWebサーバという事で、htmlとか画像ファイルとかを使えればよいわけです。phoenixプロジェクトを開始します。

```
mix phx.new phoenix_static --no-ecto
```

　endpoint.exのPlug.Staticのonlyをコメントアウトします。そうすればassets/static下に置いたファイルは、htmlでもjpgブラウザから表示できるようになります。その他のrouteの変更とかは必要ありません。

```elixir:lib/phoenix_static_web/endpoint.ex
#
  plug Plug.Static,
    at: "/", from: :phoenix_static, gzip: false,
    # only: ~w(css fonts images js favicon.ico robots.txt)
#
```

やりたいことは以上です。終了。




# ２．もう少し説明

　とはいえ、わかる範囲でもう少し説明を加えておきたいと思います。

　まずは[Plug.Staticのドキュメント](https://hexdocs.pm/plug/Plug.Static.html)を参照してみます。


　よくわからない部分も多いのですが、:atはリクエストパスで、今は"/"が指定されています。:fromはサーバのファイルが置いてあるディレクトリですが、atomで:phoenix_staticと指定されています。これは"priv/static"を意味しているようです。

　つまりURLとファイルの関係は以下のようになっています。

```
http://www.mypress.jp:4001/abc.html ==> priv/static/abc.html
http://www.mypress.jp:4001/css/app.css  ==> priv/static/css/app.css
http://www.mypress.jp:4001/js/app.js  ==> priv/static/js/app.js
```


　これはphoenixのassets管理を行っているBrunchの仕様に沿った形なのでしょうか。 [Phoenixの公式ドキュメント](http://phoenixframework.org/blog/static-assets)を参照してみます。

　まずPhoenixはassets管理にBrunchを利用していると述べ、次のように続けています。ディレクトリassets/staticにあるファイルは、変更されることなくpriv/static/ にコピーされます。これは以下のbrunch-config.jsのconventionsのコメントと同じです。


```js:assets/brunch-config.js
exports.config = {
  // See http://brunch.io/#documentation for docs.
  files: {
    javascripts: {
      joinTo: "js/app.js",

      // To use a separate vendor.js bundle, specify two files path
      // http://brunch.io/docs/config#-files-
      // joinTo: {
      //   "js/app.js": /^js/,
      //   "js/vendor.js": /^(?!js)/
      // }
      //
      // To change the order of concatenation of files, explicitly mention here
      // order: {
      //   before: [
      //     "vendor/js/jquery-2.1.1.js",
      //     "vendor/js/bootstrap.min.js"
      //   ]
      // }
    },
    stylesheets: {
      joinTo: "css/app.css"
    },
    templates: {
      joinTo: "js/app.js"
    }
  },
  conventions: {
    // This option sets where we should place non-css and non-js assets in.
    // By default, we set this to "/assets/static". Files in this directory
    // will be copied to `paths.public`, which is "priv/static" by default.
    assets: /^(static)/
  },

  // Phoenix paths configuration
  paths: {
    // Dependencies and current project directories to watch
    watched: ["static", "css", "js", "vendor"],
    // Where to compile files to
    public: "../priv/static"
  },

  // Configure your plugins
  plugins: {
    babel: {
      // Do not use ES6 compiler in vendor code
      ignore: [/vendor/]
    }
  },

  modules: {
    autoRequire: {
      "js/app.js": ["js/app"]
    }
  },

  npm: {
    enabled: true
  }
};
```

　この時endpoint.exのPlug.Staticにある:only optionで指定されたもののみがroot path("/")にマウントされるようになります。:only optionを削除すればこの制限も消えます。Plug.StaticとBrunchの関係がイマイチよくわかりませんね。


　まあ、しかしPhoenixにStatic Fileをサーブさせたいときは、assets/staticにファイルを置けばOKのようです。例えばassets/static/cssにapp9.cssファイルを置けば、priv/static/css/app9.cssにコピーしてくれるので、アクセス可能になります。

以上です。
JavaScriptのプログラムをブラウザで実行する

![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/229736/1205ed13-354f-05c9-9193-5f12379f45fb.png)

　上の図はJavaScriptのプログラムを書いたHTMLのコードである。ブラウザで実行すると「Hello Javascript!」というメッセージウィンドウが表示される。

(補足)
　1.　alertというのは、JavaScriptにおいて、メッセージウィンドウを表示する命令である。
　2.　JavaScriptの命令(文)の末尾には「;」を書く。
　3.　scriptタグが登場した瞬間にjavaScript実行エンジンに引き渡される。
　4.　scriptタグを置く場所は基本的には任意である。

--------------------------------------------------------------------------------

　最初の図のコードではJavaScriptのプログラムをscriptタグで囲んで、HTMLファイルの中に記述した。この方法以外に、JavaScriptのプログラムを別ファイルに分ける方法がある。
　![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/229736/73493acf-4d68-56d8-3103-0c7b359adc77.png)



　上の図は実際に別に分けたHTMLファイルの一部のコードである。このように、別に分ける場合には「src="JavaScriptのプログラムを書いたファイル名"」と記述する。「src="…"」のようにHTMLの要素の中に書いて様々な情報を加えるものを属性と言う。
　
　別のファイルに分けるメリットは

　1.　全体が見やすい  
　デザイナーとプログラマーが共同作業する時は、デザイナーはHTMLファイルを、プログラマーはJavaScriptファイルを編集するというように担当を分けられるため、作業効率が高まる。

　2.　同じJavaScriptファイルを別のHTMLから利用できる

　JavaScriptファイルは、別のHTMLから利用することもできる。

　3.　組み合わせて利用できる
　
　1つのHTMLで、複数のJavaScriptプログラムを混ぜて利用できる。

が挙げられる。

(補足)
　JavaScriptでのコメントの記述方法は以下の通りである。
　1.　「//」と記述する。
　2.　「/＊」と「＊/」で囲む。

　※この内容は[「ちゃんと使える力を身につける　JavaScriptのきほんのきほん」](https://book.mynavi.jp/ec/products/detail/id=78352)のChapter2を簡単にまとめたものです
【イベントレポート】エンタープライズ開発におけるフロントエンドのいま -HTML5、JavaScript、TypeScript、Angular-

本記事は、
弊社スタイルズと、LPI-Japan様、カサレアル様の3社共催した『[エンタープライズ開発におけるフロントエンドのいま-HTML5、JavaScript、TypeScript、Angular-](https://www.casareal.co.jp/ls/service/eventseminar/lineup/fs180319)』(2018/3/19)のイベントレポートです。

![Main_blog.jpg](https://qiita-image-store.s3.amazonaws.com/0/223994/f826f4df-e037-07b2-4b3d-64b338ca790a.jpeg)

SI業界でもフロントエンドの技術が注目されており、
今回のセミナー参加者も多くはSIerのエンジニア職の皆様。
　
業務システム開発を行ってきたサーバーサイドのエンジニアも、
フロントエンド開発の知識が必要となってくるようになってきている雰囲気を感じます。
　

## HTML5が創り出す新たな世界

本セミナーの一発目のセッションとして、
LPI-Japanの成井理事長にご登壇いただきました。

HTML4から、HTML5にフロントエンドの技術が変化したことで、
システム開発サーバーサイドだけではなく、
フロントエンドの知識はきっても切り離せない存在になってきたと成井理事長。
　
SAPの技術は、
速度、複雑なデザインの画面を表現することなどに優れており
今後もますます需要は伸びていくとお話されていました。

また、
アイティメディアが2015年に行った「＠IT スキル調査 2015.09」の「今後取得したい資格」の項目では、
LpI-Japanが運営している
「HTML5プロフェッショナル認定試験」が一位になるなど、
HTML5が注目を浴びていることを示されました。
（https://html5exam.jp/merit/top1.html ）を参照


## HTML5/Angularによる業務系システム開発 -プロジェクト成功へのノウハウと大規模事例紹介-

休憩をはさんで、二つ目のセッションでは
スタイルズの梶原からHTML5/Angularによる業務系システム開発の大規模移行事例、開発事例をご紹介。
　
はじめに、業務システムアーキテクチャーの歴史をご紹介。
2006年ごろからきれいで柔軟なデザインをWeb画面で開発するため、Flex（Flash）システムによって開発された業務システムが多くありました。

しかしながら、2017年にAdobe Systemsから2020年末にサポート終了宣言をされました。

アップルはもとからFlashサポートをしないと宣言していたうえ、
Googleなどの主要ブラウザベンダーもサポートをしないと宣言をしました。

つまりFlash/Flexを使ったシステムは動かさせなくなるということで、もし使い続けるためには、OSやブラウザのバージョンアップをしないことが必要になってきます。

ただ、この方法では、セキュリティの懸念がかなり残ります。



###さて、移行する方法は？

![Stylez_blog.jpg](https://qiita-image-store.s3.amazonaws.com/0/223994/5dc3ceec-adb9-ef63-4626-b96bb2c02c1d.jpeg)

スタイルズでは、フロントを書き換え、
サーバーサイドは通信フォーマットを変える（AMF⇒JSONへの変更）方法で移行を行っています。

移行のときに気を付けることとしては、UIの合意を先に進めることが大切。

そしてコンポーネントを開発したら、
コンポーネントの使い方をWikiに投稿しておく。
正しい書き方の基礎を固めていくことが必要とお話をさせていただきました。

[本講演資料のご請求はこちらから](https://www.stylez.co.jp/contacts/material/)

また、
本セミナーではお話できなかったのですが、
現在スタイルズでは、Flex->HTML5をよりよく進めるための開発および実案件を進めており、
もうすぐ皆様に良いご報告ができるのではー。。と思っています。


## HTML5/Angularによる業務系システム開発 -プロジェクト成功へのノウハウと大規模事例紹介-

最後のセッションでは、カサレアルの越智様がご講演。

参加者の皆様の中から、
「フロントのFWを選ぶ基準は？」とご質問があった際、
ReactはよりJavaScriptの知識などが求められるためフロントエンドエンジニアが親しみやすいフレームワーク、
Angularはよりサーバーサイドエンジニアが親しみやすいコンポーネントを利用するフレームワークのように感じるとコメントされていらしゃいました。

![Casareal_blog.jpg](https://qiita-image-store.s3.amazonaws.com/0/223994/a8c6f70c-b3d8-3591-144a-6db1f49ff121.jpeg)

セッションの中では、Typescriptがおススメの理由を
実際にデモを交えながら、
Typescriptの活用方法を講演していただきました。


## 最後に

今回参加していただいた皆様の多くは、
基幹系業務システムや業務システムのサーバーサイド開発を行ってきたエンジニアの皆様でした。

・JavaScriptのセミナーでは、どのフレームワークが今後主流になっていくのか
・業務システムにHTML5を適用するためには
などを皆様ご興味を持たれておりました。

今後もスタイルズではAngularを活用した事例や
Flex->HTML5への移行事例について、
発信していく予定です。
　
事例やツールにご興味がある方はお気軽にご連絡ください！

![gift_blog.jpg](https://qiita-image-store.s3.amazonaws.com/0/223994/9ebbdaee-33d8-75da-c063-62619c0aa2b6.jpeg)
古いUnityでSpineを使う方法

# 概要
2017年6月15日のお話。

UnityでSpineを動かすには、Unity内にSpineのランタイムを入れる必要があります。
しかし、古いUnityの場合ちゃんとSpineのランタイムが動かないのですが、それを動かす方法の備忘録。

# 作業内容
まず、普通にspine-csharpとspine-unityを入れます。
すると、次の内容で文句を言われます。

```
Assets/spine-unity/Assets/spine-unity/Modules/Shaders/Sprite/Editor/SpineSpriteShaderGUI.cs(381,33): error CS1502: The best overloaded method match for UnityEditor.MaterialEditor.ShaderProperty(UnityEditor.MaterialProperty, string)' has some invalid arguments
Assets/spine-unity/Assets/spine-unity/Modules/Shaders/Sprite/Editor/SpineSpriteShaderGUI.cs(381,33): error CS1503: Argument #2′ cannot convert UnityEngine.GUIContent' expression to type string’
Assets/spine-unity/Assets/spine-unity/Modules/Shaders/Sprite/Editor/SpineSpriteShaderGUI.cs(659,41): error CS1502: The best overloaded method match for UnityEditor.MaterialEditor.ShaderProperty(UnityEditor.MaterialProperty, string, int)' has some invalid arguments
Assets/spine-unity/Assets/spine-unity/Modules/Shaders/Sprite/Editor/SpineSpriteShaderGUI.cs(659,41): error CS1503: Argument #2′ cannot convert UnityEngine.GUIContent' expression to type string’
```

要は、UnityEditor.MaterialEditor.ShaderPropertyがstring型じゃないぜ、コンバートもできないぜ！っていう内容です。
開発者の意図としてあっているかは不明ですが、UnityEngine.GUIContentにはtextという属性がありますので、単にそれを指定してやれば解決します。

```
SpineSpriteShaderGUI.csの381行目
古 ： _materialEditor.ShaderProperty(_pixelSnap, _pixelSnapText);
新　　：　_materialEditor.ShaderProperty(_pixelSnap, _pixelSnapText.text.text);
```

```
SpineSpriteShaderGUI.csの659行目
古 ：　_materialEditor.ShaderProperty(hasGlossMap ? _smoothnessScale : _smoothness, hasGlossMap ? _smoothnessScaleText : _smoothnessText, indentation);
新　：　_materialEditor.ShaderProperty(hasGlossMap ? _smoothnessScale : _smoothness, hasGlossMap ? _smoothnessScaleText.text : _smoothnessText.text, indentation);
```

以上
authlogicのバリデーション&エラーメッセージカスタマイズ方法3つ

#1, authlogic既存エラーのフォーマット
I18nを使ってフォーマットできる。
activemodelとほぼ同じ書き方。

```config/locales/ja.yml

ja:
  authlogic:
    error_messages:
      login_blank: "を入力してください。"
      login_not_found: "が間違っています。"
      password_blank: "を入力してください。"
      password_invalid: "が間違っています。"
    attributes:
      user_session:
        login: "ログインID"
        password: "パスワード"
```

authlogic内でエラーをaddしているところ。

```ruby/2.5.0/gems/authlogic-3.8.0/lib/authlogic/session/password.rb

def validate_by_password
  self.invalid_password = false

  # check for blank fields
  if send(login_field).blank?
    errors.add(login_field, I18n.t('error_messages.login_blank', :default => "cannot be blank"))
  end
  if send("protected_#{password_field}").blank?
    errors.add(password_field, I18n.t('error_messages.password_blank', :default => "cannot be blank"))
  end
  return if errors.count > 0
  (後略)
end
```
loginはlogin_not_foundでpasswordはpassword_invalidなのが面白い。

#2, ログイン時チェックの追加

認証条件にID、パスワード以外の項目を認証条件に追加したい時はwith_scopeでできる。

```
UserSession.with_scope(:find_options => {:conditions => "account_id = 2"}, :id => "account_2") do
  UserSession.new(user_session_params)
end
```
* errorsのキーは明示的に指定できない？
* conditionsの中はべた書きにするとべた書きされる

# 3, ログイン時バリデーション＆エラーメッセージを追加したい。
より柔軟にバリデーションを行いたい時はモデルにvalidateを追加する。

```
class UserSession
  validate :check_if_awesome

  private
  def check_if_awesome
    errors.add(:login, "must contain awesome") if login && !login.include?("awesome")
    errors.add(:base, "You must be awesome to log in") unless attempted_record.awesome?
  end
end
```

インスタンスをsaveする時にvalidationチェックしてくれる。


参考リンク
[AuthLogicでID、パスワード以外の項目を認証条件に追加する。](http://techmedia-think.hatenablog.com/entry/20091208/1260279335)
C++17： アライメント付き動的メモリ確保

これはブログ記事（http://in-neuro.hatenablog.com/entry/2018/03/26/125059 ）のダイジェスト版です。

# TL;DR

C++17ではデフォルトより大きなアライメント要求を持つ型はアライメント指定`new`が優先的に呼ばれる。これで動的メモリ確保でも（通常より大きな）アライメント要求が通るようになった。

# 背景

アライメントまわりのことを調べていたらC++17で`aligned_alloc`と`new`の新しいオーバーロードが入っていたことに気づき、少し規格書（[N4659](https://github.com/cplusplus/draft/blob/master/papers/n4659.pdf)）と元になった[P0035R4](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0035r4.html)にあたってみることにしました。§番号はN4659に対応します。

## C++11 `alignas`の問題点

`alignas`で通常より大きなアライメント指定をした変数や構造体は、そのメモリ境界にアラインされるようになります。

```cpp
alignas(32) int i;

struct alignas(32) double4 {
     double elems[4];
};
```

……ただし、動的確保した場合はこの限りではなく、`new`の結果はアライメントが保証されていません。`new`の結果はデフォルトで要求されるアライメントのうち一番大きいものに合わせられていますが、デフォルトより大きい値に関してはその限りではありません。

このため、`posix_memalign`や`_aligned_malloc`などの処理系固有の関数を使いわけるか、大きめに確保しておいて`std::align`を使ってアライメントが揃っている範囲だけを取り出して使う、というような策を取らざるを得ませんでした。

# C++17におけるアライメントサポート

C++17ではめでたく動的確保時にアライメントを指定できる機能が追加されました。C11で`<stdlib.h>`に入っていた`aligned_alloc`が`<cstdlib>`に追加され（§ 23.10.11）、`new`には`std::align_val_t`を取るオーバーロードが追加されました（§ 21.6.1）。

`std::align_val_t`は以下のように定義されています。

```cpp
namespace std {
  enum class align_val_t : size_t {};
}
```

`enum class`ですが、これは意図しない型変換を防ぐための（opaque typedef相当の）ものなので、特にenum値が定義されているわけではありません。

`new`と`delete`にはこれを取るオーバーロードが追加されました。

```cpp
void* operator new(std::size_t, std::align_val_t);
void* operator new[](std::size_t, std::align_val_t);
void operator delete(void*, std::align_val_t);
void operator delete[](void*, std::align_val_t);
void operator delete(void*, std::size_t, std::align_val_t);
void operator delete[](void*, std::size_t, std::align_val_t);
```

`align_val_t`として不適当な値を渡した場合、その動作は未定義です（§ 21.6.2）。

ではこれらのオーバーロードを手動で指定して呼び分けねばならないかというと、そうでもありません。もし通常の`new`の結果が満たすものより大きなアライメントを要求する型について`new`を呼びだせば、自動的に`align_val_t`版が、引数に`alignof(T)`が渡されて呼ばれます（§ 21.6.2.1 _Effects_、§ 21.6.2.2 _Effects_）。

「通常の`new`の結果よりも大きなアライメントを要求する型（new-extended alignment）」かどうかは、定義済みマクロ`__STDCPP_DEFAULT_NEW_ALIGNMENT__`の値を超える大きさのアライメント要求を持っているかどうかで判定されます（§ 6.6.5）。このマクロは`std::size_t`型の整数リテラルに展開され（§ 19.8）、それより大きいアライメント指定を持つ型には`new(align_val_t(alignof(T)))`が呼ばれるようになります。

## 注意点

ところで、クラスは`new`・`delete`演算子をオーバーロードできます。
そのようなクラスは、通常の`new`の結果より大きなアライメントを要求する場合でも、今まで通りクラス特異的な`new`が呼ばれます。

ユーザー定義`new`があった場合、アライメント指定に関わらずグローバルな`new`よりもそちらが優先され（P0035R4でのNitty-grittyで言及されています。§ 21.6.2.1 _Replaceable_ がこれに対応すると認識しています）、もしユーザー定義`new`にアライメント指定を取るバージョンとそうでないバージョンがあった場合は、その中でアライメント指定を取るバージョンが優先的に考慮されます。
どうしてもhomebrew,rbenvからrubyをインストールできない場合

これから素敵なrubyライフを送ろうとして、イントールに手間取ってしまい、その回避方法の記述をあまり見受けられなかったので、投稿いたします。


## 現象
rbenvのインストールまでは行えるが、rubyのインストールでBUILD FAILEDとなる。

```bash:各種コマンド
# homebrewのインストール
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

# rbenvのインストール
brew install rbenv

# rubyのインストール <- ここでエラー
# (-vオプションでエラー内容を出力するとわかりやすい)
rbenv install 2.3.5 -v
```

``` :エラー内容
ruby-build: use openssl from homebrew
Downloading ruby-2.3.5.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.5.tar.bz2
Installing ruby-2.3.5...
curl: (4) Unsupported proxy scheme for 'https://xxx.xxx.xxx.xxx:80' :libcurl is built without the HTTPS-proxy support

BUILD FAILED (OS X 10.12.3 using ruby-build 20170201)
```

プロキシの問題でダウンロードできない状態の様子。
[curl自体にhttpsプロキシの設定ができない](https://github.com/curl/curl/issues/1015)ことから生じるらしいので、~/.curlrcを確認するもhttpのプロキシのみしか設定していない・・・


## 解決（根本ではない）
[rbenvでrubyのダウンロードが遅い時の対処法](https://dev.classmethod.jp/tool/rbenv-too-slow/)を参考に直接、ダウンロードしてみる。
どうやらchacheディレクトリに圧縮ファイルをダウンロードすればrubyのインストールができるらしい。
1.~/rbenvにcacheディレクトリを作成・移動
`# mkdir ~/.rbenv/chache`
`# cd ~/.rbenv/chache`
2.対象圧縮ファイルのダウンロード
参考サイトでは、ミラーサイトのrubyだったため、筆者もミラーサイトからダウンロードしてみたところ成功。
`# curl -O https://ftp.ruby-lang.org/pub/ruby/2.3/ruby-2.3.5.tar.gz`
3.rbenv install 2.3.5
無事インストールされる

## 疑問
直接curlコマンドを打つとプロキシに引っかからないのは一体・・・

## 原因調査
rubyのインストールに関して、原因調査を行なった内容。役立つかもしれないので記載。

### brew doctor
homebrew自体に問題がないか確認
`Warning: You have a curlrc file`と出るも[問題ないとのこと](https://discourse.brew.sh/t/brew-doctor-you-have-a-curlrc-file/750)

### brew info
brew infoコマンドを実行すると仮ビルドをして内容を出力してくれるので、Dependenciesなどに記載されているものが無事にbuildされるか確認（チェックマークなら問題なし）。なければインストールしてみる。

```bash
brew info rbenv
```

```bash
rbenv: stable 1.1.1 (bottled), HEAD
Ruby version manager
https://github.com/rbenv/rbenv#readme
/usr/local/Cellar/rbenv/1.1.1 (36 files, 62.9KB) *
  Poured from bottle on 2018-03-23 at 08:52:47
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/rbenv.rb
==> Dependencies
Recommended: ruby-build ✔
==> Options
--without-ruby-build
	Build without ruby-build support
--HEAD
	Install HEAD version
```
コンポジションのサイズを設定し、その中のレイヤーをコンポジションサイズにフィットさせる。

#やりたかった事

大量のPSDファイルをインポートした後、そのPSDファイルをそれぞれコンポジション作成し、コンポジションのサイズを変更してさらに中のレイヤーをコンポジションのサイズにフィットさせる。

```js
//設定する箇所は①のみ

var selItem = app.project.selection.length;

//①コンポジションの幅と高さを指定する。
var lw=600;
var lh=750;

app.beginUndoGroup("undo");//アンドゥグループ開始
for(var i=0; i<selItem; i++){
        var myComp=app.project.selection[i];
    myComp.width=lw;
    myComp.height=lh;
    
    var myCW = myComp.width;
    var myCH = myComp.height;
    
    var layH=myComp.height/myComp.layer(1).height*100;
        myComp.layer(1).property("ADBE Transform Group").property("ADBE Scale").setValue([layH,layH,layH]);
        myComp.layer(1).property("ADBE Transform Group").property("ADBE Position").setValue([myCW/2,myCH/2])

            }
    app.endUndoGroup();//アンドゥグループの終わり
```
メモ： ONOS P4Runtimeリポジトリを覗いてみる

## これは何？

https://github.com/opennetworkinglab/onos/tree/master/protocols/p4runtime
- このあたりの構成をちょっと覗いていく感じのなにかです
- とりあえずP4Runtime越しにパケットインされた情報がどう上位に伝わっていくのか見てみた
- コンパイルや動作確認は実施していません

## P4Runtimeって何？ ONOSって何？

- 割愛

## リポジトリ構成

- ONOSは現在ビルドツールとしてBuckとMavenを併用している様子。いずれ統合されるとか。
     - Maven vs. Buck: https://wiki.onosproject.org/display/ONOS/Building+the+ONOS+Sample+Apps
- 全部Javaで書かれてます

```
onos/protocols/p4runtime/
  + api/ ・・・Javaのinterfaceが記述されたコードを格納
  + ctl/ ・・・テストとP4Runtimeの外部連携APIのコードが格納
  + model/ ・・・P4Runtimeの内部動作コードが格納
  + proto/ ・・・本フォルダ内BUCK/POMのなかで、P4.orgのPIリポジトリの.protoを引いてきてコンパイルしている
  + BUCK ・・・Buck用ファイル
  + pom.xml ・・・Maven用ファイル
```

## CTL（外部連携API）の中身

- `p4runtime/ctl/` 配下にはいろいろファイルが入っているが、ファイル名からして`P4RuntimeControllerImpl.java`と`P4RuntimeClientImpl.java`がポイントっぽいので読んで見る
  - https://github.com/opennetworkinglab/onos/blob/master/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeControllerImpl.java
  - https://github.com/opennetworkinglab/onos/blob/master/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeClientImpl.java
 
- `ControllerImpl.java`ではあんまり何もやってなくてP4Runtimeの主要な動作の実装は`P4RuntimeClientImpl.java`でやっている。
- p4Runtimeの実装は`p4.P4RuntimeGrpc`をimportしており、P4RuntimeGrpcは`p4runtime.proto`からコンパイル時に動的に生成される。
- p4runtime越しにパケットインされたパケットは一旦`PiPacketOperation`というONOS内のP4Runtime向け専用のフォーマットに変換される。`PiPacketOperation`は直接ONOSで扱えるパケット形式`InboundPacket`ではなく、これに変換するには`mapInboundPacket`を用いる。

## まとめ

- p4lang/PIの.protoを引いてきてjavaに変換して使っている。
- ODLの実装とも見比べたい。
[Rails] DBにつけた一意制約（add_index xxxs, :yyy_id unique: true）を削除する

# 概要
Railsのmigration時に加えた一意制約を解除する方法です。解除するためには、remove_indexを使えばOKです。

# 説明
例えば、テーブル名xxxs、カラム名yyy_idに対して下記のようなmigrationで一意制約がつけられているとします。

```2018zzzzzzzzzz_create_xxx.rb
class CreateXxx < ActiveRecord::Migration[5.1]
  def change
    create_table :xxxs do |t|
      t.string :yyy_id
    end
    add_index :xxxs, :yyy_id, unique: true
  end
end
```

この場合、一意制約を解除するにはremove_indexをするだけです。

## 手順
まずmigrationファイルを作成します。（__DeleteYYYIdUniqIndexFromXXX__の部分はなんでもいいです。）

```
> rails g migration DeleteYYYIdUniqIndexFromXXX
```

すると、`2018zzzzzzzzzz_delete_yyy_id_uniq_index_from_xxx.rb` というファイル名のmigrationファイルが作成されています。

この作成されたmigrationファイルを下記の様に編集します。

```2018zzzzzzzzzz_delete_yyy_id_uniq_index_from_xxx.rb
class DeleteYYYIdUniqIndexFromXXX < ActiveRecord::Migration[5.1]
  def change
    remove_index :xxxs, :yyy_id
  end
end
```


そしてmigration実行してください。

```
> rake db:migrate
```

これで終わり。


## 補足

もし、検索のためなどindexだけはつけておきたい場合は、remove_indexの後にadd_indexを追加すればOKです。

```2018zzzzzzzzzz_delete_yyy_id_uniq_index_from_xxx.rb
class DeleteYYYIdUniqIndexFromXXX < ActiveRecord::Migration[5.1]
  def change
    remove_index :xxxs, :yyy_id
    add_index :xxxs, :yyy_id
  end
end
```

# 参考
* [How can I remove a unique constraint from a database column in Rails?](https://stackoverflow.com/questions/33495396/how-can-i-remove-a-unique-constraint-from-a-database-column-in-rails)
* [Railsドキュメント remove_index](http://railsdoc.com/references/remove_index)

# 所感
普通の話です。
ストレートな日本語の手順があれば役立つと思い、書かれていなかったので書きました。
AWS ElasticBeanstalkでNode.jsを選択したのにnode: command not foundなんだが

# nodeが見つからない
AWS ElasticBeanstalk（正確にはCodeStar）を使ってWebアプリケーションを作成しよう思い、Node.jsの環境を構築しました。

SSHでのアクセスもでき、無事にインスタンスが生成されました。
（ElasticBeanstalkのインスタンスには`eb ssh`でアクセスできます）

nodeのバージョンが気になったので、おもむろにコマンドを打ってみました。

```
$ node --version

-bash: node: コマンドが見つかりません
```

コマンドが見つかりません！？
Node.jsのテンプレートを選択して構築したインスタンスなのに？

# nodeの居場所

調べたところ、こちらの質問を見つけました。

[AWS Elastic Beanstalk - Node not found after creating NodeJS instance](https://serverfault.com/questions/767866/aws-elastic-beanstalk-node-not-found-after-creating-nodejs-instance)

こちらによると、デフォルトではnodeのPATHが通っていないようです。
実体は以下にありました。

/opt/elasticbeanstalk/node-install/

```
$ cd /opt/elasticbeanstalk/node-install/
$ ls

node-v4.8.5-linux-x64   node-v6.11.5-linux-x64  node-v8.8.1-linux-x64
node-v4.8.7-linux-x64   node-v6.12.2-linux-x64  node-v8.9.3-linux-x64
node-v5.12.0-linux-x64  node-v7.10.1-linux-x64
```

これらは全てフォルダです。どうやら複数のバージョンのNodeがあるようです。
試しにv8.9.3の中身を見てみました。

```
$ cd /opt/elasticbeanstalk/node-install/node-v8.9.3-linux-x64/bin
$ ls

node  npm  npx
```

nodeがいました！

```
$ ./node --version

ｖ8.9.3
```

どうやら本物のようです。
後はPathを通せば何とかなりそうです。
heroku+ClearDBの環境でMySQL Workbenchを使ってデータ追加してみた

## はじめに

heroku+ClearDBの環境にMySQL Workbenchを使ってデータの追加をしてみた話です。
HerokuはデフォルトのデータベースはPostgreSQLを使用していますが、add-onを追加することによってMySQLを使用することもできます。
今回はClearDBへの接続をします。


## MySQL Workbenchのダウンロード

https://dev.mysql.com/downloads/workbench/ からMySQL Workbenchをダウンロードします。
このときLoginかSignUpをすることを求められますが、下のほうに小さくある

>No thanks, just start my download.

のリンクから開くことでアカウントを使用せずにダウンロードが可能です。

![mysqlworkbench.png](https://qiita-image-store.s3.amazonaws.com/0/239790/cb4580e5-89bf-cee2-3d0d-0b63e211da6c.png)

インストール完了後、MySQL Connectionsの横の＋ボタンから接続先を追加できます。

![mysqlworkbench-connection.png](https://qiita-image-store.s3.amazonaws.com/0/239790/14d0a59b-5db3-526b-aa03-79e2bdce8145.png)

この時入力する情報は

+ Connection Name
+ Hostname
+ Username
+ Password

の四つです。ポートを変えている場合はPortも変更しましょう。

上記の四つの情報はコマンドから`heroku config`と入力すると出てくる中の

`CLEARDB_DATABASE_URL`

という情報に全て含まれています。
フォーマットは

`CLEARDB_DATABASE_URL: mysql://[Username]:[Password]@[Hostname]...

となっているので必要な情報を入力して接続されたら完了です。

接続完了後、適当にクエリを書き、`Ctrl + Shift + Enter`を押すと実行できます。
NAYA　memo　ショートカット

#自分用：ショートカットメモ
###■ピボット表示
| |  |
|:-----:|:-----:|
| D     | 押しているときだけ表示|
|Insert |表示切替|

###■注視
| |  |
|:-----:|:-----:|
|F| 選択オブジェを画面に納める|
|A|表示オブジェを画面に納める|

###■スナップ
| |  |
|:-----:|:-----:|
|C|エッジに沿う|
|X|グリッドに沿う|
|J|スナップ|
|Shift+J|相対スナップ|

###■ツール
| |  |
|:-----:|:-----:|
|Q|選択 |
|W|移動|
|E|回転|
|R|拡大縮小|
|T|マニピュレーター表示|
|Ctrl+T|ユニバーサルマニピュレーター表示|
|Y|最後に使用したツールを再選択<br>（移動、回転、拡大、除く)|
|G|最後に実行したコマンドを再実行|

###■選択項目切り替え
| |  |
|:-----:|:-----:|
|F8|コンポーネントモードON/OFF|
|F9|コンポーネントモード頂点|
|F10|コンポーネントモード辺|
|F11|コンポーネントモード面|
|Ctlr+F9|選択項目を頂点に変更|
|Ctlr+F10|選択項目を辺に変更|
|Ctlr+F11|選択項目を面に変更|
|<|選択項目の縮小|
|>|選択項目の拡大|

###■ペアレント
1.　子供のオブジェクトを選択
2.　Shiftを押して親を選択（順番大事）
3.　**[Pキー]**

###■ペアレント解除
1. 解除したいオブジェクト（子供）を選択
2. **[Shift+Pキー]**

https://knowledge.autodesk.com/ja/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2016/JPN/Maya/files/GUID-30CACC9D-8FBE-4B85-8A8F-C5ADF32DDD4E-htm.html
[github] tag作成メモ

githubでリリースタグを作成する時、mergeした後にweb画面から作業をではなく、個人リポジトリに該当タグを作成し、tagもマージするやり方があるらしい。その作業のやり方をメモする。

## tagバージョンアップ

```
npm version minor
```

minorバージョンが`1.0.0`から`1.1.0`に上がる。

## タグのpush

```
git push upstream v1.1.0
```
俺言語 その24

#概要

俺言語をやってみた。
avrにアセンブラで実装してみた。
メロディを奏でる、後編。

#環境

avr studio 4
attiny85 1mhz
tera term
usb-serial

#動画

https://www.youtube.com/watch?v=UnaSQSsNCDE

#仕組み

ドレミファソラシは、cdefgabで表現。
テンポは、固定。
?=[]で、演奏。
サーボモータ駆動、RGB LED駆動とは、別プログラム。


#サンプルコード

```
10 '=16
20 ?=[ccggaag ffeeddc ggffeed ggffeed ccggaaggffeeddc   ]
30 #=20
```

以上。
モバイルホットスポットが使えなくなった時の対処

# **Windows10 Fall Creators Update**を適用したら**モバイルホットスポット**が使えなくなった。

Windows10 Fall Creators Update適用後にモバイルホットスポットを「オン」にしたら、「設定を適用しています」と出て処理中のローディングGIFアニが出たっきり、いつまだ立っても終わらない。10分くらい経ったらしれっとエラーも出ず、「オフ」の状態で終わってる。

Windows10 Fall Creators Updateには、他にも無線LANを不安定にさせる効能もあるらしい。

[バージョン1709に更新したら無線LANが不安定に!?｜マイナビニュース](https://news.mynavi.jp/article/win10tips-240/)

それを改修するUpdateをずっと待ってたんだけど、いつまでたっても出ず、調べてみたら一つの解決方法を見つけた。

# 解決方法

1.「Windows Defender セキュリティ センター」を開く
2.「ファイアウォールとネットワーク保護」を開く
3.「ファイアウォールを既定値に復元する」をクリックし「既定値に戻す」

[After update to version 1709, Internet connection sharing stays starting and consumes cpu - Microsoft Comminity](https://answers.microsoft.com/en-us/windows/forum/windows_10-performance-winpc/after-update-to-version-1709-internet-connection/ab68fb4c-a1b8-4ec3-aa18-32a104e21172)

これでまた使えるようになった。

# Windows update適用前に戻す？

Windows update適用前に戻す策もあるが、Updateしたり戻したりとか繰り返してOS大丈夫か不安っていうのと、戻してもダメだったという報告もあるので、戻すのは良作ではないかもしれない。

[Windows10 Fall Creators Updateを実施すると、SoftAPとモバイルホットスポットが使えなくなる。：立ち止まったら即死亡](http://sokushi.net/archives/20611735.html)
Laravelプロジェクトの作成と起動

# Laravelプロジェクトの作成と起動

## 環境
  - macOS HighSierra 10.13.3
  - PHP 7.2.1
  - Laravel Framework 5.6.12

## 手順
  1. Composerのインストール
  1. Laravelプロジェクトの作成
  1. 起動

## Composerのインストール
  [公式サイト](https://getcomposer.org/download/)のスクリプトを実行する。  

  Composerについては[良記事](https://qiita.com/niisan-tokyo/items/8cccec88d45f38171c94)があるのでそちらをば。

## Laravelプロジェクトの作成
  ```
  $ composer create-project --prefer-dist laravel/laravel SampleProject
  ```

  しばらく待つ。  
  
  作成されました。

  ```
  $ ls
  SampleProject
  ```

## 起動
  ```
  $ cd SampleProject
  $ php artisan serve
  Laravel development server started: <http://127.0.0.1:8000>
  ```

  [ローカル](http://localhost:8000)にアクセスして起動確認。  

  <img width="1280" alt="スクリーンショット 2018-03-26 11.49.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/241408/58ba2090-23d0-849b-272e-7fdce889b5f1.png">

  上の画面が出ればおしまい。簡単ね。
iOSのHuman Interface Guidelinesを読み直してみる💨

##動機

iOS, Swiftがすきだけど、あれそういえばiOSのガイドライン読んでないやん、、、と思っていたもののちゃんと読むことなく数ヶ月経っていました。
で、最近こんなツイートを見つけました⬇️

![スクリーンショット 2018-03-26 11.35.44.png](https://qiita-image-store.s3.amazonaws.com/0/138735/76ab7ca9-f0cc-00ef-3236-445ffa7fda8b.png)
[tweet](https://twitter.com/k_katsumi/status/977151822606491648?s=12)

このツイートに触発され
今更ですが、iOSのデザインガイドライン（Themesだけですが）をちゃんと読んでみました。
翻訳したものを自分なりに備忘録的にまとめたものです。

ではでは以下本題です。

本家：[Human Interface Guidelines iOS](https://developer.apple.com/ios/human-interface-guidelines/overview/themes/)
##iOSデザインにおける基本3原則

iOSデザインの特徴って何？、といわれると以下の3つです😏

###Clarity：明瞭性
* 見やすいテキストサイズである
* アイコンは正確でわかりやすいものである
* 装飾は不自然でなく（無駄にごちゃごちゃさせない）適切なものである
* 機能性をより高めるにはデザインが大事である
* 空白、色、フォント、グラフィックス、インターフェース要素（ボタンとかテキストボックスなど）は、重要なコンテンツを不自然なく強調し、ユーザーにインタラクティブ性があることを伝えられる

👉わかりやすさを追求し、無駄な装飾はしないようにしよう！

###Deference:（機能性.コンテンツへの）尊重
* デザインにはその内容を分かりやすく表示し、ユーザとやり取りする働きがあるが、コンテンツよりそれ自身の方が目立つようであってはいけない。機能を重視し内容を尊重することが大切である
* ベゼル（枠縁）、グラデーション、およびドロップシャドウの使用を必要最小限に抑えたインターフェイスであり、コンテンツを邪魔してはいけない

👉あくまで主役は機能やコンテンツであることを忘れずに！

###Depth：奥行き
* 重なりの表現や本物らしい動きを加えることで、要素の階層を認識させたり、活き活きとした動きを伝えたり、コンテンツへの理解がしやすくなる
* 触れたり、見つけやすくなることで、ユーザーの体験はより良いものとなり、文脈を見失うことなく、機能や次のコンテンツにアクセスすることができる
* トランジションはユーザーが深層性を理解する助けとなる

👉機能やコンテンツの文脈に適した階層構造を導入して、
ユーザーがアプリを使いやすくしよう！

##アプリのアイデンティティを高めるための6原則

上記の主要3原則に加えて。iOSのデザインガイドラインでは、アプリのインパクトやリーチを最大化するために気をつけるべき、以下の6つの原則を定義しています😏

###Aesthetic Integrity：美しさへのこだわり
* アプリの見た目と挙動は、機能とうまく整合性がとれているべきだ。機能にフォーカスを当てるべきアプリでは、その機能に集中できるようなUI（過度な装飾や行き過ぎたアニメーションは控える）にすべきであり、一方でゲームのようなアプリでは、楽しくてわくわくするような、心を掴む見た目にすべきである

👉機能・コンテンツとデザインは独立したものではないので、それらが一致したイメージを提供しているか確認しよう！

###Consistency：一貫性
* 一貫したアプリとは、標準のインターフェイス要素、見慣れたアイコン、標準的なテキストスタイル、統一された単語を使用し、違和感のない規則やパラダイムを構築するものである。アプリはユーザーが想定するような形式で機能や挙動を提供すべきである

👉一貫性を持たせてユーザーに無駄な意志力を使わせないように！

###Direct Manipulation：直接操作性
* 画面上のコンテンツを直接操作することで、ユーザーの エンゲージメントが高まり、何が起きているかを理解しやすくなる。直接操作を行うことで、ユーザーは自分が取ったアクションの結果をすぐにはっきりと理解することができるようになる。例えば、要素の並べ替えでは直接指でドラッグして移動できるようにすべきだ。

👉コンテンツを直接操作できるようにしてユーザーが自然なアクションを行えるようにしよう！

###Feedback：フィードバック
* フィードバックはユーザーが取ったアクションを認識し、アクションによって起こった結果を伝える役割がある。インタラクティブなUIはタップされたときにすぐにハイライト表示され、時間のかかる操作のステータスはプログレスバーが表示される。アニメーションやサウンドはアクションの結果をはっきりと示すのに役立つ。

👉アクションに対してはフィードバックを！フィードバックの種類も考えよう！

###Metaphors：比喩
* アプリ内のオブジェクトやアクションに対してユーザーが経験したことのある比喩（メタファー）を用いることで、学習の敷居を下げることができる。iOS上ではメタファーがうまく機能してる。例えば、画面からはみ出た要素があると、そこはスワイプして移動できるスクロール（巻物）と認知することができます。ボタンやスイッチ、スライダーは現実にあるオブジェクトを模しているので、一目見てそれがどのように作用するかを理解することができます。

👉日常のアクション、ものを使ってメタファー効果を利用しよう！

###User Control：ユーザーコントロール
* iOS全体では、アプリではなくユーザーがコントロールする側である。一連のアクションを提案したり、危険な結果について警告したりするアプリもあるが、通常、意思決定をアプリが行うのは間違いである。ユーザーのコントロール範囲を増やすことと、望まない結果を避けることのちょうどよいバランスを最高のアプリは見出している。インタラクティブ要素がよく見かけたり想定できたりするもので、（コンテンツが）削除されたことが確認でき、（処理中だとしても）操作をキャンセルするのが簡単であることで、ユーザーは自分たちがそのアプリをコントロールしている感覚を感じられる。

👉ユーザーの意思決定を尊重しよう！

##おわりに

抽象的なものが多く、これを見たからといってすぐにデザインが固まるというものではないですが、
iOSが求めるエッセンスを詰め込んだシンプルかつ独自性のあるガイドラインだと思いました！
ではでは（・◇・）/~~~
tmuxをCentOS6にインストール

# 概要
2016年11月4日のお話。

tmuxをCentOS6にインストールしようと思いますが、折角なので現在の最新版(2.3)をソースインストールすることにします。

# 作業手順
まずはtmuxのサイトへ行って最新版をダウンロード。
https://tmux.github.io/

左上にあるDownloadでURLをコピってwgetして、とりあえずconfigureしてみます。

```
$ cd /usr/local/src/
$ mkdir tmux
$ cd tmux
$ wget https://github.com/tmux/tmux/releases/download/2.3/tmux-2.3.tar.gz
$ tar zxvf tmux-2.3.tar.gz
$ cd tmux-2.3
$ ./configure
 
configure: error: "libevent not found"
```

libeventが無いと怒られました。
ふむ、、、ではlibeventをソースインストールしましょう。

http://libevent.org/

やたら見た目がアレなサイトへ行き、Download–Stable releasesからlibevent-2.0.22-stable.tar.gzをダウンロードします。
そして何も考えずにとりあえずconfigureしてみます。

```
$ cd /usr/local/src/
$ mkdir libevent
$ cd libevent
$ wget https://github.com/libevent/libevent/releases/download/release-2.0.22-stable/libevent-2.0.22-stable.tar.gz
$ tar zxvf libevent-2.0.22-stable.tar.gz
$ cd libevent-2.0.22-stable
$ ./configure
```

特に問題無さそう。
そのままmakeします、そんなに時間はかかりません。

```
$ make
# make install
```

ルートでインストール

そして再度tmuxのconfigureに挑戦します。

```
$ cd /usr/local/src/tmux/tmux-2.3
$ ./configure

configure: error: "curses or ncurses not found"
```

今度はcursesかncursesが無いそうだ・・・。
ふむー、ではncurses-develをyumで入れてしまいましょう。

```
# yum install ncurses-devel
```

そしてもう一度tmuxのconfigureを！

```
$ cd /usr/local/src/tmux/tmux-2.3
$ ./configure
```

今度はうまくいきました！
makeしてインストールします、こちらもそんなに時間はかかりません。

```
$ make
# make install
```

これでtmux自体は入りましたが、まだ設定ができていません。
設定ファイルを作って読み込めばOKです。.tmux.confという名前でホーム直下に置けばいいかと思います。

```
$ vi ~/.tmux.conf
```

私の場合の設定はこんな感じ。

```
bind r source-file ~/.tmux.conf \; display-message "Reload Config!!"

set-option -g history-limit 10000
set-option -g status-interval 5

set-option -g mouse on
bind -n WheelUpPane if-shell -F -t = "#{mouse_any_flag}" "send-keys -M" "if -Ft= '#{pane_in_mode}' 'send-keys -M' 'select-pane -t=; copy-mode -e; send-keys -M'"
bind -n WheelDownPane select-pane -t= \; send-keys -M
```

おしまい。
Juman++インストール[Ubuntu 16.04 LTS]

mecabをubuntu 16.04 LTSにインストールしたので、以下に覚書として記載しておきます。

#前提条件
- Ubuntu 16.04 LTS
- LANG=ja_JP.UTF-8

#ダウンロード
[juman++のサイト](https://github.com/ku-nlp/jumanpp)からアーカイブをダウンロードしてきます。
私がダウンロードしてきた時の最新版は、jumanpp-2.0.0-rc2.tar.xz でした。

#インストール

適当なディレクトリにアーカイブを解凍します。

```console:Terminal
$ tar xvf jumanpp-2.0.0-rc2.tar.xz 
```
解凍後、jumanpp-2.0.0-rc2 というディレクトリがカレントにできるので、その中に build というディレクトリを作成します。

```console:Terminal
$ cd jumanpp-2.0.0-rc2/
$ mkdir build
```
作成した build ディレクトリに移動してから、juman++をコンパイルします。

```console:Terminal
$ cd build/
$ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local
$ make
```
※CMAKEをインストールしていない場合は、"sudo apt install cmake"でCMAKEをインストールして下さい。
※DCMAKE_INSTALL_PREFIXでは、インストール先を定義します。私は、"/usr/local"としました。

無事にコンパイルが完了したら、インストールします。

```console:Terminal
$ sudo make install
```

#動作確認
動作確認をしてみます。

```console:Terminal
$ echo "覚書として記載しておきます。" | jumanpp 
覚書 おぼえがき 覚書 名詞 6 普通名詞 1 * 0 * 0 "代表表記:覚え書き/おぼえがき カテゴリ:人工物-その他"
と と と 助詞 9 格助詞 1 * 0 * 0 NIL
して して する 動詞 2 * 0 サ変動詞 16 タ系連用テ形 14 "代表表記:する/する 自他動詞:自:成る/なる 付属動詞候補（基本）"
記載 きさい 記載 名詞 6 サ変名詞 2 * 0 * 0 "代表表記:記載/きさい カテゴリ:抽象物"
して して する 動詞 2 * 0 サ変動詞 16 タ系連用テ形 14 "代表表記:する/する 自他動詞:自:成る/なる 付属動詞候補（基本）"
おき おき おく 接尾辞 14 動詞性接尾辞 7 子音動詞カ行 2 基本連用形 8 "代表表記:おく/おく"
ます ます ます 接尾辞 14 動詞性接尾辞 7 動詞性接尾辞ます型 31 基本形 2 "代表表記:ます/ます"
。 。 。 特殊 1 句点 1 * 0 * 0 NIL
EOS
```

以上です。
Typescriptでの継承可能なSingletonの実装

Typescriptに限りませんが、アプリケーション全体で管理したいデータや状態を管理する方法として、Singletonパターンを使うことがあると思います。
良く○○マネージャーとか呼ばれる機能がこれに当たります。

TypescriptでもSingletonを実装する方法は探せばいくつか記事がみつかります。
しかし、Singleonのベース機能自体は基底クラスとして実装しつつ、これを継承して使用する方法を探してもそれらしい記事が見つかりませんでした。

いろいろ試行錯誤していたところ、それらしい機能が実装できたので備忘録を兼ねて投稿しておきます。

さっそくですがコードです。



``` typescript:基底クラス


export default class SingletonBase  {

  private static _instance: SingletonBase = null;

  constructor() {
    let extendedClass = (<any>this).__proto__.constructor;

    if (extendedClass._instance){
      throw new Error("must use the instance.");
    }

    extendedClass._instance = this;
  }

  public static instance(): any{
    if (this._instance === null){
      this._instance = new this();
    }

    return this._instance;
  }

}

```


使用方法としては次のようになります。（例として、何らかのモードを管理するクラスを想定）

``` typescript:継承方法

import SingletonBase   from "./SingletonBase";

export class ModeManager extends SingletonBase{

  private mode: string = "modeA";

  public setMode(__newMode:string):void{
    this.mode = __newMode;
  }

  public getMode():string{
    return this.mode;
  }

  // 型を特定するため(コード補完するため)にこれだけは必要
  public static instance(): ModeManager {
    return super.instance();
  }

}

```

あとは、以下のように使えます

``` typescript:main.tsなど

import ModeManager  from "./ModeManager";

ModeManager.instance().setMode("modeB");

let currentMode:string = ModeManager.instance().getMode();

console.log(currentMode);  // ---> "modeB"が表示される

```



本当は継承先クラスでinstanceメソッドのオーバーライドの部分も書きたくなかったのですが、継承元がanyになっているために残ってしまいました。
それでも必ず書くロジックは減るので、ないよりはマシかなと。

ジェネリック的なものを使えば解消できる気もする（まだよく理解できてない）ので、そのあたり勉強したら記事をアップデートしたいと思っています。

ハック的なやり方であろうことは認知しておりますし、正直公にしていいものか悩みましたが、ツッコミがあったらそれはそれで正しい知識が広まるきっかけになるのでよいかなと思っています。
なので、指摘等あれば是非お待ちしています。
ERR_CONTENT_LENGTH_MISMATCH

2016年10月28日のお話。

Chromeだけで出るエラーに遭遇しましてConsoleに出力されるエラーメッセージです。
WEBAMP2というSPAを作っているんですがこのエラーに随分悩まされました。
WEBAMP2はWEB上でサウンドを再生するWEBアプリなんですが、このエラーと共にサウンドが止まってしまうわけです。
最初この問題に遭遇したときはnginxを使っていたんですが結局解決できずに泣く泣くApacheに変更することで無理矢理回避していました、今回この問題が発生したきっかけはVPSを引っ越ししたときにWEBAMP2も引っ越したことによるんですが、何故かApacheでも発生するようになってしまったわけです。
コレ、原因はCentOS6についてる標準のPHP5.3の場合のみ発生するということがわかりました。
試しにremiのPHP5.4にしたら理由は分かりませんが問題が出なくなりまして、折角なのでついでにPHP5.6にしときました。5.6でも問題は出ないみたいです。

かなり凶悪で大ハマりした問題だったので、同じ問題で悩んでいる人が居ればPHPのバージョンアップを試してみるといいかもよ！っていうお話しでした。
新しいGoogle SitesでPageごとのアクセス制御を可能にする

# 目的
GSuiteを利用している企業や勉強会などで[Google Sites](https://support.google.com/sites/?hl=ja#topic=7184580)でInternal Wikiを作ると、サーバー立てるなどの面倒な処理がいらず非常に便利である。[旧Google SitesにはあったPageごとのアクセス制御機能](https://sites.google.com/a/whps.org/google-sites/tutorials-videos/page-level-permissions)がまだ実装されていないので、少しトリッキーな方法で実現する。

# Google Sitesのメリット
- 自前サーバーを用意せずに簡単にサイトを構築できる
- Google Docとの連携が容易で、Driveより情報を構造化できる
- GSuiteアカウントにログインすれば閲覧・編集できるので、Remote Workにも適している
- Site自体はGoogle Driveの容量を使わない(Google Docも同様)
- 手間暇かけずに**それっぽい**サイトができる

# 手順概要
- Google Sitesでアクセス制御したいサブページを作成
- 秘匿したいサブページをnavigationから消す
- URLは生きているので直接アクセス

# 詳細
1. まずは適当にサイトを作ります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/234668/6c944419-b600-0990-164a-2394cb192665.png)
2. 非公開にしたいページを選択し、**Hide from navigation**を選択
![図1.png](https://qiita-image-store.s3.amazonaws.com/0/234668/a3ade3bc-2dde-d1e1-58c9-6a3b81e30d87.png)
3. 無事にNavigationから消えていることを確認
![image.png](https://qiita-image-store.s3.amazonaws.com/0/234668/b4c434a0-d2dd-b717-2c36-cc3d4c8447c8.png)
4. 直接URLを打ち込む。PageのタイトルがPathになる。ただし、**大文字は小文字にして入力**しないと404になってしまう。今回のケースではPageのPathが`非公開 > 絶対勝てるSplatoon裏技`なので、アクセスするためのPathは```https://sites.google.com/{アカウント名}/{Google Sites名}/非公開/絶対勝てるsplatoon裏技```となる。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/234668/fee0c67c-7e32-f117-2a91-06876ace2795.png)
5. これにより、URLを知っているメンバーのみが情報にアクセスできるようになり、擬似的にアクセス制御を行えるようになった。

# あとがたり
このようなURLを知っている人にのみ公開系の制御はある(Qiitaの限定共有もそうですね)が、やはりSensitiveな情報は仕組みとしてきちんと制御したい。[今後実装される予定があるらしい](https://sites.google.com/view/newsitestesting/more-info/update-deprecation-timeline)ので、それを震えて待ちますか。

# 参考リンク集
- [参考にしたやり方ページ](http://sheilspiel.blogspot.jp/2017/08/new-google-sites-page-level-permissions.html)
- [旧Google SitesでのPageごとアクセス制御](https://sites.google.com/a/whps.org/google-sites/tutorials-videos/page-level-permissions)
- [新版でも実装予定である情報](https://sites.google.com/view/newsitestesting/more-info/update-deprecation-timeline)
mecabインストール[Ubuntu 16.04 LTS]

mecabをubuntu 16.04 LTSにインストールしたので、以下に覚書として記載しておきます。

#前提条件
- Ubuntu 16.04 LTS
- LANG=ja_JP.UTF-8

#インストール
以下、インストール手順です。

```console:Terminal
$ sudo apt install mecab
$ sudo apt install libmecab-dev
$ sudo apt install mecab-ipadic-utf8
```

#動作確認
動作確認をしてみます。

```console:Terminal
$ echo "覚書として記載しておきます。" | mecab
覚書	名詞,一般,*,*,*,*,覚書,オボエガキ,オボエガキ
として	助詞,格助詞,連語,*,*,*,として,トシテ,トシテ
記載	名詞,サ変接続,*,*,*,*,記載,キサイ,キサイ
し	動詞,自立,*,*,サ変・スル,連用形,する,シ,シ
て	助詞,接続助詞,*,*,*,*,て,テ,テ
おき	動詞,非自立,*,*,五段・カ行イ音便,連用形,おく,オキ,オキ
ます	助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス
。	記号,句点,*,*,*,*,。,。,。
EOS
```

以上です。
Curlのアップグレード

# 概要
いつもどうやるのか忘れてしまうので、単純にメモ代わりです。
src.rpmを使ってちょちょいと入れてしまおうと思います。
ちなみに環境はCentOS6

# 作業手順
作業前に必要なものを予めインストールしておきます。

```
# yum install openssl-devel libmetalink-devel libssh2-devel c-ares-devel stunnel perl-Time-HiRes
```

次のURLから最新のrhel6.src.rpmを探します。
http://mirror.city-fan.org/ftp/contrib/sysutils/Mirroring/

どうも現時点（2016年12月2日）ではcurl-7.51.0-3.0.cf.rhel6.src.rpmが最新のようです。

```
$ cd /usr/local/src/
$ mkdir curl
$ cd curl
$ wget http://mirror.city-fan.org/ftp/contrib/sysutils/Mirroring/curl-7.51.0-3.0.cf.rhel6.src.rpm
```

リビルドします。

```
$ rpmbuild --rebuild curl-7.51.0-3.0.cf.rhel6.src.rpm
error: Failed build dependencies:
        libnghttp2-devel is needed by curl-7.51.0-3.0.cf.rhel6.x86_64
        nghttp2 is needed by curl-7.51.0-3.0.cf.rhel6.x86_64
        multilib-rpm-config is needed by curl-7.51.0-3.0.cf.rhel6.x86_64
```

あら、まだ足りないみたいですね。
不足しているものをインストールします。

```
# yum install libnghttp2-devel nghttp2 multilib-rpm-config
```

再度リビルド

```
# rpmbuild --rebuild curl-7.51.0-3.0.cf.rhel6.src.rpm
```

環境によると思いますが十数分くらい時間がかかりました。
その後、インストール

```
# cd
# rpm -Uvh rpmbuild/RPMS/x86_64/curl-7.51.0-3.0.cf.rhel6.x86_64.rpm rpmbuild/RPMS/x86_64/libcurl-7.51.0-3.0.cf.rhel6.x86_64.rpm rpmbuild/RPMS/x86_64/libcurl-devel-7.51.0-3.0.cf.rhel6.x86_64.rpm
```

できあがり。
unicornについ

Ruby on Railsアプリケーションを本番環境で動作させるためのアプリケーションサーバとして、unicornがある

unicornは、Railsなどでつくられたアプリケーションを動かすアプリケーションサーバです。

unicornはプロセス上で動作するサーバで、プロセスには(1)masterプロセスと(2)workerプロセスがあります。 masterプロセスがアプリケーションのソースコードを保持しており、これをforkしたworkerプロセス群が実際のリクエストを処理します。

ソースコードをロードするのがmasterプロセスのみであるため、起動が早い、デプロイ時のダウンタイムがない、などのメリットがあります。

相違機能である　nginxとの違い

nginxはクライアントからのリクエストを受け、なんらかの処理（SSLや圧縮など）を行なうWebサーバです。

単にアプリケーションを動作させるだけなら、nginxは必要ありません。
実際に、開発環境などではnginxなどなくても、unicorn（あるいはWEBrick、Puma）単体で動作します。

開発環境と本番環境の違いはリクエストの数で、unicornはworkerプロセスがせいぜい数個であるのに対し、nginxは数千ものコネクション数が存在します。 もしnginxを置かなければ、ネットワークの遅いクライアントが同時に接続してきたときにunicornプロセスをすべて占有してしまい、その他のクライアントからの接続を受け付けられなくなってしまいます。

nginxを置くことで、たくさんのリクエストを受け、それをunicornのプロセスにいい感じに振り分けています。
AWS S3 にデータを蓄積しながら、Google Cloud Storage にもデータを蓄積しよう

前回は、Apache NiFi を使って、GCP GCS にデータを蓄積する方法を紹介しました。

- [Apache NiFi を使って Google Cloud Storage にデータを蓄積しよう](https://qiita.com/kkitase/items/408cb9019dd25a74f453)

今回は、「異なる環境でデータフローを管理したい」「データ基盤環境を徐々に移行したい」という要望があるときに、Apache NiFi の "Site to Site" という機能が、とっても便利なので紹介します。ここでは、AWS S3 にデータを書き込みながら、同じデータを Google Cloud Storage (GCS) に書き込むようなデータフローを試してみたいと思います。

![nifi_aws-gcp.png](https://qiita-image-store.s3.amazonaws.com/0/42406/99fb52d4-2311-1afc-58a3-4bf1f0214420.png)
（図には、RedshiftとBigQuery のアイコンがありますが、ここでは試しません。）


### GCP 側の設定 

- [Apache NiFi と Google Cloud Storage の連携](https://qiita.com/kkitase/items/408cb9019dd25a74f453) を参考に NiFi をインストール

- GCP のファイアウォールで、NiFi の Site to Site で利用するポート（任意のポート）をオープン（ここでは9990 を使用）
- GCP のファイアウォールで、NiFi にアクセスするポートをオープン（ここでは デフォルト: 8080 を使用）

- NiFi インスタンスの、nifi.properties 下記のように設定

```
nifi.remote.input.host=<データを受信する側のホスト>（今回 GCP側）
nifi.remote.input.secure=false
nifi.remote.input.socket.port=9990 (site to site で使用する任意のポート)
nifi.remote.input.http.enabled=true
nifi.remote.input.http.transaction.ttl=30 sec
```
- PutGCSObject Processor をドラッグ・アンド・ドロップし、[Apache NiFi と Google Cloud Storage の連携](https://qiita.com/kkitase/items/408cb9019dd25a74f453) を参考に設定
  
- Input port をドラッグ・アンド・ドロップし、作成
<img width="1271" alt=" 2018-03-26 23.14.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/42406/e60a03a0-9384-5db1-07a9-2815e240ac3b.png">

- Input port processor と PutGCSObject Processor を接続
<img width="1275" alt=" 2018-03-26 23.35.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/42406/1a47c834-ca45-b7f4-1081-5a062c3ecb47.png">

- すべての Processor を実行し、正しく動作しているか確認


### AWS 側の設定 

- [Apache NiFi と Google Cloud Storage の連携](https://qiita.com/kkitase/items/408cb9019dd25a74f453) を参考に NiFi をインストール

- AWS のセキュリティグループの設定で、NiFi にアクセスするポートをオープン（ここでは デフォルト: 8080 を使用）

- GenerateFlowFile を作成
GenerateFlowFile Processor をドラッグ・アンド・ドロップし、作成

- Remote Process Group を作成
Remote Process Group Processor をドラッグ・アンド・ドロップし、``URLs`` を設定
``URLs`` は相手側のインスタンスです。
<img width="757" alt=" 2018-03-26 23.46.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/42406/f93d5db0-f7cf-b82b-f407-cd9b7ed4a8db.png">

- PutS3Object Processor を作成
PutS3Object Processor をドラッグ・アンド・ドロップし、``Bucket``と``Access Key``、``Secret Key`` を設定
<img width="798" alt=" 2018-03-26 23.37.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/42406/e079250c-e6e7-7f5d-2ca2-7bdd40948d42.png">

- GenerateFlowFile Processor と PutS3Object Processor を接続
<img width="1274" alt=" 2018-03-26 10.57.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/42406/401ba235-2cb3-26ee-7a0f-9e2e1ce82643.png">

- Remote Process Group を右クリックし、``Enable transmission`` をクリックして、Remote Process Group Processor を有効に
<img width="512" alt=" 2018-03-26 23.22.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/42406/c7ee6065-6da2-023f-3e4b-704007f4abad.png">

- すべての Processor を実行し、AWS S3 と GCS にデータが正しく書き込まれているか確認

少し、はしょって書いているので、不明な点があれば、 [@kkitase](http://twitter.com/kkitase) まで。

以上
deviseについて

deviseはログイン認証機能を提供するgemでRuby on Railsでも使用できる。
会員登録からログイン認証が必要なページの管理等が容易に行える


deviseと同様な機能として使われるのがAuthlogic

Authlogicは認証の部品しか提供してくれないのでカスタマイズしやすいが、
１つ１つの部品部品を繋げていくのは自分ですることが必要である

Deviseは勝手に色々やってくれるので実装が少なくて済む分、
少し中身が分かりづらい

Authlogicはシンプルなものになっていて、そのかわり自分で実装しないといけない箇所は多いといった印象を受けました。
WindowsServer2016のPowerShellでADDSの停止と開始

# 概要
主に検証時にWindows Server2016ののADDSを
停止したり開始したい時のためのメモです
 
## ADDSのサービスの情報を取得
`Get-Service NTDS`
<img width="334" alt="get_service.png" src="https://qiita-image-store.s3.amazonaws.com/0/210923/b4d33497-d594-296e-1177-898eeff6f428.png">


## ADDSに依存するサービスも含めて取得
__※　–DependentServices オプションで依存するサービスも取得__
`Get-Service NTDS –DependentServices`
<img width="342" alt="get_service_dep.png" src="https://qiita-image-store.s3.amazonaws.com/0/210923/e87d7df4-7771-e336-55eb-95493d1960f4.png">


## ADDSに依存するサービスも含めて停止
__※ –Force オプションで依存するサービスも停止__
`Stop-Service NTDS –Force`

## ADDSを開始
`Start-Service NTDS`

## 余談：依存するサービスを意識せずADDSを停止した時
`Stop-Service NTDS`
<img width="708" alt="stop_service_error.png" src="https://qiita-image-store.s3.amazonaws.com/0/210923/76425d45-aab9-1f7c-a94a-3733384187c4.png">
Nginxで国外からのWEBアクセスを遮断

# 事の発端
サーバが落ちてたので何気に再起動させたんですが、その数時間後また落ちる・・・。
何故ー？と思って原因を調べてみたところ、国外からのスパムがヒドくて落ちてたようです。
以前ちょろっとスパム対策してたので割と放置してたんですが甘かったです。
今回更にスパム対策を色々試してみたんですが、ボットの投稿がウザいとかそういう問題じゃないんです・・・、アタックのアクセスが多すぎてサーバ落ちるのが問題。

# 対策の方針
WPのサイトを運営しているのが良くないようでかなり攻撃されます。
相当頭に来たので、ブチ切れモードで海外からのWEBアクセスを全て遮断してやりましょう！ｗ

今回の対策はNginx側で国内IPのアクセスのみを許可して他を全て切り捨てるという強引な方法になります。

# 対応内容
まず、IPアドレスのリストをダウンロードします。
このサイトからダウンロードできますね、今回は「cidr.txt.gz」というものを使わせて頂くことにします。
http://nami.jp/ipv4bycc/

<pre>
$ cd /usr/local/src ← 書き込み権限アリにしてあります
$ mkdir ip_list
$ cd ip_list
$ wget http://nami.jp/ipv4bycc/cidr.txt.gz
$ gunzip cidr.txt.gz
</pre>

次にNginx用の設定ファイルを作成して、Nginxの基本の設定ファイルを書き換えます。

```
$ su -
# cd /usr/local/src/ip_list
# sed -n 's/^JP\t\(.*\)/allow \1;/p' cidr.txt > /etc/nginx/allowip.conf
# vi /etc/nginx/nginx.conf
```

こんな感じ

```nginx
http {
    ・・・
    # Allow IP
    include /etc/nginx/allowip.conf;
    deny all;
    
    include /etc/nginx/conf.d/*.conf;
}
```

そしてNginxを再起動すれば海外からのアクセスを全て遮断することになります。
Apacheと違ってallowとdenyを書く順序は逆になるみたいですね。 ^^A

ちなみに余談ですが、WPの場合は管理画面だけ個別にアクセス制限することもできます。
そうしたい場合はこんな感じの設定をそれらしい該当箇所に書けば良いかと思います。
※ただしこの場合は海外からのアクセスを受け入れる形になるのでタイトル詐欺です。

```nginx
    location ~* /wp-login\.php|/wp-admin/((?!admin-ajax\.php).)*$ {
        include /etc/nginx/allowip.conf;
        deny all;
        ・・・
    }
```

あとは再起動。

```
# /etc/init.d/nginx restart
```

おわり
jqueryについて

javascriptと比較して、
jQueryの方が記述量が短く済み、気軽に記述出来るの

jQueryをダウンロードし、HTML内にリンクさせるだけですぐに実装できる

様々なブラウザに対応しているため、普通はブラウザへの対応を意識しなければなりませんが、あまり意識 しなくても大丈夫

デメリットはファイルのサイズを縮小化してファイルを軽くすることはできるが、読み込む際にページの表示時間が遅くなる場合がある

人気は下降気味。読み込みの遅さが起因している
　元々、jQueryに搭載されていたメソッドは、その殆どがネイティブメソッドで賄えるようになってきた
バックアップを世代管理

# 概要
バックアップデータを世代管理するスクリプトです。
サーバの引っ越しとかでよく無くなるので、メモがわりに投稿。

# 使い方
下記のシェルスクリプトをcronで朝4時とかにセットする想定。
（もし流用するのであれば勿論少し設定が必要です）

```sh
#!/bin/bash

PATH=/usr/local/sbin:/usr/bin:/bin

# バックアップ先
BACKUP_DIR=/path/to/backup/dir/

# バックアップ対象
TARGET_DIR=/path/to/dir/
TARGET_FILES=(file1 file2 file3)

# 今日の日付を取得する
DATE=`/bin/date '+%Y%m%d'`

# 削除する日付を取得する（この場合は10日前）
DELETE_DATE=`/bin/date -d '10 day ago' +%Y%m%d`

# バックアップ対象のディレクトリへ移動
cd ${TARGET_DIR}

# バックアップ
for TARGET_FILE in ${TARGET_FILES[@]}; do
    # バックアップ対象ファイルを圧縮して保存
    tar zcf "${BACKUP_DIR}${TARGET_FILE}_${DATE}.tar.gz" ${TARGET_FILE}

    # 過去のバックアップを削除
    if [ -f "${BACKUP_DIR}${TARGET_FILE}_${DELETE_DATE}.tar.gz" ]; then
        rm -rf ${BACKUP_DIR}${TARGET_FILE}_${DELETE_DATE}.tar.gz
    fi
done
```

# 定期的にバックアップ
深夜4時とかにcronをしかけておきます。
<pre>
0 4 * * * sh /path/to/backup/dir/backup.sh > /dev/null 2>&1
</pre>
[Flow Type] 存在型 Existential Type

### flowの存在型の定義

> An existential type is used as a placeholder to tell Flow to infer the type.


存在型がFlowに自動的に推測してくれっと指示するためのプレースホルダである。

次の例では、実際に渡されたdataの`1`であるため、自動的に`T`が**number**と認識される。そのため、戻り値を`ParamStore<boolean>`にすると、`flow check`エラーとなる。

```javascript

// @flow
function makeParamStore<T>(storeClass: Class<ParamStore<T>>, data: T): * {
  return new storeClass(data);
}
(makeParamStore(ParamStore, 1): ParamStore<number>);
(makeParamStore(ParamStore, 1): ParamStore<boolean>); // failed because of the second parameter

```

### 任意型と存在型の違い

任意型がなんでも良いので、型安全チェックが失いう。存在型に違う型のデータを入れると怒られる。

次の例では、constructorで先にisOfflineに`boolean型`を入れたので、次の`string`を入れると、`flow check`エラーとなる。

```javascript

// @flow
class DataStore {
  data: *; // If this property weren't defined, you'd get an error just trying to assign `data`
  constructor() {
    this.data = {
      name: 'DataStore',
      isOffline: true
    };
  }
  goOnline() {
    this.data.isOffline = false;
  }
  changeName() {
    this.data.isOffline = 'SomeStore'; // oops, wrong key!
  }
}
```

### 感想
- １つの変数に違う型のデータを入れたい場合、`any`を使う
- データの型を１つに限定したい場合、型をはっきり記載する
- 冗長な記載を避けたい場合、存在型`*`を使っても良い

### 参考記事
- [flowの存在型](https://flow.org/en/docs/types/utilities/#toc-existential-type)
- [Haskellの存在型](https://ja.wikibooks.org/wiki/Haskell/%E5%AD%98%E5%9C%A8%E9%87%8F%E5%8C%96%E3%81%95%E3%82%8C%E3%81%9F%E5%9E%8B)
iPhoneのメッセージアプリでテキストメール内のhttpsのURLがハイパーリンク化されない件


# 試した環境
iOS 11.2.6

# 文量が少なく、全文表示できるとき

こんな感じでhttpもhttpsもハイパーリンクになっています。
<img width="275" alt="mail_全量.png" src="https://qiita-image-store.s3.amazonaws.com/0/134694/3925b2e1-bd1b-cd12-c38c-ae21867e1ade.png">

# 文量が多く全文表示できないとき

全文表示できないときは＞を押下すれば全文表示されます。
<img width="280" alt="mail_省略.png" src="https://qiita-image-store.s3.amazonaws.com/0/134694/c30c2727-8afd-0de8-8495-d394c429c2a2.png">

## 全文表示後
展開後はhttpはハイパーリンクになっていますがhttpsはハイパーリンクになっていません。
<img width="366" alt="mail_展開.png" src="https://qiita-image-store.s3.amazonaws.com/0/134694/121ca189-e903-081c-a880-6a1bc2e5b054.png">

# まとめ
まだまだテキストメール配信の需要はありそうなので、メールの開封率を向上したいときは注意が必要そう。
回避する方法がないものかご存知の方がいらっしゃったら教えてください。

# 追記
リンク先のURLの前方に「URL：」をつけることでハイパーリンクになるようです。
「URL」は全角でも半角でも問題ないですが、「：」は全角の必要があります。



![iOS の画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134694/9a6c7728-dad1-d386-f288-c7428a72b44d.png)

リンク先にはhttpでアクセスしに行くようです。

![iOS の画像 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134694/5ccd6dba-18ed-8711-c50e-9d19f518f189.png)

※たまたまメルマガを見ていて気づいたので、詳しい条件は不明なままです。どこかに仕様がないか引き続き調査中。