OmniAICreator/Qiita-1.07M huggingface dataset:
【Jest】画像ファイルやCSSのインポートに失敗する場合の対処法

ReactプロジェクトにJestを導入してテストコードを書いていたところ、エラーに遭遇して躓いたためその備忘録として。


## 事象

以下のような`Sample`コンポーネントをJestでテストした時、エラーが発生しました。
エラーメッセージを確認すると画像ファイルの読み込みでシンタックスエラーが発生しているようです。

```React:sample.tsx
import React from 'react'
import image from '../images/image-001.png'
import '../app.css'

const Sample = () => {
    return (
        <div className="sample">
            <span>Image File Test</span>
            <img src={image} alt="Image" />
        </div>
    )
}

export default Sample;
```

```
 FAIL  src/__test__/sample.test.tsx
  ● Test suite failed to run

    C:\Users\Application\src\images\image-001.png:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,
global,jest){�PNG

    SyntaxError: Invalid or unexpected token

    > 2 | import image from '../images/image-001.png';
```

また、同様の事象がCSSファイルのインポートでも発生します。

```
    C:\Users\Application\src\app.css:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,
global,jest){@import '~antd/lib/grid/style/index.css';

             ^

    SyntaxError: Invalid or unexpected token

      1 | import React from 'react'
      2 | import image from '../images/image-001.png'
    > 3 | import '../app.css'

```


## 原因
上のように画像やCSSを`import`する処理は、WebPackによって解決されています。
JestはWebPackの機能を持っていないため、画像やCSSがインポートされた時にJavaScriptとして読み込こもうとしシンタックスエラーが発生します。




## 解決法


`package.json`、もしくは`jest.config.js`に設定を加え、画像ファイルとCSSをモック化することで解決できます。


`package.json`の場合

```json:package.json
{
  "jest": {
    "moduleNameMapper": {
      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
      "\\.(css|scss)$": "<rootDir>/__mocks__/styleMock.js",
    }
  }
}
```

`jest.config.js`の場合

```javascript:jest.config.js
module.exports = {
  "moduleNameMapper": {
    "\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
    "\\.(css|scss)$": "<rootDir>/__mocks__/styleMock.js",
  },
}
```


次に、`__mocks__`フォルダ内に以下の２つのファイルを格納します。

```javascript:__mocks__/styleMock.js
module.exports = 'test-file-stub';
```

```javascript:__mocks__/fileMock.js
module.exports = ''; 
```

`moduleNameMapper`は渡された正規表現にマッチするモジュール名を持つ、画像やスタイルなどのリソースをスタブ化する設定です。
これによりインポートするモジュールが画像ファイルであった場合は代わりに`__mocks__/fileMock.js`が、cssファイルであった場合は`__mocks__/styleMock.js`が読み込まれるようになります。


## 参考

[Using with webpack](https://jestjs.io/docs/ja/webpack)
[Configuring Jest](https://jestjs.io/docs/ja/configuration#rootdir-string)
ssh 鍵を設定したはずなのに、パスワードを求められる時の対処法

## 概要
https://qiita.com/kenmaro/items/a548a302228029c5c870
以前上の記事で、ssh鍵を作り、サーバーにおくことで快適にリモートサーバー内のdockerにも
ssh アクセスできるようになる手順を書いた。

この時、鍵認証を行っていればパスワード認証はいらないはずだが、
設定したにもかかわらずパスワードを聞かれた時の対処法。

もしパスワードを聞かれないようにしたい時は、以下で解決できるかもしれない。

## 解決法
http://www.linuxproblem.org/art_9.html
ここを参考にした。とても単純だが、
リモートサーバ上の、　`~/.ssh/authorized_keys`
のパーミッションを確認して欲しい。

自分の場合は、　

`sudo chmod 700 ~/.ssh`
`sudo chmod 640 authorized_keys` 
をすることで、sshする際のパスワード認証を聞かれなくなった。


備忘録的にまとめたが、めんどくさい手順をカットしたいときは試してもらいたい。


以上。

終わり。
gemとbundlerについて詳しく学習

##gemとは
gemとは`rubyのライブラリ`のことです。
一応railsのライブラリにもなりますが、railsはもともとrubyのライブラリの
１つであるため、正しくはrubyのライブラリであるという認識が必要です。

##bundlerとは
`gemを管理する`ものです。
例えばbundlerを使うと以下のようなメリットがあります。

**１．bundlerを使ってgemをインストールするとgem同士の互換性を保ってくれるので、
gemを追加したり時間が経ってもエラーを起こさず開発できる**
（補足）例えばAというgemがあって、Aを使うにはBというgemを使う必要がある、
そのgemを使うにはCというgemを….となっている時、
AはBに依存しており、BはCに依存しているということになります。

**２．Gemfileという1つのファイルにgemを書くのでgemの管理がしやすい**

**３．Gemfileを使ってアプリごとにgemを管理できる**

**４．環境ごとにインストールするgemを管理できる。**

##bundlerでよくあるエラー
よくある原因はgem同士のバージョンがあっていない可能性があります。
なのでもしbundle installコマンドでエラーが発生した際にはまず始めに
`gem file`の中を確認することがポイントです。
また、Gemfile.lockを削除することで解決する場合もあります。
Ruby on Railsのファイルの中にある`Gemfile.lock`というファイルではGemの
バージョン指定が管理されています。
なので、Gemfile.lockのファイルを削除してからもう一度`bundle install`をして
みましょう。
※ちなみにGemfile.lockはbundle installした後の結果を記したものです。
削除し再度インストールを実行することで、また作成されますのでご安心を。

##まとめ
gemとはrubyのライブラリであり、たくさんのプログラムをまとめたものになります。
そしてそのライブラリの種類やバージョン管理を行っているのがbundlerです。

MacOSで例えるとHomebrewやiphoneで例えるとApp storeがrubyにおける
bundlerになるイメージです。
何気なく使用しているbundle installコマンドはbundlerで管理されたライブラリを
gemfileの中から見つけインストールするためのコマンドであるということが分かりました。
LINE Bot＋Power Automateで家庭内DXを促進するお手軽購入申請を作ってみた

#家庭内のDXにとっても有効なLINE botを利用した購入申請できたよ!!

よくある日常の会話。※実際の人物・団体とは(以下略
> パパ「XXXX買いたいんだけど、いいでしょうか」
> ママ「なんで必要なの？」
> パパ「いや、古くなってきたから・・・」
> ママ「いくら？」
> パパ「XXXX円です・・・」
> ママ「んー。いらなくない？」

このやりとり結構辛いんですよね。人によると思いますが。こういうやりとりの辛さを、LINE botさんに仲介していただくことで改善しようというのが、今回の目的です。

お互いドライに。品名、金額、参考URL、購入理由などをフォームにポチポチと入力したら、あとはLINE botさんがよきように手配してくれます。

動作は以下の動画を見てみてください。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">家庭内DXに効果抜群のLINE botを活用した購入申請。<br>申請： Microsoft Forms<br>承認アクション : Flex message<br>一覧 : Azure Blob storage上のhtmlファイル <a href="https://t.co/zhdd0BgDZJ">pic.twitter.com/zhdd0BgDZJ</a></p>&mdash; Hiro (@mofumofu_dance) <a href="https://twitter.com/mofumofu_dance/status/1273286893287833606?ref_src=twsrc%5Etfw">June 17, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 今回のアーキテクチャ

アーキテクチャというほどでもないですが、今回使ったのは、

- LINE Messaging API : いうまでもなく。インターフェース
- Microsoft Forms : フォームを作れないのでFormsで代用
- Power Automate : ロジック全般
- SharePoint リスト : データ蓄積用
- Azure blobストレージ : 申請履歴をHTMLファイルとして保管

です。
Formsのフォームを購入申請情報の入力に使っていますが、LINE上でページを表示してくれるので、ユーザーが接するアプリとしてはLINEに限定されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/c715de80-e0b9-b781-8711-81de84f81972.png)

# LINE上での表示

LINE上の画面は以下のように構成されています。よく使うアクションである、**申請作成** と **一覧表示** はリッチメニューで起動できるようにしています。

承認者は、送られてきたFlex messageに表示された内容を確認して、OK/NGのボタンをタップするだけ！大変ドライな対応ですみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/3e60139d-5ad5-ee2a-bc96-c7e7497b709c.png)

# イベントの処理 (Power Automate)
申請フォームへの入力をトリガーにして承認者にメッセージを送信する、承認結果を処理して記録&結果通知。主にこれらのイベントが発生しますが、これらはPower Automateで処理しています。
HTTPのコネクタを使っているので、場合によってはLogic Appsのほうが良いかもしれません。

長い方のフローがLINEからのWebhookをトリガーとして起動するメッセージ処理＋もろもろのデータ処理用フローです。
短い方はFormsの回答をトリガーにしています。回答があったら承認者側にPushメッセージを送信します。

手軽さと、想定されるデータ件数から、すべてのデータはSharePointリストに保存しています。

※各フローの詳細は、長くなるので別の投稿で記述します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/2a5cdc48-130b-220f-c573-632d60bd92ef.png)

# 紹介おわり
LINE側は特にやることがないので、メインはPower Automate上の処理になりますが、とても長いので別のブログで解説します。
それでも、コード書くことなく手軽に ~~めんどくさい~~ プロセスのデジタル化ができるのはとても良いですね！

なお、Power AutomateではLINEのカスタムコネクタを利用しています。ご参考まで
[Power Platform用にLINE Messaging APIのカスタムコネクターを作ってみた - MoreBeerMorePower](https://mofumofupower.hatenablog.com/entry/2020/05/15/16521)

次回→[LINE Bot＋Power Automateで家庭内DXを促進するお手軽購入申請 ~フロー詳細](https://qiita.com/h-nagao/items/00209b4b20dfef6d80cd)
API側でデータのフォーマットはしないほうがいいという教訓

初めてモバイルアプリ開発(Cordova)に携わることになってデータのフォーマットはどこでするべきなのか悩みました。

MVCのWebアプリを作っていたときはModel側でデータを取得・加工してViewはデータを表示するだけという形で作っていました。

なんで悩み始めたのかというと既存のAPIでこんな感じでデータを返しているAPIがあったからです。

```json:/example.json
"example" {
 	"price": "10,000", //カンマ区切りにフォーマット
 	"tax": "1,000",
 	"released_at": "2020-06-15 12:00:00",
 	"fmt_released_at": "2020年06月15日" //表示用のフォーマット済みの日付を返している
 }
```
モバイルアプリの場合、アプリを更新するためにAndroidならGooglePlayの審査、iOSならAppleの審査を受ける必要があり、ちょっとした変更でも最低2〜3日はかかってしまいます。またユーザがアプリを最新版にアップデートしてくれるとは限りません。

例えば"2020年06月15日"の表示を"06月15日"という表示に変更したいというとき。

```json:/example.json
"example" {
 	"price": "10,000",
 	"tax": "1,000",
 	"released_at": "2020-06-15 12:00:00",
 	"fmt_released_at": "06月15日" //データのフォーマットをAPI側で変更
 }
```

```vuejs
 <p>{{ example.fmt_released_at }}</p>
```

モバイルアプリ側でAPIから取ってきたデータをただ表示するだけにしていれば、アプリをアップデートしなくても表示を変更できるので「これはこれでアリなのかなぁ」と思ったりもしました。


しかし、[こちらの記事](https://blog.yuhiisk.com/archive/2017/09/30/date-format-front-or-api-server.html)でも詳しく書かれていますがデータのフォーマット処理はフロントで行うべきでAPI側でするべきではないという結論になりました。

## 1. APIとしての汎用性がなくなる
/example APIを他のページでも使用する場合、そのページでは曜日も表示する必要があるかもしれません。そうなるとレスポンスに追加しなければいけないデータがどんどん増えていきます。

```json:/example.json
"example" {
  	"price": "10,000",
  	"tax": "1,000",
  	"released_at": "2020-06-15 12:00:00",
  	"fmt_released_at": "06月15日",
  	"fmt_day_of_week_released_at": "06月15日(月)", //地獄
  }
```

## 2. 過去のバージョンのアプリの表示も変更されてしまう
ユーザがアプリをアップデートするとは限らないと書きましたが、すでに使用済みのAPIのレスポンスの中身を変更してしまうと、最新版のアプリの表示は問題なくても、旧バージョンのアプリの表示や挙動に問題が出てしまいます。

```json:/example.json
"example" {
  	"price": "10,000",
  	"tax": "1,000",
  	"released_at": "2020-06-15 12:00:00",
  	"fmt_released_at": "06月15日(月)" //"06月15日"から"06月15日(月)"に変更
  }
```

例えば"06月15日"から"06月15日(月)"に変更してしまうと、旧バージョンのアプリで表示崩れなどの問題が起こる可能性があります。

というわけで、API側ではデータを渡すだけにしてデータのフォーマットはフロントでするようにしましょうという少し考えれば当たり前の話でした。
VBAマクロ insert文自動生成

本記事は、マクロを用いて、insert文を大量に自動作成する技術投稿記事になります。

パフォーマンス的にはsqlloaderを使用するほうが圧倒的に早いですが、本記事にて生成するsqlファイルはinsert文としてコピペしてそのまま使用可能なため、可視性に優れているという利点があります。


以下に手順を記載します。
１．ボタンを配置したシートのB2セルに、出力対象シート名を記入する。
２．出力対象シートに、作成するデータを設定する。
３．マクロを作成する。
４．マクロを実行する。


１．ボタンを配置したシートのB2セルに、出力対象シート名を記入する。
　下記のようなイメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517374/e10ddd8f-3336-408b-6210-d8b26db99117.png)

　今回はm_table1のシートデータをこのファイル名で出力します。
　ボタンを配置する当シート名は何でも良いです。


２．出力対象シートに、作成するデータを設定する。
　下記のようなイメージです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517374/4ea38da4-8855-3e24-0d28-14d2e8ae5cd0.png)

　B列をファイル出力します。
　D列～J列はm_table1_dataシートの実際のデータを加工しています。
　C列でCONCATし、B列でA1及びA2セルとC列のセルを合わせています。


　下記がデータシートのサンプルです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517374/69e7c1c7-96a4-d6f4-f022-8831201f918d.png)



３．マクロを作成する。
　以下のプログラムを作成します。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sub createInsertSql()
　Dim workfile As String, sheetName As String, r As Integer, ws As Worksheet, wsExistFlg As Boolean, wfOpenedFlg As Boolean

　sheetName = "" Then
　　MsgBox "対象シートを黄色セル(B2)に入力して下さい。"
　　End
　End If

　wsExistFlg = isSheetExist(sheetName)

　If wsExistFlg = False Then
　　MsgBox "対象シートを正しく入力して下さい。"
　End If

　workfile = ActiveWorkbook.Path & "\insert_" & sheetName & ".sql"
　wfOpenedFlg = isWorkfileOpened(workfile)

　If wfOpenedFlg = True Then
　　MsgBox "出力対象のファイルが開かれているため、書き込めません。"
　End If

　Open workfile For Output As #1

　r = 2

　Set ws = Sheets(sheetName)

　Do While ws.Cells(r, 2).Value <> ""
　　Print #1, ws.Cells(r, 2).Value
　　r = r + 1
　Loop
　Close #1

　MsgBox "作成完了しました。"
End Sub

Function isSheetExist(ByVal sheetName As String) As Boolean
　Dim ws As Worksheer
　isSheetExist = False
　For Each ws In Worksheets
　　If ws.name = sheetName Then is SheetExist = True
　Next ws
End Funtion

Function isWorkfileOpened(ByVal workfileName As String) As Boolean
　isWorkfileOpened = False

　On Error Resume Next

　Open workfileName For Output As #1
　Close #1

　If Err.Number > 0 Then
　　isWorkfileOpened = True
　End If
End Function
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

使用する際は、createInsertSql()をボタン等に設定してご使用下さい。


４．マクロを実行する。
　ボタンを押すだけ。
　以下のような内容で出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517374/2a7d31ba-ccc8-fa29-05a1-aeb96635ba8e.png)


以上になります。
simple_formのフォームを横並びに配置する方法

#目標
simple_form で実装した入力フォームは改行されて表示されるが、例えば名前記入欄で性・名を分けてフォームを作成する場合に横並びに表示させたい。
複数方法はあるようだが、今回はbootstrapのグリッドシステムを利用して実現したので備忘録的に残しておく。

#修正前

```html:hoge.html.slim
= simple_form_for @hoge, url: hoge_path, method: :patch do |f|
    = f.input :first_name, label:"苗字"
    = f.input :last_name:"名前"
```
これでは縦並びにフォームが表示される。


#修正後

```html:hoge.html.slim
= simple_form_for @hoge, url: hoge_path, method: :patch do |f|
  .col-sm-4
    = f.input :first_name, label:"苗字"
  .col-sm-4
    = f.input :last_name:"名前"
```

bootstrapのグリッドシステムによってレイアウトを格子状に分解して配置してくれる。今回はカラム数が4＋4 < 12 であるため、フォームが横並びに配置されるという仕組みである。


他にもsimple_formのstyleやclassを指定していい感じにできる方法もあるみたいだが、うまくいかなかった（圧倒的力不足）。
この記事とか
https://stackoverflow.com/questions/9985317/simple-form-for-rails-radio-button-inline
この記事
http://blueplanet42.info/2016/04/24/bootstrapform-vs-simpleform.html
が参考になりそう。





以下今回の参考記事
https://qiita.com/akatsuki174/items/53b7367b04ed0b066bbf
UnityでwavとMP3の違いで困惑したこと(MP3で前に謎の余分な部分が追加されてしまう原因とその解決策)

##訂正 (2020/06/19)
このようなコメントを頂きました。
> これはUnityの問題ではなく、mp3というファイルフォーマットの仕様です。
なので、ゲームではoggの方が好んで使われます。

なんとこれはUnityではなくファイルフォーマットの仕様だったようです！
教えてくださった @kazutomo さん本当にありがとうございます！！！

[こちらのサイト](https://kohrogi.com/?p=4085)にはそういったファイルフォーマットのアレコレがまとめられていてとてもためになります！

##記事の環境
Unity 2019.3.0f6

##この記事で分かること
MP3で前に謎の余分な部分が追加されてしまう原因とその解決方法

#状況の説明
いつもみたいにフリー効果音素材を[効果音ラボ](https://soundeffect-lab.info/)様から持ってきたんです。
MP3のやつを。

一度鳴らしてみて、自分が意図したタイミングとズレて再生されていたので、前の余分な部分をAudacityで切って再度MP3出力しました。
そしたら、なんと。。。。

##MP3でUnityに持ってきた場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293529/1a250e20-6f10-b8b0-3e8d-558794a8e749.png)
余計な部分が追加されてしまっているではないか！！！(せっかく切ったのに。。。)

色々調べて全然原因が出てこなかったのでダメもとでwav出力したらちゃんと切れた状態で取り込めました。

##wavに変換してUnityに持ってきた場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293529/5b1c1c46-3fc0-945f-8b93-3ce2bd7a0924.png)
SIGLENTのオシロからLAN経由でスクリーンキャプチャを撮る

メーカーのアプリケーションにPythonを使うサンプルがある。それをC#で書いてみた。

[Programming Example: SDS Oscilloscope screen image capture using Python over LAN | Siglent](https://siglentna.com/application-note/programming-example-sds-oscilloscope-screen-capture-python/)

```c#
// usingは各自適当に
TcpClient tcp = new TcpClient("192.168.1.186", 5025);

using (NetworkStream ns = tcp.GetStream())
using (MemoryStream ms = new MemoryStream())
{
    ns.ReadTimeout = ns.WriteTimeout = 100;

    ns.Write(Encoding.ASCII.GetBytes("SCDP\n"), 0, 5);

    try
    {
        ns.CopyTo(ms);
    }
    catch (IOException ex) when (ex.Message == "転送接続からデータを読み取れません: 接続済みの呼び出し先が一定の時間を過ぎても正しく応答しなかったため、接続できませんでした。または接続済みのホストが応答しなかったため、確立された接続は失敗しました。。")
    {
        // タイムアウトで正常終了
    }

    ms.Position = 0;

    using (Image img = Image.FromStream(ms))
    {
        img.Save(DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss") + ".png", ImageFormat.Png);
    }
}

tcp.Close();
```

オシロのIPアドレスは、Utilityボタンから2/4ページの`I/O設定`、`IP Set`で設定できる(or DHCPを有効にもできる)。英語とか中国語とか他の言語に設定している人はいい感じに雰囲気で探してください。

一旦MemoryStreamに読んでImage.FromStreamで画像インスタンスに変換してから保存し直している。今どきBitmapのファイルサイズケチる時代でもないと思うけど。

`SCDP`は`SCreen DumP`の意味らしい。他にもいろいろな機能があるらしい。

***

こんな感じの画像が得られる。

![2020-06-18_15-33-09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264452/6495aab5-a5f3-6ccf-f7c0-a1c3603d1284.png)

PrintキーでUSBメモリに保存される画像と同じ。

僕が使っているSDS1202X-EはFFTを使ったり高負荷な状態でPrintをやるとかなりの確率でハングアップする。今の所はTCP経由だと大丈夫っぽい。
USBメモリ経由だとタイムスタンプがなかったり、いちいちメモリをPCとの間で動かしたり、地味に面倒なので、ネットワーク経由でサクッとキャプチャできるのは楽でいい。
Windows10にmkcertをインストールする

#mkcertとは
任意のドメインでSSL証明書が作成できるツールです。

#前提
Windows用のパッケージマネージャー「Chocolatery」がインストールされていることをご確認ください。
インストールされていない場合は、こちら https://qiita.com/dai-andy1976/items/6a47bb36932aa1d5af2d を参考にインストールしてください。

#インストール手順
##Power Shellを起動する
- Windowsのスタートボタンを押します。
- メニューにある「Windows PowerShell」から「Windows PowerShell」を選択します。

##mkcertをインストールする
- 下記コマンドを実行してください。

```
PS C:\> choco install mkcert
```
```
PS C:\> mkcert --install
```

お疲れ様でした。
AWS☆☆ デプロイまでの道のり２（短いバージョン、全４回）

###  <font color='lightblue'>１）背景</font>
第２回目です。
自身のポートフォリオをデプロイするために、AWSのインスタンスを構築します。インスタンスの設定方法の手順記事はすごく多いので、ここでは備忘録も含めて、非常に端的に手順を記載します。
全４話で進めます。


###  <font color='lightblue'>２）環境</font>

| 項目              |               内容 | 
|:-----------------|:------------------:|
| OS.Amazon Linux AMI      |            release 2018.03 |            
| Ruby             |            v2.5.1 |  
| Ruby On Rails    |           v5.2.4.3 |  
| MySQL    |           v5.6 |  

###  <font color='lightblue'>３）内容</font>
<font color='blue'>**以下の作業は、AWS上で作業を進める。全設定で45分程度かなと思います。（段取りが分かっていれば、30分）**</font>

####  （1）yumパッケージの使用(5分)
 - yumパッケージの更新
 - 各種パッケージの導入
 （長いのでメモしておきます。）

```
CMD>sudo yum -y install git make gcc-c++ patch libyaml-devel libffi-devel libicu-devel zlib-devel readline-devel libxml2-devel libxslt-devel ImageMagick ImageMagick-devel openssl-devel libcurl libcurl-devel curl
```

####  （2）JSパッケージの導入(5分)
- node.jsの導入

####  （3）Rubyのインストールと設定(15分)
- rbenvのインストール <font color="red">（※ここは時間がかかります）</font>
- .bash_profileの設定（Rubyのパス設定）と再読み込み
- ruby-buildのインストールとrehash（再読み込み）

####  （4）Mysql設定とDB接続(10分)
- MySQLのインストール（V5.6）
- サービスの起動
- DB管理者パスワードの設定と接続確認

####  （5）EC2インスタンスとGitHubのssl認証設定(10分)
ここは少し難しいです。
- キーペアの作成。以下コマンドです。

```
ssh-keygen -t rsa -b 4096
```
- 自分のGitにアクセスして、許容するSSL通信に先ほどのRSAキーペアを設定する（ssh-rsa…から最後まで貼り付けるだけ。）
- EC2からgitへの通信確認

```
[ec2-user@ip-172-31-xxxx .ssh]$ ssh -T git@github.com
(省略)
Hi Daisuke-Ichikawa-2! You've successfully authenticated, but GitHub does not provide shell access.
```

以上、短く記載しました。
コマンドによっては応答時間がかなりかかるものがありますので、ちゃんとプロンプトが返ってくるまで待つ方がいいです。
あと、ここまで設定したらインスタンスを再起動した方がいいです。再起動後は、Mysqlサービスが起動していないので、起動する必要があります。
SSL通信でCaused by OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: wrong signature type が出たらOpenSSLの設定を変える

Rubyで外部のAPIにSSLで接続したらエラーが出た。

```
Faraday::SSLError: SSL_connect returned=1 errno=0 state=error: wrong signature type
```

このエラーの対処法についてまとめ

# 結論

OpenSSLの設定ファイル `/etc/ssl/openssl.cnf` のセキュリティレベルを以下のように変える。

```toml
[system_default_sect]
MinProtocol = TLSv1.2
CipherString = DEFAULT@SECLEVEL=1
```

```diff
< CipherString = DEFAULT@SECLEVEL=2
---
> CipherString = DEFAULT@SECLEVEL=1
```


# 発生している環境

[ruby:2.6.6](https://hub.docker.com/_/ruby)のコンテナイメージ。
OSはDebianなのでDebian系のコンテナだと同じ現象が発生する可能性がある。

コンテナで確認したらDebian10.4だった。

```
# cat /etc/debian_version
10.4
```

[ruby:2.6.6](https://github.com/docker-library/ruby/blob/a564feaaee4c8647c299ab11d41498468bb9af7b/2.6/buster/Dockerfile)のDockerfileのFROMをたどっていくと[debian:buster](https://hub.docker.com/_/buildpack-deps/)にたどり着くことからもDebian10.4であることがわかる。


# 原因

OpenSSLを使って暗号化通信（SSL,TLS）を外部と行うとき、Debianではデフォルトでより安全な設定が行われている。
このとき証明書の署名ではSHA-1はサポートされなくなり、少なくともSHA-256が必要となる。
相手側が少なくともTLS1.2以降をサポートしていない場合にエラーが発生する。

https://wiki.debian.org/ContinuousIntegration/TriagingTips/openssl-1.1.1
公式のWikiにも記載がある。


# Dockerfileで自動で編集する方法

`sed` コマンドを使って設定ファイルを編集できます。

```Dockerfile
FROM ruby:2.6.6

RUN sed -i 's/DEFAULT@SECLEVEL=2/DEFAULT@SECLEVEL=1/' /etc/ssl/openssl.cnf
```


# 注意したいこと

同じようなエラーで、

> OpenSSL::SSL::SSLError SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed

というものがあり、エラーメッセージで検索すると、これの検索結果も混じってくるので注意したいところ。
証明書を `http://curl.haxx.se/ca/cacert.pem` からダウンロードして設置、みたいなことはやっても関係ない。


# 参考資料

- [ContinuousIntegrationTriagingTipsopenssl-1.1.1](https://wiki.debian.org/ContinuousIntegration/TriagingTips/openssl-1.1.1)
- [PHP CURL - cURL error 35: error:1414D172:SSL routines:tls12_check_peer_sigalg:wrong signature type
](https://stackoverflow.com/questions/58342699/php-curl-curl-error-35-error1414d172ssl-routinestls12-check-peer-sigalgwr)
- [OpenSSL v1.1.1 ssl_choose_client_version unsupported protocol [closed]](https://stackoverflow.com/questions/53058362/openssl-v1-1-1-ssl-choose-client-version-unsupported-protocol)
【Javascript】配列、オブジェクト、両対応の要素のカウントを取得

メモとして残します。

ど忘れしちゃったのでメモ。

#■やり方
```javascript
Object.keys(配列orオブジェクト||{}).length
```
`Object.keys()`メソッドをつかってカウント。
オブジェクトだけでなく配列も可能のため便利。
一応undifined対策として、配列、オブジェクトが存在しないしない場合は空のオブジェクトをカウントするようにしました。
IE11でも動作します。IE10以下は知りません(きっぱり)


#■余談
PHPはめちゃくちゃ融通がきくので、こういったことで止まることはありませんが、
VBAに関してはそもそも配列をわざわざカウントする機会もないし（そもそも複数要素を抱えるオブジェクトは既にカウントを持っているケースが多い。）
いろいろ言語を案件ごとに切り替えてると、ど忘れしちゃいます(;´･ω･)
Windows10にChocolateyをインストールする

#Chocolateryとは
Windows用のパッケージマネージャーです。

#インストール手順
##Power Shellを起動する
- Windowsのスタートボタンを押します。
- メニューにある「Windows PowerShell」から「Windows PowerShell」を選択します。

##Chocolateryをインストールする
- Chocolatery公式サイトにあるインストールページ https://chocolatey.org/install にアクセスし、インストールコマンドを確認します。
- Power Shellにインストールコマンドを入力し、実行します。

```
PS C:\> Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
```

##Chocolaterynoのインストールを確認する
- chocoコマンドが実行できればインストール完了です。

```
PS C:\> choco list -l
Chocolatey v0.10.15
chocolatey 0.10.15
1 packages installed.
```

お疲れ様でした。
Javaの配列変数は参照型

Javaの配列変数は参照型。

当たり前な基礎的なことだと思いますが、元々PHPをしていたので、
自身の備忘録のため、少しまとめてみました。

例えば、下記のようなコードの場合には100が出力される。

```java
int[] a = { 1, 2, 3 };
int[] b = a;
b[0] = 100;
System.out.println(a[0]);
// a[0]は100が出力される。
```

これは、Javaの配列変数が参照型なので、int[] a には配列が作られた
メモリアドレスが格納されるため。

例えば、int[] a で作成された配列のメモリアドレスがABC123（実際はこんなメモリアドレスはないと思います）だとすれば、
このABC123というメモリアドレス（場所）に配列aが記録されている。

そしてint[] b に入っているのは配列変数int[] a のメモリアドレスであるABC123が入るので、要は同じ配列ということになる。
そのため、 b[0]=100 は a[0]=100 と同じことになる。

これがPHPで同様の下記コードを書いてみると、100ではなく1が出力される。

```php
$a = [1,2,3];
$b = $a;
$b[0] = 100;
echo $a[0];
// 1が出力される
```

これはPHPの場合は参照型ではなく、値渡しになるため、
\$bには\$aのメモリアドレスではなく、\$aの配列そのものがコピーして渡されているため。

PHPでは参照型にするためには、下記のように\&をつけてあげる必要がある。

```php
$a = [1,2,3];
$b = &$a;
// ↑$aの前に&をつける
$b[0] = 100;
echo $a[0];
// 100が出力される
```

こうすることで参照型になり、\$bには\$aで作成された配列のメモリアドレスが
格納されるため、上記のJavaの場合と同様の動作になる。
Ruby: `method_missing` を実装する時は - When using `method_missing`, define `respond_to_missing?`.Style/MissingRespondToMissing


# `method_missing` を定義するとRubocopに逮捕されるぞ!!

Rubyで `method_missing` を定義すると、以下のようにRubocopに逮捕される。

このコードはLoggerをラップするコードで

- LoggerインスタンスをSingletonにしたい
- Loggerインスタンスを作る時に設定ファイルで制御したい
- クラスメソッドでログ出力したい

という目的で実装しています。なので `Hound::Logger.debug('debug message')` とすればログ出力できます。


```ruby
# LoggerクラスをWrapして使う
require 'logger'
module Hound
  class Logger
    @logger = nil
    class << self
      def logger
        return @logger unless @logger.nil?
        # 本来はここで config ファイルをロードして出力先やログレベルを変更する
        # ここでは割愛
        @logger = Logger.new(STDOUT)
        @logger.level = :debug
        @logger
      end

      def method_missing(method, *args)
        if method =~ /^(debug|info|warn|error|fatal|unknown)$/
          logger.send(method, *args)
        else
          super
        end
      end
    end
  end
end

```

この時、以下のようにRubocopに逮捕されてしまいます。


```
When using `method_missing`, define `respond_to_missing?`.Style/MissingRespondToMissing
```


`method_missing` メソッドを定義する時には、合わせて `respond_to_missing?` メソッドも定義しましょう、という内容です。

> This cop checks for the presence of `method_missing` without also defining `respond_to_missing?`.

[Class: RuboCop::Cop::Style::MissingRespondToMissing](https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Style/MissingRespondToMissing)


# 修正されたコード

```ruby

module Hound
  class Logger
    @logger = nil
    class << self
      # def logger は割愛
      
      def respond_to_missing?(symbol, include_private)
        return true if symbol =~ /^(debug|info|warn|error|fatal|unknown)$/
        false
      end

      def method_missing(method, *args)
        if method =~ /^(debug|info|warn|error|fatal|unknown)$/
          logger.send(method, *args)
        else
          super
        end
      end
    end
  end
end
```

`responde_to_missing?` メソッドを実装しましょう。コードの中身がなくてもRubocopのチェックはパスできます。でもちゃんと実装しましょう。


# method_missing ってなに？




https://docs.ruby-lang.org/ja/latest/method/Object/i/respond_to_missing=3f.html
Ubuntu 20.04LTS にandroid開発環境をインストールする


# はじめに
Ubuntu 20.04LTSにAndroid開発環境をインストールした手順をメモしておく。
以下のコマンドを順次実行する。

```
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install openjdk-11-jdk
$ sudo snap install android-studio --classic
```
# android-studioの実行
android-studioを実行する(あとは適当なボタンを押し下げていればインストール完了です)。

```
$ android-studio
```

ok押し下げ。

![スクリーンショット 2020-06-18 14-05-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657403/ed71a39b-0661-b738-0feb-baa845ba52ed.png)

どちらか押し下げ。

![スクリーンショット 2020-06-18 14-05-39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657403/c9da5c0d-9860-c868-317f-50508ddb92d8.png)

next押し下げ。

![スクリーンショット 2020-06-18 14-06-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657403/dc5928b3-a378-947e-5648-d162217c51cb.png)

next押し下げ。

![スクリーンショット 2020-06-18 14-06-21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657403/fa72b60a-ad71-acd6-933c-f25e29a8fc9b.png)

next押し下げ。

![スクリーンショット 2020-06-18 14-06-45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657403/d60711a7-3cab-ef09-320e-c52112a356ee.png)

next押し下げ。

![スクリーンショット 2020-06-18 14-07-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657403/99cd299f-f918-63a5-3c8a-d7ac826d2aed.png)

next押し下げ。

![スクリーンショット 2020-06-18 14-07-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657403/765c387a-165c-cc4e-94d3-b5f229d44003.png)

next押し下げ。

![スクリーンショット 2020-06-18 14-07-57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657403/0b44546f-ca64-8429-0cec-6251c3671c26.png)

next押し下げ。

![スクリーンショット 2020-06-18 14-08-59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657403/6c5015da-086c-51bc-73ba-4b88db599d52.png)

next押し下げ。

![スクリーンショット 2020-06-18 14-10-28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657403/7daea639-6638-2a71-6800-2c58e1cff094.png)

next押し下げ。

![スクリーンショット 2020-06-18 14-10-48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657403/45fd4b55-ddd1-01c6-4af7-034b8bd5d53b.png)

おつかれさまでした。
プログラミングで相手に理解してもらえる質問方法について


初めてのQiita投稿。
記念すべき1本目の記事は「プログラミングで相手に理解してもらえる質問方法」について書いていこうと思います。

分かりやすい質問を心がけることで

**・相手が質問の意図を理解することができるので、質の高い回答が返ってくる**
**・自分で要点をまとめて質問をするので、自然と論理的思考力や問題解決能力が上がる**

など質問をする自分にもメリットがたくさんある。








# □相手に理解してもらえる質問方法

結論から言うと、質問をする際には

**①自分が実現したいこと **
**②問題点 **
**③自分がエラー解決のために試したこと**
**④補足情報**

この4点をまとめて質問をすることで、相手も理解しやすい質問を投げかけることができます。




# □質問例

以下の4つの点でまとめると良いかなと思います！

　　　　　　　　↓


**①今私は〜〜〜〜〜〜〜を実現したいと思っています。**

** ②そこで〜〜〜〜〜〜の箇所でエラーが発生しました。エラーコードは以下の内容です。
 （エラー文のコピペか画像を貼ると良い。）**

 **③エラーを解決するために3つ試してみました。 　**

**1つ目は〜〜〜〜〜です。 　
2つ目は〜〜〜〜〜です。 
3つ目は〜〜〜〜〜です。**

**④今私が使っているPCは〜〜です。**

**回答よろしくお願いします。**




例えばこのような質問をすると、要点がまとまって相手も理解しやすいと思います。
後エラーが発生した時の画像、自分が書いたコードも質問する際に送るとより相手も理解しやすいのでおすすめです。
1つの文章にまとめなくても、項目ごとにまとめるのもありです。



# □まとめ

以上が相手に理解してもらえる質問方法についてでした！
プログラミングを初めて数ヶ月の僕と同じような駆け出しエンジニアの方は是非分かりやすい質問を学ぶと良いかなと思います。
自分のためにも、相手のためにも頑張って身に付けていきましょう！

読んで頂きありがとうございます。
AWS☆デプロイまでの道のり１（短いバージョン、全４回）

###  <font color='lightblue'>１）背景</font>
自身のポートフォリオをデプロイするために、AWSのインスタンスを構築します。インスタンスの設定方法の手順記事はすごく多いので、ここでは備忘録も含めて、非常に端的に手順を記載します。
全４話で進めます。


###  <font color='lightblue'>２）環境</font>

| 項目              |               内容 | 
|:-----------------|:------------------:|
| OS.Amazon Linux AMI      |            release 2018.03 |         


###  <font color='lightblue'>３）内容</font>
<font color='blue'>**以下設定は全部で30分程度（段取りが分かっていれば、15分）**</font>

####  （1）AWSアカウントの作成(10分)
 - クレジットカードの登録
 - 住所等々の登録

####  （2）AWSインスタンスの作成(5分)
- AMI（Amazonマシンイメージ）の選択（AmazonLinux,t2_microを選択）
- 作成したインスタンスの起動

####  （3）AWSインスタンスの設定(5分)
- ElasticIPアドレスの割当
- インスタンスと、ElasticIPアドレスの関連付け
- ポートの開放(httpプロトコルの許容)

####  （4）AWSをローカルマシンから操作するため、キーペア設定とec2インスタンスへの接続(10分)
- AWSインスタンスからキーペアファイル（.pem）の新規割当、ダウンロード
- ローカルマシンにpemキーファイルの配置。
- ec2接続（接続できてうれしい…）

以上、短く記載しました。基本的にAWSの設定はウィザードで設定出来るので、ユーザに優しいです。
Windows タスクスケジューラの実行権限トラブル

#everyoneや777はダメよ
ドメイン参加の各コンピューターに定期タスク（スケジューラ）がある。
タスクで実行されるプログラムはDC上の共有フォルダにあるファイルを参照する。

接続したドメイン管理者でタスクを作成したので、ドメイン管理者の権限で実行されるプログラムはDCの共有フォルダへアクセスできる。と・・当初は深く考えなかった。

後日、事情によりドメイン管理者のパスワードを変更した。
トラブル発生・・・各コンピューターの定期タスクが失敗になっている。

一次受け担当が共有フォルダに「everyone」を追加しようとした。
everyoneや777は慎重にねーと止めた。

そもそもタスクの実行ユーザをドメイン管理者にしたのがマズかった。


#対応

タスクの実行ユーザをローカル管理者のSYSTEMに変更する。

 * １．DCの共有フォルダのセキュリティにSYSTEMを追加
**（Active DirectoryのSYSTEMアカウントはドメイン参加のコンピュータのローカルSYSTEMで接続できる）**

 * ２．各コンピューターのタスクを一括更新、GPOでタスクを作成
コンピューターの構成　→　基本設定　→　コントローラパネルの設定　→　タスク
  * 名前： **（既存タスクと同じ名前で登録すると、上書きできる）**
  * タスクの実行時に使うユーザ：NT AUTHORITY\System


#参考
https://teratail.com/questions/109162
Auth0の概要とRailsでの利用例

# Auth0とは
言語、フレームワークを問わずに数行のコードを追加するだけで、webサービスやネイティブアプリに認証・認可機能を実現できるサービス。

### できること
- GoogleやFacebookなどのソーシャルアカウント認証
- メールやSMSを利用したワンタイムパスワード認証
- 多要素認証
- パスワードを忘れた場合等の再設定の一連のフロー
- ユーザー登録時に登録を促す情報の指定
- アクセスコントロール
- ログインに関するイベントからのweb hook
- 複数アプリケーションでのシングルサインオン
- 異常アクセスの検知やブロック
- etc.

# 利用例
- ログイン認証
- APIの認可サーバ
- APIサーバに認証組み込み

## ログイン認証
### 種類
- ユニバーサルログイン: Auth0がホストするwebページでアプリケーションにログイン
  - ログインと認証が同じドメインで行われ、認証情報がクロスドメインで移動しないため、セキュリティが向上し、フィッシング攻撃や中間者攻撃から保護される
  - Auth0のダッシュボードからログインページの(少々の)UIと動作を変更できるため、アプリケーションコードの変更が不要
  - Classic Universal LoginとNew Universal Loginがあり、カスタマイズ性と動作速度に差がある

New Universal Login(ほぼカスタマイズできない)でGoogle認証のみを指定した例
![スクリーンショット 2020-06-18 13.44.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279908/66ea45cb-895d-69e8-4bdd-ca1007b3878b.png)


- 埋め込みログイン: アプリケーション上のwebページでアプリケーションにログイン
  - 認証のみをAuth0に任せるので、アプリケーションと親和性のあるUXを考慮したログインページを作成できる
  - 必然的にクロスオリジン認証になる

javascriptの場合の認証実行例

```
document
  .getElementById('login')
  .addEventListener('click', async () => {
    await auth0.loginWithRedirect();
  });
```
  
### 実装方法
- Auth0のダッシュボードにてApplication(と呼ばれるOauthクライアント)を作成する
- 上記のApplicationにログイン処理後に遷移するのコールバックURLを設定する
- ログイン認証を付与するwebアプリケーション側に、ログインページへの遷移処理とログイン処理後の処理を記述する

詳細は以下の通り
[Quick Start](https://auth0.com/docs/quickstart/webapp/rails/01-login) (Railsの例だが、言語に応じた実装方法が表示される)

### deviseからの移行
Railsの認証ライブラリのdeviseで利用していた`current_user`や`authenticate_user!`をそのまま利用するために以下のモジュールを作成し、`application_controller.rb`にincludeする。

```
module Auth0Helper
  private

  def user_signed_in?
    session[:userinfo].present?
  end

  def authenticate_user!
    if user_signed_in?
      @current_user = User.from_omniauth(session[:userinfo]) # from_omniauthはuserを特定するロジック
    else
      redirect_to login_path
    end
  end

  def current_user
    @current_user
  end
end
```

## Web APIの認可サーバ
クラウドサービスでAPIサービスを利用する時の認証認可の仕組みを提供する。
以下はAWSのAPI GatewayからLambda関数を呼び出す際のAPI Gatewayの認証認可のフロー

<img width="700" alt="スクリーンショット 2020-06-18 12.33.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279908/dc38852c-f479-c14f-b8bd-0d19260c935e.png">

Lambdaを利用したPDFパース処理での利用例
<img width="700" alt="スクリーンショット 2020-06-18 12.48.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279908/3fc85dd8-b750-1b66-1c5d-5776c5b9e95c.png">


### 実装方法
- Auth0のダッシュボードにてAPI(と呼ばれるAuth0認証するためのエンドポイント)を作成する
  - このAPIを利用することで、クライアントIDとクライアントシークレットを元にAuth0で認証できる
- Web APIを呼び出すクライアント側に、上記APIを呼び出す処理を記述する

詳細は以下の通り
[Securing AWS HTTP APIs with JWT Authorizers](https://auth0.com/blog/securing-aws-http-apis-with-jwt-authorizers/#Add-a-JWT-Authorizer-to-Your-API)

## APIサーバ
### 実装方法
- Auth0のダッシュボードにてAPI(と呼ばれるAuth0認証するためのエンドポイント)を作成する
  - このAPIを利用することで、クライアントIDとクライアントシークレットを元にAuth0で認証できる
- APIサーバ側に、Auth0からのレスポンスの検証処理を記述する

詳細は以下の通り
[Building Secure APIs with Rails 6 and Auth0](https://auth0.com/blog/building-secure-apis-with-rails-6-and-auth0/)
Javaの抽象メソッドと抽象クラス

###詳細未定のメソッド
例えば、車や自転車のメソッドがあるとします。乗り物はすべて「走行する」機能を持ちます。
プログラム上でも、Vehicleクラス(車両)を継承するすべてのクラスはrunメソッド(走行)を持っていたほうがいいです。
よって本来であれば、runメソッドはVehicleクラスに定義し継承できればいいのですが、乗り物ごとに走行方法が違うため、Vehicleクラスでは処理内容を定めることができません。
###抽象メソッド
処理が未定のメソッドを定義する方法は、メソッドの先頭に「abstract」をつけることで、抽象メソッドというメソッドを定義できます。抽象メソッドには**中身の処理**は書きません。
「abstract」とは「抽象的な」という意味です。具体的な処理が決まっていない未完成のメソッドであるため、「抽象メソッド」と呼ばれます。
抽象メソッドは、サブクラスがそのメソッドをオーバーライド（上書き）していなければエラーになります。
なので、サブクラスがそのメソッドをオーバーライドし、処理内容を定義することを強制できます。
サブクラスに、あるメソッドを必ず持たせたいという場合は、スーパークラスに抽象メソッドとして定義しておきます。
###抽象クラス
抽象メソッドを1つでも持つクラスは、「抽象クラス」と呼ばれ、クラス名の前に「abstract」をつけます。
抽象クラスはインスタンスを生成できません。抽象メソッドという未完成のメソッドを持つクラスは、それもまた未完成です。
未完成のクラスからはインスタンスを生成できません。
【例】

```
abstract class SuperClass {  // 抽象クラスの定義
  abstract public void hello();  // 抽象メソッドの定義
}
```
React のチュートリアルを Typescript でやってみた1（チュートリアル概要）

## 目次
- [React のチュートリアルを Typescript でやってみた【環境構築編】](https://qiita.com/humi/items/49a7472e9a10558ea5c0)
- [React のチュートリアルを Typescript でやってみた【環境構築編2】](https://qiita.com/humi/items/72485614151fe564dceb)
- [React のチュートリアルを Typescript でやってみた【ソース準備編】](https://qiita.com/humi/items/72485614151fe564dceb)
- [React のチュートリアルを Typescript でやってみた1](https://qiita.com/humi/items/3d4df671633b7d0f7db3) ←ここ
- [React のチュートリアルを Typescript でやってみた2](https://qiita.com/humi/items/f56214d859a0cf37a895)
- [React のチュートリアルを Typescript でやってみた3](https://qiita.com/humi/items/33e34183ccab3ff60a3b)


## 概要
チュートリアル通りにやりますが、端折る箇所もあると思います。
各々補完をお願いいたします。  

## 公式のチュートリアルページ
* [チュートリアル：React の導入](https://ja.reactjs.org/tutorial/tutorial.html)

## 今回の実施チュートリアル内容
* データを Props 経由で渡す
* インタラクティブなコンポーネントを作る

## データを Props 経由で渡す
チュートリアルのページではjsのコードが書かれていますが、Typescriptではエラーとなります。
よってTypescriptで動作するように書き換えていきます。

まずは、Propsの中身を定義する必要があるためPropsを定義します。
今回はnumberを渡すため以下の様に定義

```tsx:square.tsx
type Props = {
  value: number
}
```

Typescriptでは、Propsは引数で当てる必要があるため以下の様に引数で値を渡します。

```tsx:square.tsx
- class Square extends React.Component {
+ class Square extends React.Component<Props> {
```

あとはvalueを表示するよう書き換え

```tsx:square.tsx
  render() {
    return (
      <button className="square">
        {this.props.value}
      </button>
    );
  }
```

また、squareにデータを渡す箇所も書き換えます。
`square.tsx`で定義したPropsのvalueにデータを渡すイメージです。

```tsx:board.tsx
  renderSquare(i: number) {
    return <Square value={i} />;
  }
```

以上で無事にProps経由でデータを渡すことができました。

## インタラクティブなコンポーネントを作る

Squareコンポーネントがクリックされた場合”X”と表示されるようにします。
まずは、チュートリアルに沿ってクリックされたらアラートが表示されるように書き換え。

```tsx:square.tsx
<button className="square" onClick={function () { alert('click'); }}>
```
コンポーネントをクリックするとアラートが表示される状態になりました。

次にstateをTypescriptで実装してみます。

Porps同様にStateも定義します。
"X"を表示するためStringにしました。

```tsx:square.tsx
type State = {
  value: String
}
```

クラスのコンストラクタ定義は以下のようにしました。  
Stateのvalueの部分ですが、Stringにnullは設定できなかったので空文字にしました。
`type squareValue String | null` なんかを当ててやればnullも定義できると思います。

```tsx:square.tsx
class Square extends React.Component<Props, State> {
  constructor(props: Props) {
    super(props)
    this.state = {
      value: ""
    };
  }
```

最後にクリックの部分を実装します。
しかしこの部分に関してはチュートリアルにかかれているもので問題ありませんでした。

```tsx:square.tsx
  render() {
    return (
      <button className="square" onClick={() => this.setState({ value: 'X' })}>
        {this.state.value}
      </button>
    );
  }
```

今回は以上になります。
次回はゲーム部分の実装を進めていきます。

最終的なソースは以下
https://github.com/humi3/react-tutorial/tree/tutorial_1
Unity で Bit 演算を使ったフラグ管理を作ってみる

# Bit 演算
　Unity では、あまり見ない？（少なくとも、僕はほとんど見たことないです。C とかハードウェアに近いシステムで見た程度。。。）ので、備忘録もかねて簡単なサンプルを作ってみたお話。

## ステータス異常の管理

[[Github] note-nota/BitwiseOperation](https://github.com/note-nota/BitwiseOperation)

![BitOperation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93253/141b02dd-3460-f228-71cd-55af41745dd7.gif)

ステータス異常の状態が左のチェックボックスで表現しています。真ん中のカラムでステータス異常の追加、右側のカラムで回復の操作をそれぞれ行います。

　ステータス異常の定義は以下の enum によって行います。

```C#:StatusFlags.cs
    [Flags]
    public enum StatusFlags
    {
        None      = 0,
        Poisoned  = 1 << 0,
        Blind     = 1 << 1,
        Asleep    = 1 << 2,
        Stunned   = 1 << 3,
        Silenced  = 1 << 4,
        Paralysed = 1 << 5
    }
```

　ステータス異常の操作部分はこんな感じ。
状態変化が起きるときに Event 発火するように `OnUpdateStatus` を定義してます。

```C#:PlayerStatus.cs
        public void AddStatus(byte add)
        {
            status |= (StatusFlags)add;
            OnUpdateStatus.Invoke(status);
        }

        public void DelStatus(byte del)
        {
            status &= (StatusFlags)~del;
            OnUpdateStatus.Invoke(status);
        }
```

## Bit 演算の説明
### [Flags]
　`StatusFlags` クラスは `[Flags]` アトリビュートによって bit 処理の明示を行います。なので、わざわざ書かなくても定義さえしっかりしていれば、bit 演算でも表現されるはず。。。（試してないけど。）

### OR(`|`), AND(`&`), XOR(`^`)

|  |  | `｜` | `＆` | `＾` |
|:---:|:---:|:---:|:---:|:---:|
| 0   | 0   | 0   | 0   | 0   |
| 1   | 0   | 1   | 0   | 1   |
| 0   | 1   | 1   | 0   | 1   |
| 1   | 1   | 1   | 1   | 0   |

### NOT(`~`)
　否定：ビットが逆になる。

### 例：単純な演算

```C#
10101 | 00111 // => 10111
10101 & 00111 // => 00101
10101 ^ 00111 // => 10010

((10101 ^ 00111) | (10101 & 00111)) == (10101 | 00111) // => true
```

### 例：追加／削除

```C#
state = 10101 // 今ある状態
add   = 00010 // 追加したい状態
del   = 00100 // 削除したい状態

// 状態の追加
state | add
10101 | 00010 // => 10111

// 状態の削除
state & ~del
10101 & ~00100
10101 & 11011 // => 10001
```

### 例：判定
`state == (state | flag)` あるいは `flag == (state & flag) `

```C#
state = 10101 // 今ある状態
flagA = 00010
flagB = 00100

// flagA の判定１
state == (state | flagA)
10101 == (10101 | 00010)
10101 == (10111) // => false

// flagA の判定２
flagA == (state & flagA)
00010 == (10101 & 00010)
00010 == (00000) // => false

// flagB の判定１
state == (state | flagB)
10101 == (10101 | 00100)
10101 == (10101) // => true

// flagB の判定２
flagB == (state & flagB)
00100 == (10101 & 00100)
00100 == (00100) // => true
```
java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/android/gms/common/R$string; の解決方法

# 問題

```gradle
     - classpath 'com.android.tools.build:gradle:3.3.2'	
     + classpath 'com.android.tools.build:gradle:3.6.3'
```
Android Gradle Plugin(以後、AGP)のバージョンを上記にあげるとアプリ起動時に常にクラッシュするようになった。
クラッシュの内容は下記(長いので一部のみ)

```
    java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/android/gms/common/R$string;
        at com.google.android.gms.common.internal.StringResourceValueReader.<init>(Unknown Source:4)
        at com.google.firebase.FirebaseOptions.fromResource(com.google.firebase:firebase-common@@19.3.0:156)
        ...
     Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.common.R$string" on path: DexPathList[[zip file "/data/app/jp.co.xxxx.xxxx.dev-adXmK0xgmXrAwD6TRpvPEA==/base.apk"],nativeLibraryDirectories=[/data/app/jp.co.xxxx.xxxx.dev-adXmK0xgmXrAwD6TRpvPEA==/lib/arm64, /data/app/jp.co.xxxx.xxxx.dev-adXmK0xgmXrAwD6TRpvPEA==/base.apk!/lib/arm64-v8a, /system/lib64, /product/lib64]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:196)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
        at com.google.android.gms.common.internal.StringResourceValueReader.<init>(Unknown Source:4) 
        at com.google.firebase.FirebaseOptions.fromResource(com.google.firebase:firebase-common@@19.3.0:156) 
        ...
```
見たところ、firebaseライブラリに問題がありそうだが、調べてもクリティカルな解決方法がなかなか見つからない。
エラーメッセージ内に手がかりが無いクラッシュの解決は本当に骨が折れる。

## 解決方法
いろいろ検証した結果、RealmプラグインとAGPのバージョンの組み合わせが問題なことがわかった。

```gradle
        - classpath 'com.android.tools.build:gradle:3.3.2'	
        + classpath 'com.android.tools.build:gradle:3.6.3'
        - classpath "io.realm:realm-gradle-plugin:5.10.0"	
        + classpath "io.realm:realm-gradle-plugin:6.0.2"
```

## まとめ
すでにAndroid Studio4.0が出ており、AGPも4.0.0が標準となっているので、本記事はあまり役に立たないかもしれないが記録のために残しておく。

ちなみになぜまだ AGP3.6.3を使っているかというと、アプリの設計上AWSのAppSyncSDKを使っておりこれが最新のAGPとGradleに対応していないためだ。どうやらSDKの根本的な設計上の理由らしく、最新のバージョンへすぐに対応するのが難しいようだ。AppSyncを採用しようと考えている人は注意が必要だ。

## 参照
https://stackoverflow.com/a/60401794/6891441

https://github.com/awslabs/aws-mobile-appsync-sdk-android/issues/270
windowsでiverilog その34

#概要

windowsでiverilogやってみた。
負数、書いてみる。

#サンプルコード


```

module mul(input clk, rst, input signed [3:0] a, input signed [3:0] b, output signed [7:0] out);
	reg signed [7:0] out;
	always @(posedge clk or negedge rst)
	begin
		if (!rst)
		begin
			out <= 0;
		end
		else
		begin
			out <= a * b;
		end
	end
endmodule

module test();
	reg clk;
	reg rst;
	reg signed [3:0] a;
	reg signed [3:0] b;
	wire signed [7:0] out;
	mul u(.clk(clk), .rst(rst), .a(a), .b(b), .out(out));
	integer i,
		j;
	initial
	begin
		$monitor("%d %d %d", a, b, out);
		clk = 0;
		rst = 1;
		#10
			rst = 0;
		#10
			rst = 1;
		#10
			a = -5;
			b = -5;
		#10
			$finish;
	end
	always
	begin
		#5
			clk = 1;
		#5
			clk = 0;
	end
endmodule




```

#実行結果


```


 x  x    x
 x  x    0
 x  x    x
-5 -5    x
-5 -5   25


```

以上。
SASテクニック ファイルの読み込み excel csv

## ファイルの読み込み
sasはexcelやcsvなどといったデータを読み込める
sasデータセットならlibnameするだけでokだが、
テキストファイルやexcelファイルはimportプロシジャやdataステップで読み込める
excelはimportやlibname使えるが、ライセンス等が必要
なければDDEで読み込むか、excelをあらかじめcsvへ変換しておいて読み込む

# importプロシジャ

```sas
proc Import dbms = xlsxやcsv replace
  out = 出力データセット名
  datafile = "パス\ファイル名.拡張子" ;
  range = "シート名$範囲" ; %* excelなら *;
run;
```

getnamesとかオプション等いろいろあるが基本はこれ
範囲はA1:C99など
excelの拡張子がxlsとかならdbms = excelかexcelcsじゃないと動かなかった気がする...
※SAS/ACCESSのライセンスがないとexcelをimportできない
読み込みたいexcelファイルを他の人が開いているときにimportプロシジャ使うとエラーとなるので、サーバーなどでファイルを共有している場合には注意

# dataステップ(csv,txtなどテキストファイルの読み込み)
とりあえずいつもコピってるやつ

```sas
data 出力データセット名 ;
  length VAR1 - VAR200 $10000;
  infile "パス\ファイル名.拡張子" dsd missover lrecl = 30000 firstobs = 1;
  input VAR1 - VAR200;
run;
```

列名がファイルの1行目にあるならfirstobs = 2とすればいい
importと違って、変数定義が細かくできるからこっちのほうがいいかも
importの方が記述は楽だけどね

# DDE(excel読み込み)
これもいつもプログラムをコピってる

```sas
%* excelを開く(元々開いていて、読み取り専用になってもok) *;
options noxwait noxsync;
%sysexec "パス\ファイル名.xlsx" ;

filename EXL_DDE dde "Excel|[ファイル名.xlsx]シート名!範囲";
data 出力データセット名 ;
  length VAR1 - VAR200 $10000;
  infile EXL_DDE notab dlm = "09"x dsd missover lrecl = 30000 firstobs = 1;
  input VAR1 - VAR200;
run;

%* excel閉じる *;
filename AAA dde "excel|system" ;
data _NULL_;
  file AAA;
  put "[close()]" ;
run;
filename EXL_DDE clear;
filename AAA clear; 
```



https://www.sas.com/offices/asiapacific/japan/service/technical/faq/list/body/ba196.html
https://support.sas.com/documentation/cdl_alternate/ja/lestmtsref/68024/HTML/default/n1rill4udj0tfun1fvce3j401plo.htm
https://www.sas.com/offices/asiapacific/japan/service/technical/faq/list/body/pc074.html
MacでPDFから文字をコピペした時、濁点が分かれてしまう

# 原因

このあたりが詳しいです。
http://nakamura001.hatenablog.com/entry/20120529/1338305696
https://www.slideshare.net/emasaka/ss-82692529
NFC/NFDの違いによるもので、やはりこの問題はMacを使っていると出てくることが多いみたいです。

# 今回した対応
nkfで変換できるようでした。なのでコピーする時にnkfを実行するように設定しました。

## nkfインストール
homebrewで入れます。  

```
brew install nkf
```

## Automatorの設定

Automatorを起動
新規作成 -> クイックアクション
以下の画像のようにワークフローを設定。
<img width="613" alt="スクリーンショット 2020-06-15 18.55.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607661/8d51423f-7d66-3925-c4a6-7d22400a66d4.png">

## シェルスクリプトの中身を設定
"シェルスクリプトを実行"の部分はbashにして以下のスクリプトを貼る。

```
/usr/local/bin/nkf -w --ic=UTF8-MAC
```

これで保存します。名前は各自好きなものでいいと思います。
私は今回単純にcopy_textとしました。

## ショートカットの登録
Macのシステム環境設定からキーボードの設定を開きます。
以下の画像のように ショートカット -> サービス -> テキスト で先ほどAutomatorで作ったものを任意のショートカットに登録します。
<img width="617" alt="スクリーンショット 2020-06-17 8.47.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607661/4b4f7f88-590d-799e-b2af-db6ca0c0250d.png">
これで無事にPDFからのテキストコピペがいい感じにできるようになりました。

# 参考にした記事
こちらを参考に対処しました
https://qiita.com/takuyabe/items/ac13aa99306ad69743e7
【javascript】テンプレートリテラルについて

こちらの記事は以下の書籍を参考に執筆しました

- [入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)



#テンプレートリテラル
テンプレートリテラルは以下の3つの機能をサポートしている

- 補間
- 複数行
- タグ付け

#使い方
補間の対象となる値を波括弧`{}`でくくり先頭に`$`をつける。

```javascript
function fa(str){
  return `fa-${str}-ra`;
}

console.log(fa('test')); // fa-test-fa
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)

##テンプレートリテラルは再利用可能なテンプレートではない
以下のコードでは何が出力されるだろうか

```javascript
let name = 'JD';
let greetingTemplate=`Hello,${name}`;
name='Jon';
console.log(greetingTemplate));
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)



答えは`Hello,JD`

テンプレートリテラルが値を補間するのは**作成時**であり、新しい値を使って再び評価する方法は**ない**。
pathヘルパー(_path)が返すのは相対パス？絶対パス？: Railsチュートリアル備忘録

# pathヘルパー(_path)が返すのは相対パス？絶対パス？: Railsチュートリアル備忘録

pathヘルパーとurlヘルパーの使いどころの違いを調べていると
**”pathヘルパーは相対パス、urlヘルパーは絶対パスを返す”**

というような表記がされることに違和感を感じて調べてみた




## 前提としてローカル環境に限っては

my_roomというディレクトリを示す以下の様なフルパス（完全なパス）が存在する時

```
/my_city/my_home/my_room/i_am_here.html.erb
```



### 絶対パス (=フルパス)

`/`(ルート: 最上層のディレクトリ)から見たパス（経路）
表記は**必ず先頭に`/`(ルート)**がくる

```
/my_city/my_home/my_room/i_am_here.html.erb	# rootからみたi_am_here.html.erbのパス表記
```



### 相対パス

現在いる場所から見たパス（経路）
表記は先頭に**`/`(ルート)を含まない**

```
my_home/my_room/i_am_here.html.erb 	# my_cityからみたi_am_here.html.erbのパス表記
my_room/i_am_here.html.erb         	# my_homeからみたi_am_here.html.erbのパス表記
../i_am_here.html.erb      	# i_am_here.html.erbからみたmy_homeのパス表記
```

というようにシンプルに考える事ができる



## Railsの開発環境においては？

### `/`のあり表記、なし表記の混在

これまで2つの表記があり、それを曖昧にしてきた

ルーティングを記載する場合に
Railsチュートリアルでは`/`(ルート)をつけるのに対して
Progateでは`/`(ルート)をつけない表記(`link_to`などでは`/`がついているのに)となっていた

これは理解が簡単で
Progate式に`/` なしでルーティング記述しても

```ruby
  get 'help',      to: 'static_pages#help'	# help -> /helpでも実行結果は同じ
  get 'about',     to: 'static_pages#about'
.
.
.  
```

実際のルーティングを確認すると
`/`(ルート)が補完されていることがわかる

```
$ rails routes
	Prefix Verb   URI Pattern   	Controller#Action
	 root GET    /									static_pages#home
	 help GET    /help(.:format)		static_pages#help
  about GET    /about(.:format)		static_pages#about
.
.
.
```

**Railsが勝手に補完してくれるからどちらの表記でも良いが
内部処理した結果は`/`を基準とした、絶対パスのような表記に見える**



### pathヘルパーは相対パスを返す？

また、Railsチュートリアルでお世話になるpathヘルパー
`resouceがもたらしてくれるあいつ

以下を参考にすると
ルーティングの記述と同様
pathヘルパーは**`/`を基準とした絶対パス？を返しているようにみえる**

>2.3 パスとURL用ヘルパー
>リソースフルなルーティングを作成すると、アプリケーションのコントローラで多くのヘルパーが利用できるようになります。resources :photosというルーティングを例に取ってみましょう。
>
>photos_pathは/photosを返します
>new_photo_pathは/photos/newを返します
>edit_photo_path(:id)は/photos/:id/editを返します (edit_photo_path(10)であれば/photos/10/editが返されます)
>photo_path(:id)は/photos/:idを返します。 (photo_path(10)であれば/photos/10が返されます)
>これらの_pathヘルパーには、それぞれに対応する_urlヘルパー (photos_urlなど) があります。**_urlヘルパーは、_pathの前に現在のホスト名、ポート番号、パスのプレフィックスが追加されている点が異なります。**
>
>[Rails のルーティング - Railsガイド](https://railsguides.jp/routing.html)

### これって絶対パスなの？相対パスなの？

Railsが扱っているパスは絶対パスなの？相対パスなの？と考える上で
以下のサイトが参考になった

[【初心者向け】絶対パスと相対パスの違いをイラストを使って解説！ | webliker](https://webliker.info/78726/)

つまりRailsが扱っている`/...`というパスは
**相対ルートパス**なるもので、**ルートパス(相対的、仮想的な？ルート)を基準とした絶対パスのようなもの**
と理解した

開発環境から、本番環境への移行が想定されるので
（最初の例ではhomeディレクトリは別のcityディレクトリへの引っ越しが決まっている）
開発環境においてフルパス表記とするすることは得策でない
かつ相対パスがもつ構造変化に対する脆弱性を回避するために
ルート相対パスが便利なんだろう



### urlヘルパーは絶対パス?

再び上記Railsガイドを参考にすると

pathヘルパーがルート相対パスを返すのに対して
urlヘルパーは自身が置かれれた環境における（本番環境なら本番環境のサーバーに応じた）
**フルパスを取得して返していると考えられる**



## Reference:

[pathメソッドと_urlメソッドの使い分け - Qiita](https://qiita.com/higeaaa/items/df8feaa5b6f12e13fb6f)

[違いを説明できますか？「フルパス」「絶対パス」「相対パス」の違い フラップイズム](https://www.flapism.jp/other/194/)
intra-mart Forma Designer 処理ボタンのラベルをノード毎に変更するスクリプト

本記事では、intra-mart Accel PlatFormの基盤上で動作するアプリケーション、
Forma-Designer(以下、Forma)を用いた技術投稿記事になります。

Forma-Designerの詳細については、下記公式ガイドを参照願います。
https://www.intra-mart.jp/document/library/forma/public/forma_appli_maker_guide/introduction.html


標準機能では、「処理」ボタンのラベルは次のワークフローの処理単位で変更することが可能です。

・申請時
・再申請時
・承認時
・参照時

しかし、ノード単位で表示ラベルを制御することはできません。

以下にノード別にボタンラベルを変更する手順を記載します。

１．フォーム編集画面より、処理ボタンを配置
２．処理ボタンのデフォルトラベルを設定
３．ラベル変更用のスクリプトを作成
４．アクション設定の初期処理 or スクリプトアイテムに設定


１．処理ボタンを配置

　ボタンアイテムをフォーム内に設置します。
　標準機能です。


２．処理ボタンのデフォルトラベルを設定

　設置したボタンアイテムのラベルプロパティ値を変更します。
　標準機能です。


３．ラベル変更用のスクリプトを作成

　以下プログラムを作成します。

// 現在のノードIDを取得
var nodeId = $("input[name='imwNodeId']).val();

// 対象ノードの場合、処理ボタンのラベルを変更する
if (nodeId === "%変更対象のノードID%") { // (※1)
　　var buttonElem = $(".imui-large-button"); // (※2)
　　for (var i=0; i<buttonElem.length; i++) {
　　　　if (buttonElem[i].value === "%本項「２」にて設定したデフォルトラベル%") { // (※1)
　　　　　　buttonElem[i].value = "%設定するラベル%"; // (※1)
　　　　　　break;
　　　　}
　　}
}

※1 「%%」内は正しい値と置換して下さい。
※2 設置するボタンのサイズによって異なります。今回の例は、ボタンサイズ「1」のものです。


４．アクション設定の初期処理 or スクリプトアイテムに設定

　本項「３」にて作成したスクリプトを、アクション設定の初期処理 or ツールキットのスクリプトアイテムに設定します。


以上になります。