OmniAICreator/Qiita-1.07M huggingface dataset:
Rails6 のちょい足しな新機能を試す79（enum negative scope編）

# はじめに

Rails 6 に追加された新機能を試す第79段。 今回は、 `enum negative scope` 編です。
Rails 6 では、 モデルで `enum` を使ったとき、 negative scope が定義されるようになりました。
Ruby 2.6.4, Rails 6.0.0 で確認しました。Rails 6.0.0 は `gem install rails` でインストールできます。

```shell
$ rails --version
Rails 6.0.0
```

今回は、 Child モデルを作成して `rails console` を使って確認します。

# プロジェクトを作る

```shell
rails new rails_sandbox
cd rails_sandbox
```

# Child モデルを作る

name と generation の2つの属性をもつ Child モデルを作ります。
generation は enum にするため、 integer にします。

```shell
bin/rails g model Child name generation:integer
```

# enum を定義する

Child モデルに enum を定義します。

```ruby:app/models/child.rb
class Child < ApplicationRecord
  enum generation: %i[baby toddler preschool gradeschool teen young_adult]
end
```

# seed データを作成する

seed データを作成します。

```ruby:db/seeds.rb
Child.create(
  [
    { name: 'Andy', generation: :baby },
    { name: 'Bob', generation: :toddler },
    { name: 'Cindy', generation: :preschool }
  ]
)
```

# マイグレーションを実行し seed データを登録する

```shell
bin/rails db:create db:migrate db:seed
```

# rails console で確認する

`rails console` で確認します。

`Child.not_baby` を実行してみます。

```irb
irb(main):001:0> Child.not_baby
  Child Load (0.3ms)  SELECT "children".* FROM "children" WHERE "children"."generation" != $1 LIMIT $2  [["generation", 0], ["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Child id: 2, name: "Bob", generation: "toddler", created_at: "2019-08-31 00:54:50", updated_at: "2019-08-31 00:54:50">, #<Child id: 3, name: "Cindy", generation: "preschool", created_at: "2019-08-31 00:54:50", updated_at: "2019-08-31 00:54:50">]>
```

`Child.not_baby.not_toddler` を実行してみます。

```irb
irb(main):003:0> Child.not_baby.not_toddler
  Child Load (0.5ms)  SELECT "children".* FROM "children" WHERE "children"."generation" != $1 AND "children"."generation" != $2 LIMIT $3  [["generation", 0], ["generation", 1], ["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Child id: 3, name: "Cindy", generation: "preschool", created_at: "2019-08-31 00:54:50", updated_at: "2019-08-31 00:54:50">]>
```

こちらもちゃんと動作しました。

# 試したソース

試したソースは以下にあります。
https://github.com/suketa/rails_sandbox/tree/try079_enum_negative


# 参考情報

* [What is new in Rails 6.0](https://bogdanvlviv.com/posts/ruby/rails/what-is-new-in-rails-6_0.html)
* [Add negative scopes for all enum values](https://github.com/rails/rails/pull/35381)
GCPのサービスエージェントがなくなったときは、APIを有効化すると復活する

原因不明です。復旧策を書きます。

# まとめ
- Google Cloudの「IAMと管理」の役割からサービスエージェントが消えてしまうことがあります
- そうなると、さまざまな操作ができなくなる
- APIの無効化したあと、APIの有効化をすると、サービスエージェントが復活する

# Dataflow サービス エージェント がなくなってしまった事象の解決手順
GCPのとあるプロジェクトでDataflowを本番環境で試しました。

しかし、Google Cloudが自動的に作成するIAMの権限が足りないという旨のエラーが出るようになりました。

## エラーメッセージの確認
```
JOB_MESSAGE_ERROR: Workflow failed. Causes: There was a problem refreshing your credentials. Please check:
1. Dataflow API is enabled for your project.
2. There is a robot service account for your project:
service-[project number]@dataflow-service-producer-prod.iam.gserviceaccount.com should have access to your project. If this account does not appear in the permissions tab for your project, contact Dataflow support., There is no cloudservices robot account for your project.  Please ensure that the Dataflow API is enabled for your project.
```

ひとつひとつチェックしていきます。

- Dataflow APIは有効化されているか？
    - →有効化されている
- `service-[project number]@dataflow-service-producer-prod.iam.gserviceaccount.com` がプロジェクトにアクセスできない
    - →該当のサービスアカウントにプロジェクトオーナー権限を与えても動作しなかった
    - オーナー権限を与える前は、「Compute ストレージ管理者」のみが与えられていた

## 別のプロジェクトとの比較
不穏だなと思ったので、別のアカウントを見に行くことにしました。

別のプロジェクト `service-[project number]dataflow-service-producer-prod.iam.gserviceaccount.com` を見ると、 *Dataflow サービス エージェント` という特殊な役割が付与されていました。

**サービス エージェント** とは何か、ドキュメントで調べてみます。

> サービス アカウント（service-project-number@dataflow-service-producer-prod.iam.gserviceaccount.com）が使用されます。このアカウントは、Cloud Dataflow プロジェクト作成時に自動的に作成され、そのプロジェクトに対する Cloud Dataflow サービス エージェントの役割が割り当てられます。さらに、そのプロジェクトで Cloud Dataflow ジョブを実行する（これには Compute Engine ワーカーの起動も含まれます）のに必要な権限が付与されます。このアカウントは Cloud Dataflow サービス専用であり、プロジェクトに固有のものです。

(https://cloud.google.com/dataflow/docs/concepts/security-and-permissions?hl=ja#cloud_dataflow_service_account より抜粋)

なるほど。自動的に作成される **役割** のようです。そして各サービス(ここではCloud Dataflow)に必要な権限が付与されているようです。

じゃあ、サービスアカウトに作成されているはずの役割(サービスエージェント)を追加すればよさそうですね。

## サービスエージェントの存在確認
「IAMと管理」の **役割** を見てみました。

いろんなサービス エージェントがあることが確認できましたが、 **Dataflow サービス エージェント** は見当たりませんでした。自動的に作られるはずのサービス エージェントがない。

## 仮説
上記のエラーメッセージから、「サービス エージェントはきっとAPI有効化されたときに初めて作成される」と仮説を立てて検証しました。

Cloud Dataflowはまだ本番で利用していなかったので、ためらいなくAPIを無効化しました。

そのあと、API有効化してIAMを見ると、 `service-[project number]dataflow-service-producer-prod.iam.gserviceaccount.com` に `Dataf low サービス エージェント` が役割として追加されていました。

仮説が正しかったようです。

## 再実行
エラーメッセージに書かれていた、APIの有効化とサービスアカウントの権限見直しを実施できたため、もう一度実行してみます。

無事終了しました。
TENKitの入力を平仮名に変換（ポケベルモード）

**本記事は、[TENKit](https://tenkit.jp/) の応用的な利用について説明いたします。
事前に基礎編「 [TENKitとGoogleスプレッドシートの連携（簡単記録編）](https://qiita.com/tetotetote/items/bbacc6671b7b9f5846b3)」をご確認いただきますようお願いします。**

[TENKit](https://tenkit.jp/) （テンキット）は「テンキー」を「IoT」化するキットです。
[TENKit](https://tenkit.jp/) では、テンキーで入力された「数字」と、Googleスプレッドシートなどクラウド上のサービスを簡単に結びつけることができます。

ここでは、[TENKit](https://tenkit.jp/) の応用的な利用として、入力された「数字」を「平仮名」に変換する方法について説明します。
「平仮名」への変換は、昔の「ポケベル」と同じやり方ですので、「ポケベルモード」と呼びます。

# 平仮名への変換（ポケベルモード）

入力の最初に**「 *2*2 」**と入力してください。これによりポケベルモードに切り替わります。
その後、以下の変換表に基づき、行を1文字目、列を2文字目として、平仮名に対応する数字を入力してください。
（ 例：12 → い 、43 → つ 、2104 → が 、96 → 1 ）


|   |1  |2  |3  |4  |5  |6  |7  |8  |9  |0  |
|---|---|---|---|---|---|---|---|---|---|---|
|1  |あ  |い  |う  |え  |お  |A  |B  |C  |D  |E  |
|2  |か  |き  |く  |け  |こ  |F  |G  |H  |I  |J  |
|3  |さ  |し  |す  |せ  |そ  |K  |L  |M  |N  |O  |
|4  |た  |ち  |つ  |て  |と  |P  |Q  |R  |S  |T  |
|5  |な  |に  |ぬ  |ね  |の  |U  |V  |W  |X  |Y  |
|6  |は  |ひ  |ふ  |へ  |ほ  |Z  |?  |!  |ー  |/  |
|7  |ま  |み  |む  |め  |も  |¥  |&  |  |  |  |
|8  |や  |(  |ゆ  |)  |よ  |*  |#  |  |  |  |
|9  |ら  |り  |る  |れ  |ろ  |1  |2  |3  |4  |5  |
|0  |わ  |を  |ん  |゛  |゜  |6  |7  |8  |9  |0  |

# 利用上の注意点

無線タイプのテンキーをご利用の際、数字の入力は1文字ずつ確実に行ってください。

無線タイプのテンキーでは、ドライバー仕様により、入力を一定時間バッファーに溜めてから本体に送信されます。
ここで、高速で連続入力し、一定時間内の入力がバッファーの容量を超えた場合、以降の入力をうまく認識できなくなります。
ご迷惑をおかけしますが、ご了承の上、ご注意してご利用ください。
LaravelのincludeWhenはfalseでも右辺の評価が行われてしまう。

# includeWhenの条件式が false でも右辺が評価されてしまう
そのため isset で変数があるかどうかチェックしても、右辺が評価されてしまい
Undefined variable: user と表示されてしまう。

```blade.php
@includeWhen(isset($user), 'tags.google', ['user' => $user])
```

諦めてif文で書きましょう

```blade.php
@if (isset($user))
  @include('tags.google', ['user' => $user])
@endif
```
リモートにあるbranchをローカルに持ってきたい

## 概要
gitでリポジトリを管理してるとリモートにあるbranchをローカルに持ってきたいことが多々ある。
私の場合だと会社用と持ち運び用で2台PCを持っているので,どちらのPCでも内容を引き継いで開発ができるようにしたかった


## やること
#### 1.branchを確認
```
git branch -a
```
持ってきたいbranchがあるかを確認する。
なければ最新版を持ってくる。

```
git fetch
```


#### 2.branchをcheckout
```
git checkout -b 【branch名】 origin/【branch名】
```
【JS】わずか5文字！document.querySelectorAllの返り値を配列に変える方法

# お前のすべてが欲しい...

**結論を知りたい人は[スプレッド構文を使う](#スプレッド構文を使う)**へ

 HTML内の特定の要素をすべて取得したいというときは `document.querySelectorAll` を使うと便利です。

`.item` というクラスをすべて取得したいとき

```index.html
 <ul>
  <li class="item">item1</li>
  <li class="item">item2</li>
  <li class="item">item3</li>
 </ul>
```

```script.js
const items = document.querySelectorAll('.item');
```

と、このように簡単にすべての要素が取得できるのです。めでたしめでたし。


・・・が、ひとつ注意点！！

## 返り値は `NodeList`

さてこの配列？を操作しようと思ったらここに落とし穴があるのです。返り値は `Array` ではなく `NodeList` 。そう、配列ではありません。

### `NodeList` を操作するには 

`forEach()` メソッドを使うのが便利です。

```js
const items = document.querySelectorAll('.item');
items.forEach((item) => {
  console.log(item);
});
```

だけど`配列（Array）` にしたい時があるかと思います。

### `NodeList`を配列に変換するには

[NodeList | MDN](https://developer.mozilla.org/ja/docs/Web/API/NodeList)

によると

>NodeList は Array とは異なりますが、 forEach() メソッドで処理を反復適用することは可能です。 Array.from() を使うことで Array に変換することができます。

なるほど。 `Array.from()`メソッド を使えば配列に変換することができるようです。

```js
const items = document.querySelectorAll('.item');
const itemsArray = Array.from(items);
```

一気に操作したい場合は、

```js
Array.from(document.querySelectorAll('.item'), item => {
 console.log(item);
});
```

## もっと簡単に配列に変換したい

`Array.from()`メソッドで配列に変換できることはわかりました。ですが、もうちょっと簡単に配列に変換する方法があります。

## スプレッド構文を使う

```js
const items = [...document.querySelectorAll('.item')];
```

なんということでしょう、`[]`と`.`だけで配列に変換できました。

### 関数化

```nodeListToArray.js
const nodeListToArray = nodeList => [...nodeList];

nodeListToArray(document.childNodes); // [ <!DOCTYPE html>, html ]
```

### スプレッド構文とは

[スプレッド構文 | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax)
>スプレッド構文を使うと、関数呼び出しでは 0 個以上の引数として、Array リテラルでは 0 個以上の要素として、Object リテラルでは 0 個以上の key-value のペアとして、Array や String などの iterable オブジェクトをその場で展開します。

配列に転換したい場合は、配列の中に iterable なオブジェクトを入れてあげればよいのです簡単ですね。

### スプレッド構文の注意点
また、こんなこともMDNのページには書いてありました。

> ###大量の値を展開する場合セクション
JavaScript エンジンには、引数の個数に上限があります。関数呼び出しでのスプレッド構文では、引数の個数がその上限を超えてしまう可能性に留意してください。詳細は [apply()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/apply)のページを参照してください。

引数に上限があるようなので注意しましょう。

### スプレッド構文のブラウザー実装状況


[スプレッド構文 ブラウザー実装状況](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Browser_compatibility)

IEでは動きません・・・
適宜トランスパイルをしましょう。

---
#### 参考

[Document.querySelectorAll() | MDN](https://developer.mozilla.org/ja/docs/Web/API/Document/querySelectorAll)
[Array.from() | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/from)
[NodeList | MDN](https://developer.mozilla.org/ja/docs/Web/API/NodeList)
[スプレッド構文 | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax)
[Converting a NodeList to an array with vanilla JavaScript](https://gomakethings.com/converting-a-nodelist-to-an-array-with-vanilla-javascript/)
[querySelectorAllで帰ってきたNodeListを外部ライブラリを使わずにforEachしたい](https://qiita.com/yugo-yamamoto/items/b87470f118ac62dc6a8d)
[nodeListToArray - 30 seconds of code](https://www.30secondsofcode.org/js/s/node-list-to-array)
EC-CUBE4 全ページで使える twig 変数を定義する方法

## 値を静的に設定する方法

`eccube_config` に値を追加します。

```yaml:source/app/config/eccube/packages/prod/eccube.yaml
parameters:
  env(VAR_TEST): 'DEFAULT VAR'
  var_test: '%env(VAR_TEST)%'
```

```:.env
VAR_TEST="TEST"
```

同様に `source/app/config/eccube/packages/dev/eccube.yaml` にも定義します。

なお `source/app/config/eccube/packages/eccube.yaml` は、バージョンアップなどで書き換わることがあるかもしれないので、手を加えないようにしています。

## 値を動的に設定する方法

例えば、カートに入っている情報を元に、送料無料条件を満たしているかを計算して
ページのヘッダーなどに、その状態を表示するときなどに使えそうです。

```php:source/app/Customize/Event.php
namespace Customize;

use Eccube\Request\Context;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Twig\Environment;

class Event implements EventSubscriberInterface
{
    /** @var Context */
    protected $requestContext;

    /** @var Environment */
    protected $twig;

    /**
     * Event constructor.
     *
     * @param Context $requestContext
     * @param Environment $twig
     */
    public function __construct(
        Context $requestContext,
        Environment $twig
    )
    {
        $this->requestContext = $requestContext;
        $this->twig = $twig;
    }

    /**
     * @return array
     */
    public static function getSubscribedEvents()
    {
        return [
            KernelEvents::REQUEST => ['onKernelRequest', 100000000]
        ];
    }

    /**
     * @param GetResponseEvent $event
     */
    public function onKernelRequest(GetResponseEvent $event)
    {
        if ($this->requestContext->isAdmin()) {
            return;
        }

        $this->twig->addGlobal('var_test', 'TEST');
    }
}
```

なお、 `KernelEvents::CONTROLLER_ARGUMENTS` を Subscribe して以下のような
関数にコールバックする方法がありますが、お問い合わせフォームの確認画面のように
リクエストの途中でテンプレートが差し代わるような場合に、差し代わった方のテンプレートでは
変数が設定されていない状態となっていました。

```php:source/app/Customize/Event.php
    /**
     * @param FilterControllerEvent $event
     */
    public function onKernelController(FilterControllerEvent $event)
    {
        if ($event->getRequest()->attributes->has('_template')) {
            $template = $event->getRequest()->attributes->get('_template');
            $this->eventDispatcher->addListener($template->getTemplate(), function (TemplateEvent $templateEvent) {
                $templateEvent->setParameter('var_test', 'TEST');
            });
        }
    }
```
#Rails の ActiveJob でリトライ間隔、リトライの最大回数を指定する

```rb
class RetryJob < ApplicationJob
  class CustomAppException < StandardError
  end

  retry_on CustomAppException, wait: 1.seconds, attempts: 3 do |job, error|
    puts "JOB FAILED! RETRY!"
  end

  def perform(*args)
    raise CustomAppException

    puts "JOB WORKED! #{Time.current}"
  end
end

```

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2425








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
【Unity】Unity Hubを使用しているとVuforia AR Supportのインストールが上手く行かない件について

# 概要
Unity Hub
https://docs.unity3d.com/ja/current/Manual//GettingStartedUnityHub.html
> Unity Hub は、Unity のプロジェクトとあらゆるバージョンのインストーラーの検索、ダウンロード、管理などを効率化するスタンドアロンアプリケーションです。また、すでにマシンにインストールされているエディターのバージョンを Hub に手動で追加することもできます。

Vuforia
https://en.wikipedia.org/wiki/Vuforia_Augmented_Reality_SDK
> Vuforiaは、拡張現実アプリケーションの作成を可能にするモバイルデバイス用の拡張現実ソフトウェア開発キットです。

これを使ってスマホでARアプリを作りたかったのですが、インストールに若干ハマりました＝＝

# 環境
Unity Hub
Unity 2018.4.2f1
UnitySetup-Vuforia-AR-Support-for-Editor-2018.4-2019.1.exe

# インストール（できない）
普通にインストーラを起動し、Next, Nextしてるとフォルダパスを求められます。

![2019-09-13_12h08_59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147118/af637fda-b65c-5924-3798-7766e783be68.png)

'C:\Program Files\Unity'って書いてあるからそれでいいのかなと思いきや･･･

![2019-09-13_12h11_44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147118/6bb77380-2aa7-798c-9307-ee85d65ffcae.png)


![2019-09-13_12h12_15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147118/91f93a73-00c5-1753-d8e5-8779d8f238d7.png)


# インストール（できた）

ここまでを選択してあげたらできました。
![2019-09-13_12h14_45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147118/9f846d1f-ae53-0b53-c515-5f953d0ac940.png)

![2019-09-13_12h15_13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147118/ff449f68-9569-b355-86a7-06d1b0721c92.png)


# 感想
Unity Hubは考慮されてないんだナー(´ぅω・｀)
【便利ツール】Unubo①

以下のブログを読んで、無料だし、便利そうなホスティングサービスそうだったので、
とりあえずアカウントを作ってみる。

[Node.js,Python,RubyなどのWebアプリを完全無料でホスティング可能な「Unubo」を使ってみた！](https://paiza.hatenablog.com/entry/2019/09/11/Node_js%2CPython%2CRuby%E3%81%AA%E3%81%A9%E3%81%AEWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%92%E5%AE%8C%E5%85%A8%E7%84%A1%E6%96%99%E3%81%A7%E3%83%9B%E3%82%B9%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E5%8F%AF)

---
# アカウント作成の流れ

## 1.Unuboのサイトを開く

[Unubo](https://unubo.com/)

<img width="1440" alt="ScreenShot.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33479/165424f9-b021-8000-b9c9-48ef9caa2941.png">

## 2.SignUpを押下する

アカウント作成に必要な情報を入力する

<img width="1440" alt="ScreenShot.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33479/c8b2283b-7436-52cb-bfbd-6de17387630c.png">

## 3.登録確認する

登録したメールアドレス宛てに確認メールがくるので、承認する

<img width="1440" alt="ScreenShot 11.50.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33479/db099d48-d15b-ec15-5eab-2a7a22b04f08.png">

↓

<img width="1440" alt="ScreenShot.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33479/d69f50c2-72c3-999c-b2a1-9afd5cda5f9c.png">


## 4.ログインする

設定したアカウントでログインができるか確認する

<img width="1440" alt="ScreenShot.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33479/ad33e37b-21d0-c59d-0c20-32887ddd11d1.png">

## 5.サービス利用可能になる

<img width="1440" alt="ScreenShot.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33479/dddd51f5-1cbe-452f-341c-09e6394cc110.png">
Rails distinctメソッドについて

## distinctメソッド

distinctメソッドとは重複レコードを1つにまとめるためのメソッドです。もともとはuniqというメソッドが同じ機能で使えていたようですがRails5になってからはdistinctメソッドを使うように決められているようです。（uniqメソッドは非推奨もしくは使用不可に変更されているようです。）

Railsのdistinctの使い方に関してはっきり分からなかったので自分で検証して確認してみることにします。今回はrails cを使ってモデルを作成して検証します。前準備として、

```
rails new distinct_app
rails g model User last_name:string first_name:string birthday:date age:integer
```

として、アプリケーションを作成してモデルも作成します。その後、rails cでコンソールモードにしてコマンドでデータを作成していきます。

```shell
User.create(last_name: "Toda", first_name: "Hiroyuki", birthday: "1988-08-17", age:31)
User.create(last_name: "Suzuki", first_name: "Hiroyuki", birthday: "1988-08-17", age:31)
User.create(last_name: "Woda", first_name: "Hiroyuki", birthday: "1988-08-17", age:31)
User.create(last_name: "Toda", first_name: "Hiroyuki", birthday: "1988-06-01", age:31)
User.create(last_name: "Toda", first_name: "Taro", birthday: "1988-06-01", age:31)
User.create(last_name: "Toda", first_name: "Ichiro", birthday: "1988-06-01", age:31)
User.create(last_name: "Toda", first_name: "Hanako", birthday: "1988-06-01", age:31)
```

というようにUserモデルを作成します。その後、コマンドで

```
User.select(:first_name, :age).distinct
```

とすると、

```
=> #<ActiveRecord::Relation 
[#<User id: nil, first_name: "Hiroyuki", age: 31>,
 #<User id: nil, first_name: "Taro", age: 31>,
 #<User id: nil, first_name: "Ichiro", age: 31>,
 #<User id: nil, first_name: "Hanako", age: 31>]
>
```

という結果が返ってきて問題なさそうです。

### distinctはselectしなくても問題ないか？

```
User.distinct(:first_name)
```
のように書いて、first_nameカラムが重複しないようになるか試してみました。結果は

```
=> #<ActiveRecord::Relation [
#<User id: 1, last_name: "Toda", first_name: "Hiroyuki", birthday: "1988-08-17", age: 31, created_at: "2019-09-13 01:49:32", updated_at: "2019-09-13 01:49:32">,
#<User id: 2, last_name: "Suzuki", first_name: "Hiroyuki", birthday: "1988-08-17", age: 31, created_at: "2019-09-13 01:49:44", updated_at: "2019-09-13 01:49:44">,
#<User id: 3, last_name: "Woda", first_name: "Hiroyuki", birthday: "1988-08-17", age: 31, created_at: "2019-09-13 01:49:54", updated_at: "2019-09-13 01:49:54">, 
#<User id: 4, last_name: "Toda", first_name: "Hiroyuki", birthday: "1988-06-01", age: 31, created_at: "2019-09-13 01:50:46", updated_at: "2019-09-13 01:50:46">, 
#<User id: 5, last_name: "Toda", first_name: "Taro", birthday: "1988-06-01", age: 31, created_at: "2019-09-13 01:52:16", updated_at: "2019-09-13 01:52:16">, 
#<User id: 6, last_name: "Toda", first_name: "Ichiro", birthday: "1988-06-01", age: 31, created_at: "2019-09-13 01:52:24", updated_at: "2019-09-13 01:52:24">, 
#<User id: 7, last_name: "Toda", first_name: "Hanako", birthday: "1988-06-01", age: 31, created_at: "2019-09-13 01:52:33", updated_at: "2019-09-13 01:52:33">]>
```

となりました。これだと重複が防げてないですね。。どうやら一度selectしてからdistinctを実行する必要があるみたいです。

### まとめ

distinctコマンドは内部的にはSQLのDISTINCTコマンドを呼び出しています。個人的に何となくselectしなくても重複を避けられると思っていたので、今回の検証の結果は意外なものでした。distinctする場合は、selectとしてから...忘れないようにします。
Ubuntu ファイル名の一括置換(rename コマンド)

Ubuntuのファイル名置換は、少しだけクセがあるのでまとめました。
Ubuntu以外のOSは[こちら](http://linuxjm.osdn.jp/html/util-linux/man1/rename.1.html)。

# rename コマンドをインストール

```bash
sudo apt-get install rename
```

# ファイル名の変更

## 単語の置き換え

```bash
rename "s/[置き換えたい単語]/[置き換え後の単語]" [ File-Path ]
# 処理結果を表示したい場合
rename -v "s/[置き換えたい単語]/[置き換え後の単語]" [ File-Path ]
```

```"s/[置き換えたい単語]/[置き換え後の単語]"``` の部分は、 ```perl``` や ```sed``` での置換と同じです。
```fileA.sh``` を ```fileB.sh``` に置き換えるときは以下のようになります。

```bash
# `fileA.sh' renamed as `fileB.sh'
rename "s/A/B/" fileA.sh
```

## ワイルドカードで一括置換

ワイルドカードだと予期せぬファイルまでファイル名が変わってしまう可能性があるので、利用する際は必ずテスト環境などでお試しください。

拡張子で指定

```bash
rename "s/file/test/" *.sh
```

前後の文字列が一致するものを指定

```bash
rename "s/file/test/" file*.sh
```

## 特定のファイルのみ操作するとき

ファイル名を複数指定

```bash
# `fileA.sh' renamed as `A.sh'
# `fileB.sh' renamed as `B.sh'
# `fileC.sh' renamed as `C.sh'
rename "s/file//" fileA.sh fileB.sh fileC.sh 
```

特定ワードを含むファイルのみ操作

```bash
ls | grep -v / | grep -e file | rename -v "s/file//"
```

先頭に特定ワードを含むファイルのみ操作

```bash
ls | grep -v / | grep -e "file*" | rename -v "s/file//"
```

特定ワードと、拡張子のファイルを操作

```bash
ls | grep -v / | grep -e "file" --include "*.sh" | rename -v "s/file//"
```

## ファイル名の前後に文字列追加

ファイル名の前に文字を追加

```bash
# `A.sh' renamed as `fileA.sh'
rename "s/^/file/" A.sh
```

拡張子の後に文字を追加

```bash
# `fileA.sh' renamed as `fileA.sh.old'
rename "s/$/.old/" A.sh
```

ファイル名の後に文字列を追加
(```.sh``` が拡張子以外では使われていないときのみ)

```bash
# `A.sh' renamed as `A_file.sh'
rename "s/.sh/_file.sh/" A.sh
```

# 正規表現を用いた置き換え

Ubuntuでは、 ```rename``` コマンドで正規表現も利用できます。
[こちら](http://kurumatorajirou.blogspot.com/2015/05/ubunturename-2.html)のブログ様が詳しかったのでオススメです。

```bash
# すべて小文字にする
rename 'y/A-Z/a-z/' *
```

# 参考

- [【 sed 】コマンド（基礎編その4）――文字列を置き換える／置換した行を出力する](https://www.atmarkit.co.jp/ait/articles/1610/17/news015.html)
- [Linuxで複数のファイル名を一括変更(置換)する](http://iatlex.com/linux/rename)
- [【rename】Linuxでファイル名を一括変更するコマンド](https://uxmilk.jp/8366)
- [Linuxでファイル名の前後に文字を追加したい時の簡単な方法](http://www.nemotos.net/?p=745)
幅優先探索(BFS)と深さ優先探索(DFS)

# 概要
グラフや木の探索に用いられる幅優先探索と深さ優先探索について、Pythonでの実装を用いながら紹介します。

# 幅優先探索 (Breadth First Search: BFS)
![Screen Shot 2019-12-25 at 14.48.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122091/07d766a2-8aca-50b7-306a-44e88e3eb27a.png)
幅優先探索(BFS)はグラフにおける探索方法の一種で、与えられたnodeから近いnodeを順に探索していきます。深さ優先探索(DFS)ではスタックを用いるのに対し、BFSはキューを使って実装することができます。ノード間の最短距離を求めたい時などに使えます（辺の重みの有無、有向/無向等の性質によって実装が変わってくるので注意）。以下にPythonによる実装の一例を示します。

## 実装
```python:BFS
# Make tree as follows:
#     1
#    / \
#   2   3
#  / \ / \
# 4  5 6  7

from collections import deque

class Node:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

node1 = Node(1) # Root node
node2 = Node(2)
node3 = Node(3)
node4 = Node(4)
node5 = Node(5)
node6 = Node(6)
node7 = Node(7)

node1.left = node2
node1.right = node3
node2.left = node4
node2.right = node5
node3.left = node6
node3.right = node7

# キューを作成して初期ノード(root)を入れる
q = deque()
q.append(node1)

# キューが空になるまで繰り返す
while len(q) > 0:
    # キューの先頭（左端）からnodeを取り出す
    node = q.popleft()
    
    if node is not None:
        print(node.val)
        # nodeの子要素をキューの末尾（右端）に入れる
        q.append(node.left)
        q.append(node.right)
```

## 出力結果
```
1
2
3
4
5
6
7
```


# 深さ優先探索 (Depth First Search: DFS)
![Screen Shot 2019-12-25 at 14.48.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122091/76992878-7fc0-9e85-9133-843f8400d17d.png)
深さ優先探索(DFS)はグラフにおける探索方法の一種で、与えられたnodeから可能な限り遠くまで探索していく手法です。幅優先探索(BFS)ではキューを用いるのに対し、DFSはスタックまたは再帰を使って実装することができます。以下にPythonによる実装の一例を示します。

## 実装
```python:DFS
# Make tree as follows:
#     1
#    / \
#   2   5
#  / \ / \
# 3  4 6  7

class Node:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

node1 = Node(1)
node2 = Node(2)
node3 = Node(3)
node4 = Node(4)
node5 = Node(5)
node6 = Node(6)
node7 = Node(7)

node1.left = node2
node1.right = node5
node2.left = node3
node2.right = node4
node5.left = node6
node5.right = node7

def traverse(node):
    if node is not None:
    	print(node.val)
        # 子要素に対して再帰的に呼び出していく
    	traverse(node.left)
    	traverse(node.right)

traverse(node1)
```

## 出力結果
```
1
2
3
4
5
6
7
```

## 補足
上記のように木を探索する手法は先行順巡回 (pre-order)とも呼ばれます。他にも中間順巡回 (in-order)、後行順巡回 (post-order)といった手法があるので、気になる方は調べてみてください。
Singularity pull で、docker のイメージを変換する

# 概要

docker のイメージがあるものを、 Singularity に変換したい

# 結論

Singularity pull で、docker のイメージを変換する。

**root権限はいらない**

```
singularity  pull ファイル名 docker://使いたいdockerイメージ
```

ファイル名は、「新しく作るシンギュラリティイメージのファイル名」

# 参考

sailfishのdockerコンテナをsingularityイメージに変換する

```console
$ sailfish
bash: sailfish: command not found
$ singularity  pull sailfish.0.10.1.sif docker://quay.io/biocontainers/sailfish:0.10.1--h6516f61_3
WARNING: Authentication token file not found : Only pulls of public images will succeed
INFO:    Starting build...
Getting image source signatures
Copying blob sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
 32 B / 32 B [==============================================================] 0s
Copying blob sha256:b0dc45cd432d14fb6df7d3239dc15d09c63906f8e7bfd373a4647b107fc3746c
 2.13 MiB / 2.13 MiB [======================================================] 1s
Copying blob sha256:9466b3513669459396338a74673ede0166f534ab64923f66ecca58176d1ffe5e
 247 B / 247 B [============================================================] 0s
Copying blob sha256:ddd482ea7b54727ff2b6748188290b75f6441ba4091d15a5e62d2a0ed47c81dd
 221 B / 221 B [============================================================] 0s
Copying blob sha256:4d69f833b9d8db2f02cc784f9bab7317317e4062129cafe65660c9eb2cd1c115
 2.49 KiB / 2.49 KiB [======================================================] 0s
Copying blob sha256:e7c454e5167ddab5101c53d104c90c0a037c3ee3930b9a74a14da40c852134cc
 34.41 KiB / 34.41 KiB [====================================================] 0s
Copying blob sha256:e38092b005c08dab4ae80615d29944107dc3d07307e37c4558914998e0e61827
 243.10 KiB / 243.10 KiB [==================================================] 0s
Skipping fetch of repeat blob sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
Skipping fetch of repeat blob sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
Copying blob sha256:f879b42dfe2b253544b0dc6834eff097a2a994cecda76b3c2950465fef9bfdfc
 879.28 KiB / 879.28 KiB [==================================================] 0s
Skipping fetch of repeat blob sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
Copying blob sha256:f27b1200e6ac02b64fb993ae17f708cc4b515e437343c38733f8174c28bbce07
 116.92 MiB / 116.92 MiB [==================================================] 8s
Copying config sha256:1de74eb292217936a929325a39b4774d8b6dab3267ed4afcfbb843e723f4d59f
 2.77 KiB / 2.77 KiB [======================================================] 0s
Writing manifest to image destination
Storing signatures
INFO:    Creating SIF file...
INFO:    Build complete: sailfish.0.10.1.sif
$ ls -l sailfish.0.10.1.sif
-rwxr-xr-x 1 manabu manabu 123822080 Sep 13 11:38 sailfish.0.10.1.sif
$ singularity exec sailfish.0.10.1.sif sailfish --version
version : 0.9.2
$ 
```
gulp環境をコピーした時の記録

すでにあるgulpの環境を
別のPCやディレクトリにも再構築した時の手順をメモします。

gulpのバージョンは
CLI version: 2.2.0
Local version: 4.0.2

#作業手順
1.すでに使用している既存のpackage.json、gulpfile.jsを
　新規プロジェクトディレクトリにコピーします。
2.新規プロジェクトルートディレクトリにて
　npm installを実行(yarn install)

##備考
gulp移行と同時にnpmからyarnに移行する際は
Package-lock.jsonからyarn-lock.jsonと
生成されるファイルが変わるので
.gitignoreなど適宜調整してください。

##注意事項
※.globをインストール（npm i glob）している場合は
以下のプラグインが入っていると思うので
gulp-combine-media-queries/index.jsの
152行目付近の以下の部分をコメントアウトする

```index.js

# file.contents = new Buffer(cssJson);

```

↑これをやらずに実行した時には↓のエラーが出た。
[vagrant@localhost example]$ npx gulp
[08:11:41] Using gulpfile /var/www/html/example.com/wp-content/themes/example/gulpfile.js
[08:11:41] Starting 'default'...
[08:11:41] Starting 'sass2'...
[08:11:42] File sass/ampstyle.css found.
[08:11:42] 'sass2' errored after 103 ms
[08:11:42] TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type object
    at Function.from (buffer.js:225:9)
    at new Buffer (buffer.js:175:17)
    at Transform.transform [as _transform] (/var/www/html/example.com/wp-content/themes/example/node_modules/gulp-combine-media-queries/index.js:152:21)
    at Transform._read (/var/www/html/example.com/wp-content/themes/example/node_modules/gulp-combine-media-queries/node_modules/readable-stream/lib/_stream_transform.js:184:10)
    at Transform._write (/var/www/html/example.com/wp-content/themes/example/node_modules/gulp-combine-media-queries/node_modules/readable-stream/lib/_stream_transform.js:172:12)
    at doWrite (/var/www/html/example.com/wp-content/themes/example/node_modules/gulp-combine-media-queries/node_modules/readable-stream/lib/_stream_writable.js:237:10)
    at writeOrBuffer (/var/www/html/example.com/wp-content/themes/example/node_modules/gulp-combine-media-queries/node_modules/readable-stream/lib/_stream_writable.js:227:5)
    at Transform.Writable.write (/var/www/html/example.com/wp-content/themes/example/node_modules/gulp-combine-media-queries/node_modules/readable-stream/lib/_stream_writable.js:194:11)
    at DestroyableTransform.ondata (/var/www/html/example.com/wp-content/themes/example/node_modules/readable-stream/lib/_stream_readable.js:619:20)
    at DestroyableTransform.emit (events.js:182:13)
[08:11:42] 'default' errored after 106 ms
初投稿に関しまして

#はじめ

Qittaは読むことが基本で、投稿は初めてだったので少し緊張いたしました。先日投稿したものは以下にリンクを載せておきます。
[論文メモ](https://qiita.com/kaco/items/f186af6abad626ce0374)

#感想

投稿から半日のviewは2と言うことで、こんなもんだろうと思い寝ました。
次の日、最終的にviewは6000になっていました。パニックですw
話は簡単です。某SNSで私の記事を取り上げて頂いたらしくこんなことになっているみたいでした。

少し思ったのはフォロワー0でなんの影響もない記事をこの方達はどのようにして見つけてきたのだろうか？
情報網が国家レベルですか？と思いました。

ただただ、凄いなと思います。この方達はいたるところに情報網があって。それならいろいろな知識が身につきますし、先に先に考えることができるでしょうね。
また、影響力も大きく、色々意見を普段発信していない人たちからも引っ張り出せることができるので議論していて楽しい人たちだと思いました。

#一言

皆様のように多くの人たちにAIをわかっていただけるように頑張ります。
Flutterよくある質問

よくある質問をメモしておきます。

## デザイン関連

### アイコンを探す
https://material.io/resources/icons/

### Flutter Studio
https://flutterstudio.app/

## アプリ関連

### アプリアイコンを生成する

パッケージとアイコンパスを追加。

```dart
dependencies:
  flutter_launcher_icons: any

flutter_icons:
  image_path: "assets/icons/ic_launcher.png" 
  android: true
  ios: true
```

アイコンを作成し、assets/icons/ic_launcher.pngに置きます。

* [アイコン作成サイト](https://romannurik.github.io/AndroidAssetStudio/icons-launcher.html#foreground.type=clipart&foreground.clipart=android&foreground.space.trim=1&foreground.space.pad=0.25&foreColor=rgba(96%2C%20125%2C%20139%2C%200)&backColor=rgb(68%2C%20138%2C%20255)&crop=0&backgroundShape=square&effects=none&name=ic_launcher) - これで作成した場合は、res/mipmap-xxxhdpiにあるファイルを使います
* [フリーアイコンサイト](https://iconstore.co/)

コマンドを実行。

```dart
flutter packages pub run flutter_launcher_icons:main
```

### ビルド＆インストールする

apkは、build/app/outputs/apk/release/app-release.apk にできます。

```dart
flutter build apk
flutter install
```

### スクリーンショットを撮る

```dart
flutter screenshot
```

### バージョンを更新する

コマンドでlocal.propertiesの情報を更新します。
build-numberが同じだと、同じバージョンとみなします。
build-nameは表示用です。

```dart
flutter build apk --build-name=1.0.1 --build-number=2
```


### Android StudioでSHA 証明書フィンガープリントを得る

https://stackoverflow.com/questions/51845559/generate-sha-1-for-flutter-app

> GradleのWindowが空だったらFile>Sync Project with Gradle Filesを実行

## Dart関連

### シングルトンにする

```dart
class ThisIsSingleton {
  static final ThisIsSingleton _instance = ThisIsSingleton ._internal();

  ThisIsSingleton ._internal();

  factory ThisIsSingleton () {
    return _instance;
  }
}
```

## Flutterインストール

1. [flutter](https://flutter.dev/docs/get-started/install)をダウンロードして、zipを展開。展開後のflutter/binをPATHに設定。
2. [Android Studio](https://developer.android.com/studio/?hl=ja)をインストール。File>Settings>PluginからFlutterをインストール。
3. flutter doctorでチェック。
laravelでbase64でエンコードされたpng画像を表示する

1x1の透明pngを表示するサンプル。
`return response(base64_decode("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQI12NgYAAAAAMAASDVlMcAAAAASUVORK5CYII="))->header('Content-type','image/png');`
【Macアプリ】Yoink

MacBookなどで、ブログや資料を作成するときに便利なアプリ。

[Yoink](https://apps.apple.com/jp/app/yoink-%E3%83%89%E3%83%A9%E3%83%83%E3%82%B0-%E3%83%89%E3%83%AD%E3%83%83%E3%83%97%E3%82%92%E5%BF%AB%E9%81%A9%E3%81%AA%E3%82%82%E3%81%AE%E3%81%AB/id457622435?mt=12)
<img width="962" alt="ScreenShot.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33479/6eb17054-3985-c0d2-49b6-379e6957b4d7.png">


このアプリを使うと

- ファイル（画像、書類など）やフォルダ、テキストのコピー、URLなどを一時的に格納しておける
- 一時的に保存ができるので、端末内に無駄にファイルを保存とかをしなくて済む
- ドラッグ＆ドロップでという簡単な操作で済む

ということができて、とても便利。
有料のアプリだけど、作業効率とかを考えれば、全然元が取れる。

サブスクリプションでなく、買い切りなのもいい。

起動すると、画面の端に表示される。
<img width="622" alt="ScreenShot.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33479/8df1fd60-554d-b97a-a181-eeaf28d70bf8.png">

参考までに、チュートリアル画面。
<img width="694" alt="ScreenShot 16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33479/60124eec-42b5-7c04-2a9e-910a0c81025e.png">
<img width="694" alt="ScreenShot 17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33479/220fbbca-92ee-5abb-0e32-3f01e37c67d5.png">
<img width="694" alt="ScreenShot 18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33479/5f2e4e30-27d7-a39e-0b77-59c39802bea0.png">
<img width="694" alt="ScreenShot 19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33479/8769a6e1-421e-314e-c8ce-f4c7919f3854.png">
<img width="694" alt="ScreenShot 20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33479/830e7d61-f630-d45c-6f0b-29ed4dc918cc.png">
<img width="695" alt="ScreenShot 21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33479/8413f0b5-e047-b590-93bb-2074797fb494.png">
<img width="695" alt="ScreenShot 22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33479/592ae8c3-e9fe-b61d-fa6a-b152fa300d97.png">
<img width="695" alt="ScreenShot 23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33479/3ccb9130-948c-c4e9-b8cc-84ec4fcebad2.png">
特定のdocker networkに依存するコンテナ名を列挙するワンライナー

起動中のコンテナだけ分かれば十分なのであれば、 以下でOK

```
docker network inspect $network_name | jq -r '.[].Containers[].Name'
```

停止しているコンテナも含めて列挙したい場合は

```
docker container inspect -f "{{.Name}} {{.NetworkSettings.Networks}}" $(docker ps -aq) | grep $network_name | sed -r 's/^\/(\S+) .*$/\1/'
```
インターネットの基礎を調べた

# 経緯
Web会社に中途で入社したが、基本的な知識が足りていないと指摘された。
基礎の基礎から勉強していく。

# そもそもインターネットとは

コンピューターどうしを無線,有線でつなぎ、情報を交換できるようにする仕組みのこと
<img width="633" alt="スクリーンショット 2019-09-13 14.17.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496792/32300491-5dc4-0a58-2825-45e8b7125374.png">

https://saruwakakun.com/it/web/www

## Webとは
文書、画像、動画、音楽などを公開したり、閲覧したりできるシステムのこと。

## webブラウザとは
サーバからのレスポンス(HTMLやCSS）を解析して可視化するためのアプリ

## IPアドレスとは
パソコンやスマホに一意についている番号のこと。インターネットの情報を行き来するために使用される住所のようなもの。

## グローバルIPアドレスとは
インターネットに接続する際に利用されるIPアドレスで、PC等一意についている番号

## プライベートIPアドレスとは
ルーターがwebサーバからのレスポンスをそれぞれのPCに返す際に使用されるIPアドレス

## ドメイン名とは
URLに含まれるIPアドレスの別名。IPアドレスのままだと人間にわかりにくいので

## ポート番号とは
webサービスや、メールサービスのようにコンピュータには様々なサービスがある。IPアドレスだけだと、送り先のPCは指定できるが、PCが提供するサービスまでは指定できない。指定するために使用されるのがポート番号
webは80番

## サーバとは
ネットワーク場でサービスや情報を提供する側のPC

## クライアントとは
ネットワーク場でサービスや情報を利用する側のPC

# プロトコルとは
ネットワークを介して情報をやりとりする際用いられる通信の約束事

## TCP/IPとは
インターネットでPCどうしが通信を行うために標準化されたプロトコル
TCP/IPには種類がある
https://www.pc-master.jp/internet/tcp-ip-protocol.html

## httpとは
webブラウザとwebサーバの間でwebコンテンツをやりとりする際使用されるプロトコル

## httpsとは
SSLプロトコルのこと。通信内容を暗号化してくれる。盗聴、改ざん、なりすましを防ぐ。
ホームページの所有者の正当性を確認できる。
httpsの方がSEOでも有利になる。
https://cybersecurity-jp.com/security-measures/25772

SSLサーバ証明書
<img width="437" alt="スクリーンショット 2019-09-13 11.29.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496792/84bc90c8-0537-05d8-55a6-60a841d76692.png">



## なぜ暗号化されていない通信(http）は危険なのか
ネットワーク内に流れるパケットパケットを確認するとformなどで入力した情報がみれてしまうから。
https://saitodev.co/article/%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%8D%E3%83%83%E3%83%88%E5%86%85%E3%81%AB%E6%B5%81%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%83%91%E3%82%B1%E3%83%83%E3%83%88%E3%82%92%E5%82%8D%E5%8F%97%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B
#Rails | rails new してから sidekiq + redis を起動してジョブを動かすまでの最小手順

# Rails new

```
rails new your-project
cd your-project
```

# Gemfile

```diff
+ gem 'sidekiq'
+ gem 'redis'
```

```
bundle install
```

# Job

```
bundle exec rails generate job sample
```

```
vim app/jobs/sample_job.rb
```

```diff
class SampleJob < ApplicationJob
  queue_as :default

  def perform(*args)
+    puts 'Worked!'
+    puts Time.current
  end
end
```

# Config

```
vim config/application.rb
```

```diff
require_relative 'boot'

require 'rails/all'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module RailsNewSidekiq
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 6.0

+    config.active_job.queue_adapter = :sidekiq

    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration can go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded after loading
    # the framework and any gems in your application.
  end
end
```

# Redis

```
brew install redis (Mac)
redis-server
```

![image](https://user-images.githubusercontent.com/13635059/64828465-92f0a080-d603-11e9-8db6-2d24b39f7017.png)



# Worker

```
bundle exec sidekiq
```

![image](https://user-images.githubusercontent.com/13635059/64828575-085c7100-d604-11e9-86c0-31f814cf8b86.png)

# Run

```
bundle exec rails runner 'SampleJob.perform_later'
```

result in worker

```
2019-09-12T23:40:33.677Z pid=29375 tid=owiiogm93 class=SampleJob jid=0c56247c9f77a055dd35e78b INFO: start
Worked!
2019-09-12 23:40:33 UTC
2019-09-12T23:40:33.692Z pid=29375 tid=owiiogm93 class=SampleJob jid=0c56247c9f77a055dd35e78b elapsed=0.015 INFO: done
```

![image](https://user-images.githubusercontent.com/13635059/64828672-6ab57180-d604-11e9-8a91-f36b9b057733.png)


# ref

https://github.com/YumaInaura/rails-new-sidekiq

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2424








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
nuxtのheadプロパティとheadメソッドについて

nuxt.js全く勉強してないが、ちょっと触ることがあって、
Object型で書いてたりfunction型で書いてたりされている違いが気になったのでメモ。

#headプロパティ
nuxt.config.js内でアプリケーションのメタ情報を定義する時に使う。
型はObject。

#headメソッド
ページのコンポーネントでメタ情報を定義する時に使う。
型はObjectまたはfunction。どっちで書いても動いた。
コンポーネントのデータをheadメソッド内でthisを使って利用することができる。

#結論
nuxt.config.jsでheadプロパティを使うときはObject型のみ。
ページのコンポーネントでheadメソッドを使うときはObject型でもfunction型でもどちらでも良い。
Object型とfunction型で挙動の違いがあるかどうかはまだわからないので追い追い調べる。

#参考
- [API: head プロパティ - Nuxt.js](https://ja.nuxtjs.org/api/configuration-head/ )
- [API: head メソッド - Nuxt.js](https://ja.nuxtjs.org/api/pages-head)
【PBCS】FDMEE機能 - ⑦ロケーション～⑨マッピング定義

前記事はこちら
[【PBCS】FDMEE機能 - ④ソース・システム～⑥インポート・フォーマット](https://qiita.com/iwa_gino/items/ed0746fc58538e79a909)

# ⑦ロケーション

・[データ管理]＞[設定]＞[ロケーション]
・データの取込単位を定義

---

・ロケーションを **⑥インポート・フォーマットの個数分** 作り、⑥⑦を紐づける

【名前】任意ロケーション名（例：LOC_[インポート・フォーマット名]　等）
【インポート・フォーマット】⑥を指定
【機能通貨】[NONE]
【確認エンティティグループ】[NONE]
【ロジック勘定科目グループ】[NONE]
【確認ルールグループ】[NONE]

# ⑧データ・ロード・ルール

・[データ管理]＞[ワークフロー]＞[データ・ロード・ルール]
・テキストファイルとのデータ連携の際に実行するルールを定義

---

・データ・ロード・ルールを **⑥インポート・フォーマットの個数分** 作り、⑥⑦⑧を紐づける
　 **※必ず画面下から紐づけるロケーションを選択してから登録すること** 
　
【名前】任意のデータ・ロード・ルール名（例：DLR_[インポート・フォーマット名]　等）
【カテゴリ】③で設定したカテゴリから選択
【ターゲットプランタイプ】Plan1（BSO）
【インポート・フォーマット】⑥を指定

# ⑨マッピング定義

・[データ管理]＞[ワークフロー]＞[データ・ロード・マッピング]
・ソース・システムからターゲット・システムへデータを連携する際のマッピングを定義

---

【種類】1. **明示** ：ソース値との **完全一致** がターゲット値に置き換えられる
　　　　2. **範囲** ：ソース値の **範囲** が1つのターゲット値に置き換えられる
　　　　3. **含む** ：非シーケンシャルなソース値のリストを1つのターゲット値にマッピングできる
　　　　　　　　→別途用意したcsvのリストから、ソース値とターゲット値を読み込ませたい場合に使用
　　　　4. **マルチ・ディメンション** ：複数のソース列値に基づいてメンバー・マッピングを定義できる
　　　　5. **類似** ：ソース値内の文字列との一致がターゲット値に置き換えられる

【ソース値】取込元の値
【ターゲット値】取込先のメンバー
【符号の変更】Accountのみ
【ルール名】「明示」を除くものすべてに設定
　※「DATA」には基本何も設定しなくてよい

＜例＞ソース・ファイルのAccountの値：12345
　　　取込先（PBCS）Accountの値：AC12345　に変換する場合

　　　【タイプ】類似
　　　【ソース値】*
　　　【ターゲット値】AC*
　　　【ルール名】Rule01　※任意の名称でOK　


# 設定後のFDMEE実行方法

①「 **データ・ロード・ルール** 」を押下
②画面下から実行するロケーションとカテゴリを選択
③「 **ソース・オプション** 」にて取込csvファイルの名前を選択する
④「実行」を押下
　　・「ソースからインポート」「ターゲットにエクスポート」にチェックを入れることで
　　　　 **インポートからエクスポートまで1回で実行** する

※エクスポート・モード＝「データの保管」で、データのマージが可能
→ **同じ次元交差の行をcsv内で複数持った場合、合算金額として取り込むことができる**
【PBCS】FDMEE機能 - ④ソース・システム～⑥インポート・フォーマット

前記事はこちら
[【PBCS】FDMEE機能 - ①プロファイル設定～③カテゴリ・マッピング](https://qiita.com/iwa_gino/items/62cb900843aafb6a788f)

# ④ソース・システム

・[データ管理]＞[設定]＞[ソース・システム]
・データ連携元となるシステムの情報を定義します。

---

【ソース・システム名】File ※固定
【ソース・システム・タイプ】File　※csv取込の場合

# ⑤ターゲット・アプリケーション

・[データ管理]＞[設定]＞[ターゲット・アプリケーション]

・データ連携先となるアプリケーションの情報を定義します。
　※Years次元のターゲット・ディメンション・クラスを「Years」にとすると
　　エラーとなり登録できないので注意　→「 **Year** 」にしておく

---

## ターゲット・アプリケーションのサマリー

１．「追加」から、取込先を指定 →「ローカル」を選択
２．  Planning、[アプリケーション名]を選択（※PBCSの場合）
３．「 **メタ・データのリフレッシュ** 」と「 **メンバーのリフレッシュ** 」を押下
　　　⇒アプリケーション詳細が自動生成される
４．「保存」を押下
　
## アプリケーション詳細

【名前】[アプリケーション名]
【タイプ】Planning　※固定
【デプロイメント・モード】クラシック　※固定
【ディメンション名】アプリケーションの次元
【ターゲット・ディメンションクラス】
【データ表列名】ステージング表の項目名
【シーケンス】マッピングの順序

※カスタム・ターゲットアプリケーションを作成する際に編集
　基本、初期生成されたままでＯＫ

# ⑥インポート・フォーマット

・[データ管理]＞[設定]＞[インポート・フォーマット]
・ソースデータのレイアウトを定義

---

## インポート・フォーマットのサマリー

※取込元csvがカンマ区切りの場合
【名前】IF_[カテゴリ名]　等
【ソース】File
【ターゲット】[アプリケーション名]
【ファイル・タイプ】
　　 **[2018/12/10追記]** 
　　①数値データのみを取り込む場合
　　　区切り - 数値データ　⇒マッピングターゲットに「 **Amount** 」がある事を確認
　　②数値データおよびテキストデータを取り込む場合
　　　区切り - すべてのデータ型　⇒マッピングターゲットに「 **Data** 」がある事を確認
【ファイル区切り文字】カンマ
「保存」押下で登録→[次元マッピング]へ　※１個ずつ作らないとエラーが出て保存できないので注意！
　
## 次元マッピング
【ソース列】取込元ファイルの列名
【フィールド番号】取込元ファイルの列番号
【ターゲット】アプリケーションの次元名
　→サマリー登録後に表示される次元のみでOK
　→実際の取込元にはない次元のフィールド番号は任意の番号でＯＫ（デフォルトは1）
Sign in with Apple のガイドライン

2019年9月12日、Sign in with Apple に関するガイドラインが追加されました。ので訳しておきたいと思います（訳が変なところあったら編集リクエストお願いします）。

# 要約

* 新規アプリは今日からこのガイドラインを守ろう
* 既存アプリは2020年4月までにこのガイドラインを守ろう
* 自社独自の認証システムのみ使っている場合は対応しなくてもOK
* ガイドラインを守って Sign in with Apple のボタンを使ってね

# Sign in with Apple に関する News and Updates

[News and Updates](https://developer.apple.com/news/?id=09122019b) より

すでに発行済の Apple ID を使って、ユーザがアプリやウェブサイトに簡単にサインインできるようになります。Sign in with Apple はプライバシーやセキュリティに関する機能が備わっており、アカウントを作成したりサインインしたりするにも、アプリを素早く簡単に操作してもらうにも、優れた方法だと言えます。すべてのアカウントは優れたセキュリティにより2段階認証で保護されており、Apple と言えどもアプリやウェブサイト上でのユーザの行動を追跡することはありません。

Sign in with Apple を使う必要がある場合の基準を App Store Review Guidelines で公開しています。今日から App Store に新規アプリを提出する場合はこのガイドラインに従う必要があります。既存アプリは2020年4月までに従う必要があります。また、ウェブサイトや他のプラットフォームで Sign in with Apple を使う場合のガイドラインも公開しています。

# Sign in with Apple 部分の iOS レビューガイドライン

[4.8 Sign in with Apple](https://developer.apple.com/app-store/review/guidelines/#sign-in-with-apple) より

サードパーティのログインサービス、もしくは ソーシャルログインサービス（ Facebook ログイン、Goole サインイン、Twitter サインイン、Linked-In サインイン、Amazon ログイン、WeChat ログインなど）のみを使ってユーザの設定、プライマリアカウントの認証を行うアプリは、Sign in with Apple も提供しなくてはなりません。プライマリアカウントとは自分自身を識別したり、サインインしたり、ある機能や関連サービスにアクセスするためにアプリ内で開設するアカウントのことを指します。

以下の場合、Sign in with Apple は必要ありません。

* 自社独自のサインアップ、サインインシステムのみを使用している場合
* すでに存在する教育、エンタープライズアカウントでサインインする必要がある、教育、エンタープライズ、ビジネスアプリの場合
* 認証手段として、政府、業界が支援する国民認証システムや電子 ID を使うアプリの場合
* サードパーティサービスのクライアントであり、コンテンツにアクセスするには直接メール、ソーシャルメディア、他のサードパーティアカウントにサインインする必要があるアプリの場合

# 他のプラットフォームやウェブサイトでのガイドライン

[Usage Guidelines for Websites and Other Platforms](https://developer.apple.com/sign-in-with-apple/usage-guidelines-for-websites-and-other-platforms/) より

Sign in with Apple は iOS、macOS、tvOS、watchOS で使うことができます。加えてどのブラウザでも動作可能であり、ウェブサイトやアプリにおいても統合的に扱うことができます。ユーザはアクセスするサービスに関わらず、アカウント作成やサインインを簡単に行うことができるようになります。ウェブサイトやアプリを計画、開発する時は、これらのガイドラインを念頭に置いてください。

## Sign in with Apple JS

もし App Store であなたのアプリが Sign in with Apple を有効にしているなら、関連する他のウェブサイトやアプリで Sign in with Apple JS（システムが提供する JavaScript の API）を提供することをおすすめします。この API を使用するには、App Store にアプリが存在する必要があります。

-> [Learn more in Developer Account Help](https://help.apple.com/developer-account/#/devde676e696)

## デザイン

ウェブサイトやアプリもアカウント作成、サインイン体験に関するデザインガイドラインに従う必要があります。また、[Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/sign-in-with-apple/overview/) に記載されている Sign in with Apple のボタンを使う必要があります。

## 禁止されているユースケース

以下のサービスの場合、Sign in with Apple をウェブサイトやアプリに組み込むことはできません。

* 法律に違反している、または法的要件を順守していない
* 以下に関連するサービスや取引
  * タバコやタバコ製品
  * 銃器、武器、弾薬
  * 違法薬物や、非合法的と定められている規制物質
  * 消費者の安全を脅かすアイテム
  * 違法な活動に使用されることを意図したアイテム
  * ポルノ
  * 偽造品や盗難品
* 主に麻薬や性的指向が絡むアイテムやサービスを提供
* 人種、年齢、性別、性同一性、民族、宗教、性的指向をもとに憎悪、暴力、不寛容さを助長
* あらゆる種類の詐欺に関与
* 他者の知的財産、パブリシティ、プライバシーを侵害
* Apple やその他の製品を模造して見せたり、軽蔑的に見せる

また、ユーザが自発的にアカウントを発行したりサインインしたりする以外の目的で、アプリやサービスに Sign in with Apple の API を使うことはできません。

Apple はいつでも理由の如何を問わず、ウェブサイトやアプリの Sign in with Apple を無効にする権利を有しています。
【PBCS】FDMEE機能 - ①プロファイル設定～③カテゴリ・マッピング

前記事はこちら
[【PBCS】FDMEE機能 - 機能概要](https://qiita.com/iwa_gino/items/1909597e546b87c19d65)

# ①プロファイル設定

・ナビゲーター＞統合＞データ管理＞設定＞ **システム設定** より設定

## ファイル設定（プロファイル・タイプ：ファイル）
【ロケーション・フォルダの作成】アプリケーションのルートフォルダを設定 → 空白
【アーカイブ・モード】Inboxフォルダ内にロケーション毎のフォルダを作成するか設定 → Copy
【ファイル・アップロードのワイルド・カードを除外】アップロードできないファイル拡張子を指定する→空白
【バッチ・サイズ】メモリーに一度に読み込まれる行数を指定する → 1000
【ファイルの文字セット】テキストを作成、保管および表示する際の文字コードを指定する → UTF-8
　
## POV設定（プロファイル・タイプ：POV）
【デフォルトPOVロケーション】デフォルトPOVの場所を選択 → 空白
【デフォルトPOV期間】デフォルトPOV期間を選択 → 空白
【デフォルトPOVカテゴリ】デフォルトPOVカテゴリを選択 → 空白
【グローバルPOVモード】POVをロックするかを選択 → 空白
　
## ODI設定（プロファイル・タイプ：ODI）
　※設定項目なし
　
## その他設定（プロファイル・タイプ：その他）
【デフォルトの確認レポート】デフォルトの確認レポートとして利用する確認レポートのタイプを指定 → Check Report
【バッチ・タイムアウト(分)】ジョブの最大実行時間を指定する。 → 空白
【ログ・レベル】ログに表示される詳細レベルを指定する。（１(要約)～5(詳細)の間で指定） → 4
【レポート精度の確認】2
【データ・エクスポート・オプション「すべてのデータを上書き」の表示】いいえ
【マップ監査を使用可能にする】いいえ
【アクセスしてソース・ドキュメントを開く】All Users
【マップ・エクスポート・デリミタ】,
【マップ・エクスポートのExcelファイル形式】Excel 97-2003 Workbook (*.xls)
　
---

・ナビゲーター＞統合＞データ管理＞設定＞ **アプリケーション設定** より設定

## アプリケーション設定 (ターゲット・アプリケーション：[アプリケーション名])
【ファイルの文字セット】空白
【デフォルトPOVロケーション】空白
【デフォルトPOV期間】空白
【デフォルトPOVカテゴリ】空白
【グローバルPOVモード】空白
【デフォルトの確認レポート】空白
【ログ・レベル】空白
【レポート精度の確認】空白
【データ・エクスポート・オプション「すべてのデータを上書き」の表示】空白
【マップ監査を使用可能にする】空白
【アクセスしてソース・ドキュメントを開く】空白


# ②期間マッピング

・[データ管理]＞[設定]＞[期間マッピング]

グローバル・マッピング：データ連携で利用される期間の情報を定義
アプリケーション・マッピング：マッピング内容がアプリケーション固有の設定の場合に使用
　　　　　　　　　　　　　　　アプリケーションごとに固有の設定を定義
ソース・マッピング：ソース・システムからデータを取得する場合に利用される期間を定義

※全取込処理に共通する場合はグローバル・マッピングで良い

---

【期間キー】対象月の月末
【前期間キー】対象月の前月末
【期間名】ファイル名に付与する期間名
【期間】PBCSのPeriod次元のメンバー名
【ターゲット期間の四半期】空白
【ターゲット期間の年】空白
【ターゲット期間の日】空白
【ターゲット年度】PBCSのYears次元のメンバー名


# ③カテゴリ・マッピング

・[データ管理]＞[設定]＞[カテゴリ・マッピング]

グローバル・マッピング：データ連携で利用されるカテゴリ(Scenario)の情報を定義
アプリケーション・マッピング：マッピング内容がアプリケーション固有の設定の場合に使用
　　　　　　　　　　　　　　　アプリケーションごとに固有の設定を定義

※全取込処理に共通する場合はグローバル・マッピングで良い

---

【カテゴリ】ファイル名に付与するカテゴリ
【ターゲット・カテゴリ】PBCSのScenario次元のメンバー名
【SCSS】レスポンシブデザインを作成する時のおすすめコーディング方法

# レスポンシブデザインのコーディングはPCとSPデザインが混ざる
なにはともあれまずは、どちらが`直感的に読めるか`、２つのソースコードを20秒ほどで眺めて欲しい
※ 両方とも完成するデザインは同じものになる。

## PCのスタイルをSPで上書きするSCSS設計で作るとこの様になる。

```scss
.company-pc-cta {
  @include mobile {
    display: none;
  }
}

.company-sp-cta {
  display: none;

  @include mobile {
    display: block;
    width: 100%;
  }
}
```

## PCとSPのスタイルは別で書いた方がスッキリする
```scss
.company-pc-cta {
  width: 100%;

  @include mobile {
    display: none;
  }
}

.company-sp-cta {
  width: 100%;

  @include desktop {
    display: none;
  }
}
```




※ include mobile or desktop でメディアクエリが利用できる状態です

やっていることはシンプル

* PCの時だけ表示する画像
* SPの時だけ表示する画像

その２つをメディアクエリで出し分けているだけ。

## レスポンシブデザインのコーディング時は上書きしない方が良い
PCとSP、タブレットなど、複数のデバイスが出るほど
上書きがより複雑になってしまう。

共通の部分のみ通常のセレクタ部分に記述し
デバイスサイズごとに異なるスタイルを当てる場合は
全て分けて書いておいた方が後々保守性が高くなるだろう。


一旦Laravelチームではこの方針でコードを書くことにした。
【PBCS】FDMEE機能 - 機能概要

# FDMEE

・ **Oracle Hyperion Financial Data Quality Management, Enterprise Edition** の略称
・Enterprise Resource Planning (ERP)システムをOracleのHyperion EPMアプリケーションと統合するための主要アプリケーション

■機能概要
https://docs.oracle.com/cd/E64585_01/AGFDE/epm_integrator_architecture.htm

## 仕組み・特徴

[ソース（取込元）]→インポート→[FDMEEステージング表]→エクスポート→[ターゲットシステム(Essbase)]

・csv、またはtxtからデータを取り込める
・Service AdministratorまたはPower Userまたは「統合の実行」が
　プロビジョニングされたユーザが使用可能
・ロード方法には
　「 **追加** （既にデータがある場合に値を合算する）」
　「 **置換** （既にデータがある場合に値を上書きする）」などがある
・ **EPMAutomate** からの実行により、データの自動取り込みが可能
　→その場合、ファイル名に応じて、取込方法、取込先の期間、取込先のシナリオ等が決定されるため
　　予め命名規則を設ける必要がある
　　
 　　【取込ファイルの命名規則例】売上実績データの取込
　　　ファイルID_ロケーション(A)_カテゴリ(B)_期間(C)_ロード方法.txt
　　　ID1010_LOC_Sales_Actual_201704_DLR_Sales.txt
　　　
　　　※(A)ロケーション
　　　　(B)カテゴリ・マッピング
　　　　(C)期間マッピング　　でそれぞれ設定

・エクスポート・モードを「 **データの保管** 」にすることで、 **データのマージが可能** 
　→同じ次元交差の行をcsv内で複数持った場合、 **合算金額として取り込む** ことができる

## FDMEEで出てくる特殊用語

・ロケーション：ひとつのFDMEE設定の定義名
・カテゴリ： **Scenario次元** のこと
・インポート：ソース（取込元）からステージング表にデータを取り込むこと
・エクスポート：ステージング表から取込先（Essbase）にデータを送ること

## 設定が必要な箇所は以下の通り

・ナビゲーター＞統合＞データ管理より設定

①プロファイル設定（システム設定、アプリケーション設定）
②期間マッピング
③カテゴリ・マッピング
④ソース・システム
⑤ターゲット・アプリケーション
⑥インポート・フォーマット
⑦ロケーション
⑧データ・ロード・ルール
⑨マッピング定義（データロード・マッピング）