OmniAICreator/Qiita-1.07M huggingface dataset:
【Rails6】RSpecによるダイアログ表示機能の結合テストの実装

#はじめに
サービスの品質を保つために必要不可欠なテストを実施しております。

今回はダイアログ表示機能の結合テストを実装し、その実装内容を記事にしていきたいと思います。

#前提
・ダイアログ表示機能は実装済み
　ダイアログ表示機能の実装方法や詳細について、以下URLよりご覧になれます。

https://qiita.com/narimiya/items/d4d7cbcfb3d01d8da49c

・投稿時の結合テストと同じ、テストファイルにダイアログ表示機能の内容も記述しています。
　投稿時におけるテストコードの記述は以下のURLよりご覧になれます。

https://qiita.com/narimiya/items/45a4561349f1039a9a65

#バージョン
rubyのバージョン　ruby-2.6.5
Railsのバージョン Rails:6.0.0
rspec-rails 4.0.0

#ダイアログ表示について
JavaScriptなしで、HTMLとCSSのみを使用してダイアログ表示を行います。

![ダイアログ機能.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1052793/95718714-a4ec-6db9-da24-d95f7bd41eee.gif)

動画のようにボタンをクリックすると、ダイアログが表示されます。
読んで欲しい文章を表示させることができます。

※ダイアログとは「ダイアログボックス」のことをいいます。何かを入力させたりメッセージを確認させるために、操作の過程で一時的に開かれる小さい画面のことです。

```index.html
 <dialog id="dialog" class="dialog_style" >
                        「ダイアログの中身の文章（任意）」
 　 <button class="form__btn" onclick="document.getElementById('dialog').close();">
                       「ダイアログの中身にあるボタンの文章（任意）」
   </button>
 </dialog>
 
<button class="form__btn" onclick="document.getElementById('dialog').show();">
                    「クリックするとダイアログが表示されるボタンの文章（任意）」
                    </button>
```

#実施したテスト
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1052793/6f3c5b5f-a717-9fc7-8a00-4d065ef558e0.png)

#テストコードの内容
###投稿時の結合テスト

```spec/system/definitions_spec.rb
require 'rails_helper'

# 〜省略〜

RSpec.describe 'ダイアログ表示について', type: :system do
    context 'ダイアログ表示ができるとき' do
        it 'ダイアログボタンをクリックするとダイアログ表示ができる' do
        #トップページへ移動する
        visit root_path
        
        # トップページにダイアログボタンが存在することを確認する
        expect(page).to have_css(".form__btn")

        # ダイアログボタンをクリックする
        expect{ find_link('1 「相談」の仕方について', ".form__btn").click }

        # ダイアログの内容が表示されていることを確認する
        expect(page).to have_content('相談')

        # ダイアログボタンをクリックする
        expect{ find_link('2 「回答」の仕方について', ".form__btn").click }

        # ダイアログの内容が表示されていることを確認する
        expect(page).to have_content('回答')

        # ダイアログボタンをクリックする
        expect{ find_link('3 「いいね」の仕方について', ".form__btn").click }

        # ダイアログの内容が表示されていることを確認する
        expect(page).to have_content('いいね')
     end
  end
end
```

以上です。
vue.js css heartアニメーション

vue.jsでハートアニメーションをしたい。

https://qiita.com/ma7ma7pipipi/items/29e916809810df059ecb

でもやってみたが、なんかコッテリするのでもっとシンプルにした。

参考
https://yuyauver98.me/twitter-like-animation/#_fontawesomecss

```app.scss

.LikesIcon-fa-heart{
    font-size: 30px;
    cursor: pointer;
}
.LikesIcon-fa-heart.heart{
    /* heartAnimationアニメーションを200ミリ秒かけて実行する */
    animation: heartAnimation .2s;
    /* アイコン色を黒から赤へ変更する */
    color: #e2264d;
}

```

```hoge.vue

<div class="LikesIcon" @click.stop="toggleHeart(100)">
    <i class="far fa-heart LikesIcon-fa-heart" :class="{ heart: isActive }"></i>
</div>


<script>

//中略
        data () {
            return {
                isActive:false,

//中略

        methods: {
            
            toggleHeart(id){
                if(!this.isActive){
                    this.isActive = true;
                } else {
                    this.isActive = false;
                }
            },

</script>

```

これでコピペで動きます。

# 塗りつぶしたい場合

```hoge.vue


<i class="fa-heart LikesIcon-fa-heart" :class="{ heart: isActive , fas: isActive ,far: !isActive }"></i>


```
【Kotlin 初学者】画面遷移時で値を渡す方法

## 画面遷移時に値を渡す方法
EditTextなどで入力した値を別画面に渡したいなど頻繁に使われる実装になります
本当はViewBindingでid取得したかったんですが、それはまた別記事に書きますので、まずはfindViewByIdでxmlのidを取得してください🙇‍♂️

## イメージサンプル
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320838/c13fc913-6ae8-d8ab-e8cd-91c25a527801.gif" width="300" height="100%">

## 実際のコードになります
画面遷移先をNextActivityにします
EditTextで値を入力し、Intentで画面遷移時にNextActivityで値を受け取り、
TextViewに代入してます

```MainActivity.kt
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var editText = findViewById<EditText>(R.id.edit_text)
        var inputText = editText.editableText

        val nextButton = findViewById<Button>(R.id.next_button)

        nextButton.setOnClickListener {
            if(editText.text != null){
                val intent = Intent(this, NextActivity::class.java)
                intent.putExtra("INPUT_TEXT",inputText.toString())
                startActivity(intent)
            }
        }
    }
}
```

```activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/edit_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="ここに値を入力する"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

    <Button
        android:id="@+id/next_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="クリック"
        app:layout_constraintTop_toBottomOf="@+id/edit_text"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
```

```NextActivity.kt
class NextActivity : AppCompatActivity(){

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_next)

        var getText = findViewById<TextView>(R.id.get_text)
        val intentText = intent.getStringExtra("INPUT_TEXT")

        getText.text = intentText

        val returnButton = findViewById<Button>(R.id.return_button)
        returnButton.setOnClickListener {
            finish()
        }
    }
}

```

AndroidManifestなどはQiita上に記載してないので、
困ったらGithubから確認してください

## 終わりに
Githubにもサンプル乗せているのでよかったらどうぞ！

https://github.com/naoyukitsuruo/EditTextSample
診断ツールを起動しない方法

# 事象

Visual Studio上でAzure Sphereのアプリケーションをデバッグ実行すると、同時に診断ツールが起動してAzure Sphereのメモリ使用状況が見れるようになった。
デバッグ実行時にいつも診断ツールが起動して画面が占有されてしまうので、止めたい。

![名称未設定2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/77172632-088a-a0dc-97d1-a1a140d76b4e.gif)

# 解決方法

**デバッグ > オプション** でオプション画面を開き、**デバッグ > 全般** にある**デバッグ中に診断ツールを有効にする**のチェックを外す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/c71e7d49-8883-aa8e-a2d5-9180b37c1231.png)
React入門(コンポーネントのライフサイクル)

- [公式サイトの参考](https://ja.reactjs.org/docs/react-component.html)

https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/

**Mounting**は初期値
**Unmounting**は初期値から変更された値

#useEffect

`import { useEffect } from 'react';`

```js:
useEffect(() => {
  // MountingとUnmountingに呼ばれる
})

useEffect(() => {
  // Mountingの時に呼ばれる
}, [])

useEffect(() => {
  // Mountingと引数の時に呼ばれる
}, [引数])

useEffect(() => {
    // Mountingの時に呼ばれる
  return () => {
    //Unmountingが呼び出される
   }
})
```


#おまけ
`styled-components`の書き方
`yarn add styled-components`でインストール出来ます
`import styled from 'styled-components';`

```js

const EditBtn = styled.button`
  margin: 0;
  padding 0;
`
```
コンポーネントにCSSをつけることができます。
RubyXLで最初のシート（テンプレート）から複数のシートを作成する２

以前書いた記事の続報です。前回の記事だけでは解決できない２つの不具合に遭遇しましたので情報を共有します。
https://qiita.com/DYO/items/bbdac8a9521cdaf5757e

- 計算式がコピーされない
- 計算が反映されない

こちらは前回までコードの一部でテンプレートのセルを新しいセルにコピーするメソッドです。

```
  def cell_render(template_cell, row_num, col_num)
    cell = @worksheet.add_cell(row_num, col_num, content_eval(template_cell.value))
    cell.style_index = template_cell.style_index
  end
```

テンプレートのセルが計算式の場合は `template_cell.value` の中身は''かnilになるので計算式はコピーされませんでした。

そこで以下のようにしました。

```
  def cell_render(template_cell, row_num, col_num)
    cell =
      if template_cell.formula.nil?
        content = content_eval(template_cell)
        @worksheet.add_cell(row_num, col_num, content)
      else
        expression = template_cell.formula.expression
        cell = @worksheet.add_cell(row_num, col_num, '', expression)
        cell.formula = template_cell.formula.dup
        cell.formula.ca = true
        cell
      end
    cell.style_index = template_cell.style_index
  end
```

`template_cell.formula.nil?` でそのセルが計算式かどうかがわかります。
`template_cell.formula.expression` で計算式が取得できます。

しかし、計算式が入っているにもかかわらず `template_cell.formula.expression`　が空になってしまうケースがありました。

その理由はテンプレートとなるエクセルを編集するときに、計算式をコピーしたり、フィルハンドルをドラッグして一気に入力させたりするとエクセルの内部データとしては `template_cell.formula.expression` は空のままで、元のセルを参照する形になるからです。

そこで一旦追加したセルにテンプレートのformulaをコピーして代入することで参照情報も追加します。
`cell.formula = template_cell.formula.dup`
これで一つ目の問題は解決しました。

もう一つ問題だったのがセルに計算式は入っているけれども見た目が空になることがありました。つまり計算が行われていない状態でファイルが開くという現象です。一度そのテキストを選択して確定すると計算されるような感じでした。調べてみるとformulaには「計算しろ」というフラグがあって、それをtrueにすることで解決できました。 `cell.formula.ca = true`

formulaのプロパティはこちらのドキュメントで確認できます。

http://www.datypic.com/sc/ooxml/e-ssml_f-1.html
インスタのハッシュタグ検索をAPIを使う

# 目標
動物に関する動画のURLや詳細情報一覧を取得すること

## まずは検索したいハッシュタグのidを取得する
今回はハムスターのタグのIDを検索する、
Getで
`"https://graph.facebook.com/v10.0/ig_hashtag_search?user_id=0000000000&q=ハムスター&access_token={access_token}"`
を叩く

で、17841563824129378が返ってくる

## 次に情報をGETで取得
`# ハムスター`のIDは17841563824129378
なので、ハムスターに関する最新の投稿情報を取得する
`recent_media?`を入れている部分に注目

####取得情報は`recent_media`と`top_media`の2種類を選択できる
`recent_media`
特定のハッシュタグが付いている最近公開された写真および動画IGメディアオブジェクトのリストを取得します。
`top_media`
ハッシュタグでタグ付けされている人気上位の写真および動画IGメディアオブジェクトを返します。

### Getで情報を取得する
`https://graph.facebook.com/17841563824129378/recent_media?user_id={USER_ID}&fields=id,media_type,comments_count,like_count&access_token={access_token}`


```json

{
    "data": [
        {
            "id": "000000000000000",
            "media_type": "IMAGE",
            "comments_count": 0,
            "like_count": 5
        },
        {
            "id": "000000000000000",
            "media_type": "VIDEO",
            "comments_count": 0,
            "like_count": 5
        },
       ......
       ......
        {
            "id": "000000000000000",
            "media_type": "CAROUSEL_ALBUM",
            "comments_count": 0,
            "like_count": 5
        },
        ...
    ],
    "paging": {
        "cursors": {
            "after": "UVZAGRFptWkRUV05mYzBKMFRVVTVWVEpYZAUhRMGQxSnVkME01ZAUZASalYxWmlhbmhFTjNwMVNWOUdVR1V3UkdVMGFsRjBWRXhoYUVKcVpHOVJWM2hLWkRRd05HbEpNR05IVkhWeE9YSmlURVpXTURORlRXVTBaUT09"
        },
        "next": "https://graph.facebook.com/v10.0/17843776303020306/recent_media?access_token=EAAGb8eIVAU0BAAKzUAs1yNZCJSetSTch&fields=id%2Cmedia_type%2Ccomments_count%2Clike_count&user_id=17841446220096876&limit=25&after=UVZAGRFptWkRUV05mYzBKMFRVVTVWVEpYZAUhRMGQxSnVkME01ZAUZASalYxWmlhbmhFTjNwMVNWOUdVR1V3UkdVMGFsRjBWRXhoYUVKcVpHOVJWM2hLWkRRd05HbEpR05IVkhWeE9YSmlURVpXTURORlRXVTBaUT09"
    }
}
```

返り値は件数制限があるようで、["paging"]["next"]に続きの情報を見ることができました
参考:https://developers.facebook.com/docs/instagram-api/reference/ig-hashtag/?translation
Railsの【params】を自分なりに噛み砕いた(３部作その１)

`flash`を理解する過程で、`params`や`session`についても理解できたのでまとめ
長くなりそうだったので、`1:params`、`2:session`、`3:flash`の3回に分けた

####【３部作リンク】
1:params（ここ）
[2:session](https://qiita.com/masahiroDIARY/items/4b442b149d0dc9a42eb0)
[3:flash](https://qiita.com/masahiroDIARY/items/d2d81f55fd695eb9d44e)

####【ページ内リンク】
[０．環境](#０環境)
[１．前提知識](#１前提知識)
[２．利用例](#２利用例)
[３．ストロングパラメータ](#３ストロングパラメータ)
[４．結論](#４結論)

#０．環境
・AWS
・Rails 5.2.4.5
・ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-linux]

#１．前提知識
この2つは**同義**。よく考えたらRubyで勉強したハッシュの仕組みと何ら変わらなかった･･･

```rb:example.rb
params[:id] = 2
params = { id: 2 }
```
・`.html.erb`で値を利用したいときは`<%= params[:id] %>`とすれば良い
・`params`は`link_to`等で渡された値が**一時的**に入れられる
・値は`link_to`等で渡された場所でしか利用できない。

[ページ内リンクへ戻る](#ページ内リンク)

#２．利用例
##順序①：ルート指定
```rb:routes.rb
Rails.application.routes.draw do
  resources :teams, only: [:index, :show]
end
```


##順序②：team_pathに「params[:id]=3」「params[:name]=名前」を渡す
```erb:index.html.erb
<%= link_to "押す", team_path(3, name: "名前") %>
```
・`link_to`は複数の値を指定することが可能
・これは`<%= link_to "押す", team_path(id: 3, name: "名前") %>`を略した書き方。先頭キーは指定しない場合`id`キーとなる
・これはつまり「**params = { id: 3, name: "名前" }**」が**一時的に**代入されたのと同義

###順序③：リンク「/teams/3」に表示させる
```erb:show.html.erb
その１：<%= params[:name] %>      <!--表示結果：名前-->
その２：<%= params[:id] %>        <!--表示結果：3-->
その３：<% params = { id: 4 } %>  <!--表示されない-->
その４：<%= params[:id] %>        <!--表示結果：4-->
その５：<%= params[:key] %>       <!--表示されない-->
```
・`link_to`等によって値(というよりハッシュ？)が渡されたので表示できる。しかし他のページでいくら`<%= params[:name] %>`と書いても表示できない
・「その２～４」のように、ページ内で値を書き換えることもできる

※「その５」でエラーとならず何も表示されない仕組み
１：Rubyはハッシュで存在しないキーを指定されると`nil("何も存在しない"の意)`を返す
２：つまり「その５」は`<%= nil %>`を表示しろ、という意味
３：２の表示結果は「何も表示しない」


エラーではなく正しい表示結果としてこうなっていた

[ページ内リンクへ戻る](#ページ内リンク)

#３．ストロングパラメータ
```erb:new.html.erb
<% @user = User.new %>
<%= form_with model: @user do |f| %>
  <p><%= f.text_field :name %></p>    <!--名前、と入力したとする-->
  <p><%= f.text_field :email %></p>   <!--Eメール、と入力したとする-->
  <%= f.submit "登録" %>
<% end %>
```
ここでは`params = { user: {name: "名前", email: "Eメール" } }`をcreateメソッドに渡している。これらの値を得るには以下の2通りの方法がある(勿論他にも沢山あると思うけど)。


```rb:users_controller.rb
その１：user = User.new(name: params[:user][:name], email: params[:user][:email])
その２：user = User.new(params.require(:user).permit(:name, :email))
```
・その２がストロングパラメータ。
・その１は、`params`から該当する値を取り出している。なので「name」「email」以外のキーがあっても無視されるだけである。
・その２は、値を得る前に既に`params = { user: {name: 〇〇, email: 〇〇 } }`という箱が出来ており、そこに**値をはめ込む**イメージ。よって他のキーの値が来たら失敗する。

[ページ内リンクへ戻る](#ページ内リンク)

#４．結論
【`params`の特徴】
`link_to`等で渡された値が**一時的**に入れられるけど、値はその場所でしか利用できない。

・`params`は**値**ではなく**ハッシュ**！！！！！（←超重要）

　ということは`link_to`や`form_with`で渡される値も全部**ハッシュ**･･･？って考えに至ってからは`session`や`flash`もすんなり理解できた（真偽は分からない）
　というかこれRails分野じゃなくて殆どRubyの知識だけだな･･･。Rails未経験でRubyだけ勉強してるときはハッシュの存在意義って何だよって思ってたけど、めっちゃ便利じゃん･･･
　とりあえず、`params`など知らない言葉が出てきても、焦らずにまずは文法を読み解くことが大事だと思った。

[ページ内リンクへ戻る](#ページ内リンク)
Dynamic importをしてrouteの情報が拾えなくなった問題の対応

# 始めに
vue-routerではファイルを直接importせずに非同期importすることによって画面ごとにファイルを分割してくれて1ファイルあたりのサイズを減らしてくれます。また実装コードも簡単なので手軽にできるのも魅力的です。

```javascript:router.js
// Pageコンポーネントの読み込みをimport呼び出しメソッドに変更するだけ
// before
// import Login from 'pages/Login.vue';
// import MyPage from 'pages/MyPage.vue';
// after
const Login = () => import(/* webpackChunkName: "Login" */ 'pages/Login.vue');
const MyPage = () => import(/* webpackChunkName: "Menu" */ 'pages/MyPage.vue');

const router = new VueRouter({
  routes: [
    { path: '/', components: Login, meta: { isPublic: true } },
    { path: '/my-page', components: MyPage },
  ],
});
```

しかし画面の取得が非同期になったことで初期表示では`$route`の情報が拾えずにログインチェックが上手くいかなかった問題が発生しました。ここではこの問題の対応方法について説明したいと思います。

```vue:App.vue
<script lang="js">
export default Vue.extend({
  created() {
    this.checkLogin();
  },
  methods: {
    checkLogin() {
      // publicな画面はスキップ
      // 初期表示ではmetaが含まれていなかったorz
      if (this.$route.meta.isPublic) {
        return;
      }
      // 認証情報があるかチェックする
    },
  },
});
</script>
```

# 解決方法
結論から言うと`router.onReady`のコールバックから処理をかくと良いです。ルーティング情報も非同期で取得されるため、routerが使える状態になるのも少し遅れるようです。
Issueでも上がっていました。
https://github.com/vuejs/vue-router/issues/3439

```vue:App.vue
<script lang="js">
export default Vue.extend({
  created() {
    this.$router.onReady(() => {
      this.checkLogin();
    });
  },
  methods: {
    checkLogin() {
      // publicな画面はスキップ
      // onReady後だとキチンとmetaが拾える
      if (this.$route.meta.isPublic) {
        return;
      }
      // 認証情報があるかチェックする
    },
  },
});
</script>
```

## 補足
画面ごとに$route.paramsとか見ている場合も問題になるのかちょっと考えたのですが、そもそも画面を読み込めた時点でroute情報は取れるはずなので、全体のルーティング設定とかの場合にこの現象が発生するのかなと思いました。

# 終わりに
以上がDynamic importにしたらroute情報が取得できなくなった問題の対処方法でした。実装自体は簡単ですが、非同期処理が挟まれるため、思わぬところで問題が起きました。比較的限定的な時に発生して気付きづらいので、もし似たような境遇の方がいましたら参考になれれば幸いです。
[StoryBook] KnobsとかControlsの値をコンポーネント内から変える

こういうコンポーネントがあるとする

```react
const ToggleButton = ({ isOn, onClick }) => (
  <button onClick={onClick(!isOn)}>
    {isOn ? 'ON' : 'OFF'}
  </button>
);
```

で、こういうコンポーネントをStoryBookで見る時に
"knobsやcontrolsの操作で`isOn`が切り替わる" かつ "ボタンを押した時でも`isOn`が切り替わる" ストーリーを書く方法

## Storybook v6~ & addon-controls の場合
`@storybook/client-api`からカスタムフック`useArgs`をインポートしてきて
ストーリーコンポーネントの引数ではなく`useArgs`の第一要素の値をコンポーネントにpropsとして渡す。

値を変更する場合は`useArgs`第二要素の関数へオブジェクトを`{ 変更したいキー: 変更後の値 }` の形で投げてやればArgsが変更され、それに応じてControlsアドオンの表示も変わる

```react
import { useArgs } from '@storybook/client-api'

// コンポーネント記述
export default {
  /* 省略 */
}
// ストーリー記述
export const Story = () => {
  const [argValues, updateArgs] = useArgs();
  return (
    <ToggleButton
      {...argValues}
      onClick={(value) => updateArgs({ isOn: value })}
    />
  )
};
// ストーリーのProps初期値
Story.args = {
  value: false
};
```

## Storybook ~v5 & addon-knobs の場合

`@storybook/addons`パッケージを読み込んで表示中ストーリーのチャンネルを取得し、
そこに対して任意のprops名と変更後の値をemitして強制的に書き換える
(参考: https://github.com/storybookjs/storybook/issues/3855#issuecomment-624164453)

```react
import { addons } from '@storybook/addons';
import { boolean, CHANGE } from '@storybook/addon-knobs';

// コンポーネント記述
export default {
  /* 省略 */
}
// ストーリー記述
export const Story = () =>　(
  <ToggleButton
    isOn={boolean('isOn', false)}
    onClick={(value) => {
      const channel = addons.getChannel();
      channel.emit(CHANGE, { name: 'isOn', value });
    }}
  />
)
```
RedashのデータをGoogleスプレッドシートに自動で反映する方法

## はじめに
Redashを使って取得したデータを時系列で比較したい時、今までは手作業で行っていました。
手作業だと取得し忘れたりなど地味に面倒なので、この作業を自動化できないかと考えたのがきっかけです。

## 手順
Googleスプレッドシートにベースとなるシートを作り、そのシートを定期的に複製することで、データをためていきます。

1. RedashのデータをGoogleスプレッドシート用に調整
2. GoogleスプレッドシートでRedashのデータを読み込む
3. データの読み込み作業を自動化するスクリプトを設定
4. 自動化した作業の繰り返しを設定

### 1. RedashのデータをGoogleスプレッドシート用に調整
Googleスプレッドシートに転記したいRedashデータを開き、`Refresh Schedule`を設定します。
`Refresh Schedule`は画面左下（下記画像の赤枠部分）の青文字から設定できます。

![アートボード 1-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351760/909aba92-c3f2-11f0-9662-e8699a4cb405.png)

### 2. GoogleスプレッドシートでRedashのデータを読み込む
Googleスプレッドシートを開き、`IMPORTDATA`を使ってRedashのデータを読み込みます。
任意のセルに`=IMPORTDATA("RefreshのQuery API Key")`を入力すると、RedashのデータがGoogleスプレッドシートに反映されるようになります。

#### RefreshのQuery API Keyの取得方法
1. 画面右上の`・・・`をクリック
2. 展開したメニューの`Show API Key`をクリック
3. 表示されたモーダルの`Results in CSV format`下部のURLをコピーすれば完了

![アートボード 1-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351760/6c6bab74-4fe1-3638-8da4-6c8b13719460.png)

![アートボード 1-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351760/08f4c684-f442-a48c-cf27-37b8bb0787a6.png)


### 3. データの読み込み作業を自動化するスクリプトを設定
Googleスプレッドシートのツールバーにある`ツール`から、`スクリプトエディタ`をクリックします。

![アートボード 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351760/2531a40c-4968-5e4a-b84c-371c3cf0fedd.png)

Apps Scriptが表示されるので、画像の赤枠部分に以下のスクリプトを追加します。

![アートボード 3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351760/68f8e50a-d468-e264-2f59-a9561552795a.png)

```javascript
function myFunction() {
  var book = SpreadsheetApp.openById('[GoogleスプレッドシートのID]');
  var sheet1 = book.getSheetByName('[シート1（コピー元のシート）]');
  var date = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyyMMdd');
  var lastRow = sheet1.getLastRow();
  var lastColumn = sheet1.getLastColumn();
  
  book.insertSheet(date,1);
  var sheet2 = book.getSheetByName(date);
  var newData = sheet1.getRange( 1 , 1 , lastRow , lastColumn ).getValues();
  sheet2.getRange( 1 , 1 , lastRow , lastColumn ).setValues(newData);
}
```
このスクリプトでは、以下を実行するようにしています。
※ 画像では以下実行内容に加えて、書式設定もコピーするように記述していますが、ここでは割愛します

1. 「シート１」の後ろに新しいシートを挿入する
1. 「シート１」の情報を新しく追加したシートにコピーする
1. 新しく追加したシートの名前を日付（yyyyMMdd）の名称に変更する

### 4. 自動化した作業の繰り返しを設定
1. Apps Scriptの左にある時計アイコンをクリック（トリガーページへ移動）
1. ページ右下の`トリガーを追加`をクリック（モーダルが起動）
1. `イベントのソースを選択`で`時間主導型`を選択
2. `時間ベースのトリガーのタイプを選択`で任意のタイマーを選択
3. 最後にタイマーの実行間隔を選ぶ

私は毎日定時で取得して欲しかったので、以下のような設定にしました。

- `時間ベースのトリガーのタイプを選択`：日付ベースのタイマー
- `時刻を選択`：午前 10 時～11 時  
※ Redashの実行タイミングと被らないように1時間遅めの実行時間でセット


以上です。
これでRedashのデータをGoogleスプレッドシートに自動的に持ってくることができるようになります。

最後までお読みいただき、ありがとうございました。

---
### お世話になったサイト
- [データの変化を見るためにRedashで実行したSQLの結果をGoogleスプレッドシートに定期的に保存する](https://note.com/711fumi/n/nbe825df70b89)
- [GASでredashの最新の結果を取得してスプレッドシートに反映する](https://qiita.com/Iwark/items/d1eaff284669e99c5f41)
- [GAS×Redashで月18時間の工数削減を実現！ ～API操作は難しいけど便利だった～](https://techblog.locoguide.co.jp/entry/2020/10/26/095334)
Rails 超簡単 プロフィール画像ちょっとした工夫  初期画像 (no image)

#  はじめに
筆者は [大学生限定 プログラミングコミュニティ 『GeekSalon』](https://geek-salon.com/?utm_source=Direct&utm_medium=attract&utm_campaign=2Q&utm_content=Fukuoka_E_2Q)で活動している者です！ 
もし少しでも興味がありましたら、ぜひお話を聞きにきてくださいね♪

では本題。プロフィール画像の設定をしていないとき、LINEやTwitterのように、あの人型シルエットを表示させたい！ってなったことありませんか？!？!？

実はこれ、知ってるか知ってないかだけで、めちゃくちゃ簡単に実装できるのです！！！

#前提
マイページを作成していること
プロフィール画像を実装していること

#ポイントはこれだ！！！

```ruby:xxx.html.erb
<% if 〇〇.present? %>
```

これで画像を設定しているのかどうかを判定しています！！(〇〇は画像のカラム名が入ります)
プログラミング的な言い方をすると、画像が存在していたらtrueを、存在していなかったらfalseを返しています。

#具体的な使い方を見てみよう！！


まず、 ```app/assets/images```　配下に、プロフィール画像が設定されていないときに表示させたい画像を準備します


![スクリーンショット 2021-03-16 14.07.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081227/97ab9bae-14e6-7c2f-98b3-d25f5a9eff96.png)

次に、条件分岐によってプロフィール画像が設定されている時はその画像を、設定されていない時は先ほどのnoimageの画像が表示されるようにします！

```ruby:xxx.html.erb
  <% if @user.image.present? %>
    <%= image_tag @user.image.url %>
  <% else %>
    <%= image_tag 'noimage.jpg'%>
  <% end %>
```
※この場合は、プロフィール画像が入るカラムをimageとしています！

いかがだったでしょうか、、、？　　たったこれだけです！！^^
#最後に
今回はプロフィール画像に焦点を当てて記事にしてみましたが、```if 〇〇.present?``` を使えば様々なことに応用可能です！！

ぜひ色んなのを考えて組み立ててみてくだせえ！^^

何か補足修正等ございましたら編集リクエストしてくださいませ〜！！

それではバイちゃ〜〜👋
wordpressでブログを作ったが、数式が画面外にはみ出してしまった

Wordpressでブログを作成しようと思い立った。
それは、自分の高校から続く20年近い理系のキャリアを活かして、何か有益な情報発信ができるのではないか、と思ったから。

でも、そもそも理系といっても実験系のキャリアで、かつブログ運営経験はほとんどなく、どのように数式や計算を表現していくかについても漠然としたイメージしかもっていなかった。
ワードやパワーポイントでは数式エディタで書けるように、「まぁ普通に書けるんじゃないかな？」ぐらいにしか思ってなかった。
そんな甘い認識の中、えいやっとブログを開設し、実際に書き始めてみたが、分からない。まぁ、分からない。

単純にy=x/y+2√7などと、直接打ち込むことも考えたが、これは分数になっただけで既にものすごく見ずらい。まして、微分積分など、表現できようが無い。

次に、ワードやパワーポイントの数式エディタで描いた数式を、ワードプレスに画像として貼り付けることを考えた。
これは、まぁそれなりに「見れる」ぐらいのものにはなるが、これもいくつか問題がある。
というのは、なにせ「画像」であるため、数式が続いて大きな画像になると、パソコンから見るのには大丈夫だが、スマホのような小さな画面から見ると画像が小さく縮小されてしまい、細かくなった数式が読める状態では無くなってしまう。

そんな、おそらく超初歩的なところで躓きながら、ようやくLaTeX形式、というもので表現しなければならない事が分かった。
じゃあそのLaTeX形式をどうやって入力するか、表現するか、が分からない。

プラグインに、LateX形式で描けるものがあるようだ。またこれもいくつかあるようで、どれにしたらいいのか分からないが、とりあえずMathJax-LaTeXというのがメジャーっぽい。
このプラグインを導入すると、確かに数式が描けるようになった！！！
だが、このLaTeX形式、結構くせ者で、表現技法を習熟するのは、とても大変。
また、新しい行に数式を書く方法と、文章中と同じ行中に数式を書く方法も違うため、かなりやっかいである。

そして、このMathJax-LaTeXを使って数式を表現する事に少しずつ慣れてきたところに、最後の関門が待ち受けていた。。
それは、パソコンで見ると非常に綺麗に描けているせっかく書いた数式が、スマホ画面になると、横にはみ出してしまっているのである！！！

な、なんということか！！せっかく苦労して描いたのに！！（涙）

で、例によって同じような症状の人がいないかググってみると、やっぱりいた。同じようなことになっている人たち。
その方々は、どうやらCSSにコードを追加することで解決しているらしい。

自分もやってみた。。。。。。でも、うまくいかない。。。なぜか、うまくいかない。。。
何故かはわからないが、うまくいかないのだ。。。。

結局、詳細な理由は不明だが、最後までうまくいかなかった。横にはみ出す問題が解消しないのだ。

ほとほと困り果てていると、そもそもMathJax-LaTeXを使わなくても、LaTeX形式で数式を書く事ができるらしいことに気付いた。
それは、headタグにJavaScriptソースコードを挿入することで、MathJaXが使えるようになる、というもの。
具体的には、以下のリンク先が詳しい。

https://michikusa.biz/wordpress-sushiki-hamidasanai/

この方法を用いることで、先ほどのプラグインを入れなくても数式を綺麗に描く事ができた。さらにCSSを追加することで、スマホのような小さな画面の場合には数式を横スクロールできるようになり、全ての問題を解決できた。

ここまで苦労するとは思わなかったが、結果としては、数式を綺麗に書く事ができるようになった。
やはり一つずつできることが増えていくことは、とても嬉しい事だと思う。
element ui tab 下のバーの色を変更

element ui で タブのバーの色を変えたい。

```

    .el-tabs__item:hover {
        color:#ed6ba0;
    }

    .el-tabs__item.is-active{
        color:red;
    }

    .el-tabs__active-bar{
        background-color:pink;
    }

```

こんな感じでOK!
「ゼロからはじめるLinuxサーバー構築・運用ガイド-動かしながら学ぶWebサーバーの作り方」で躓いたところ

#概要
下の本で自分が躓いたところをまとめました。
(初版第3刷)

<https://www.amazon.co.jp/dp/4798146374>

#躓いたところ
##p33 CentOSのストレージの設定画面
###躓いた点
ストレージの設定画面でポップアップが表示されるはずが、表示されない。
###解決法
「other storange options partitioning」で「Automaticall contigure partitioning」が選択されているか確認

##p46 Tera Termの使い方
###躓いた点
VPSにログインできない。
###解決法
TCPポートを「22」から「10022」(設定した値)に変更する。これより前の作業でポート番号の設定を変えているため。

##p170 Wordpressが使えない
###躓いた点
「ttp://VPSのIPアドレス/blog/wp-admin/install.php」 にアクセスすると「php5.4は無理。5.6以上にして(意訳)」と言われる。
###解決法
下の記事を参考にphp5.6を導入する。
<https://qiita.com/heimaru1231/items/84d0beca81ca5fdcffd0>
画像ライブラリphp-gdだけインストールできなかった気がしますがどうやったか度忘れしました。下の記事を参考にしていた気がします。
<https://qiita.com/ozawan/items/caf6e7ddec7c6b31f01e>


##p219 dockerのimage削除
###躓いた点
dockerのimageが削除できない。
###解決法
コンテナを削除してからイメージを削除する（文章に書いある）。
具体的には、
`sudo docker ps -a`
でコンテナ一覧から削除したいイメージに関連したコンテナを見つけて
`sudo docker rm コンテナID`
でコンテナを削除。その後、
`sudo docker images`
でイメージ一覧から削除したいイメージを見つけて
`sudo docker rmi イメージID`
で削除できる。

##p220 CentOS6のyum
###躓いた点
Dockerfileからbuildコマンドでイメージを作成したいが上手くいかない。
###解決
あきらめた。CentOS6系のyumレポジトリの場所が変わってしまっていいるのが原因と思われる。
レポジトリ(リポジトリ):保管場所
スマホを横向きにした時の右余白を消したい！

#症状
iPhoneなどのスマホを横向きにした時に、
右側に余白が出来ることがあります。

「そんな余白を消したい！！」

という時の対処法です。


##対処法
1.画面右側からはみ出ている要素がないか確認する。はみ出ていれば修正する。
2.`viewport`の指定を確認する
3.htmlタグ、bodyタグに`width: 100%;`が指定されているかを調べる。されていなかったら指定する。
4.bodyタグに`min-width: 100%;`を指定する。

###手順1
1の方法で問題なければバンザイです。
2へ進む必要はありません。

###手順2
2については、最低限下記を指定します。

```
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
```

`initial-scale=1`や`minimum-scale=1`の記述が抜けていることがあるので、
抜けていたら追加してください。

###手順3、4
2を完了したあと、手順3、4を確認します。
3で問題なければ4の対応をする必要はありません。

とりあえず、私はこれでなんとかなりました。
よかった。

###参考サイト
https://on-ze.com/archives/1902


##終わりに
取り急ぎ、備忘録として。
以上です。
Cloud Pubsub でpublishした順序通り(順序指定)にpullする

# 背景
Pubsubでpublishされたメッセージをpullを順序通りに取得したい

# 方針
- subscribeを順序有効で作成し
- publishの実装で以下3つを行った実装をする
  - enable_message_orderingをTrue
  - region指定
  - ordering_keyを指定 

# subscribe を 順序有効で作成
コンソールでsakuseijini `順序指定キーを使用してメッセージの順序を指定する` にチェックするのが楽

https://cloud.google.com/pubsub/docs/ordering

# publish の実装

参考

https://cloud.google.com/pubsub/docs/publisher#using_ordering_keys


```py
from google.cloud import pubsub_v1

project_id = "your-project"
topic_id = "my-topic"


# enable_message_ordering=Trueでoptionを作成する
publisher_options = pubsub_v1.types.PublisherOptions(enable_message_ordering=True)
# 同じリージョンのapi_endpontを指定する. 今回はasia-northeast-1
client_options = {"api_endpoint": "asia-northeast1-pubsub.googleapis.com:443"}
publisher = pubsub_v1.PublisherClient(publisher_options=publisher_options, client_options=client_options)
topic_path = publisher.topic_path(project_id, topic_id)

for n in range(1, 10):
    data = "Message number {}".format(n)
    data = data.encode("utf-8")
    # ordering_keyは任意の文字列を指定。このvalueが同じ物同士が順位付される. (注意: 勘違いしてここに順序を意味する "1", "2", "3"などを入れないこと) 
    future = publisher.publish(topic_path, data, ordering_key='key1')
    print(future.result())

print(f"Published messages to {topic_path}.")
```

# subscriberの実装(同期)

通常の同期pullと同様



```py
from google.api_core import retry
from google.cloud import pubsub_v1

project_id = "your_project"
subscription_id = "my-sub"

subscriber = pubsub_v1.SubscriberClient()
subscription_path = subscriber.subscription_path(project_id, subscription_id)

NUM_MESSAGES = 1

with subscriber:
    while True:
        response = subscriber.pull(
            request={"subscription": subscription_path, "max_messages": 1},
            timeout=10,
            retry=retry.Retry(deadline=300),
        )

        ack_ids = []
        for received_message in response.received_messages:
            print(f"Received: {received_message.message.data}.")
            ack_ids.append(received_message.ack_id)

        # Acknowledges the received messages so they will not be sent again.
        subscriber.acknowledge(
            request={"subscription": subscription_path, "ack_ids": ack_ids}
        )

        print(
            f"Received and acknowledged {len(response.received_messages)} messages from {subscription_path}."
        )
```

以上でpublishされた順序通りにpullすることができる。

# 順序指定のデメリット
自分の手元で確認したところ、、、

順序指定を有効にすると、非同期pullでは1つずつしか処理できず(並列化できない)、同期pullでも同時複数の取得ができなくなるので、パフォーマンスを重視したpullシステムを作りたい場合は順序指定は慎重に導入する必要がある。
Google Anthos

#背景
- "OpenShiftがオンプレでもクラウドでも"と言ったときにGKEはどうなのか調べたかった


#概要
- ざっくり「GKEをパッキングしてGCPにもオンプレにもAWSにももっていける」感じ
- AWS Outpostsのように"クラウドのAZをオンプレで"ではなく、"GKE, Istio, Knativeなどコンテナを動かせるクラスターをVM上で"のイメージ（GKE以外のコンピュート・ストレージサービスなどはAnthosには含まれない）
- Ingress for AnthosはGCPでのみ（オンプレもAWSも非対応）
- GCPのコンソールからオンプレのAnthosも管理できる
- 管理用通信はAnthosからアウトバウンドでPollingして実施（FWのインバウンド穴あけは不要）
- 構築・運用は利用者で実施
- PodネットワークはCalico、NodeネットワークはVMware（Tanzu Kubernetes Clusterにイメージは近い）



#その他調べたことQA形式
Q. オンプレGKEのコントロールプレーンはどこに存在するのか
A. オンプレ

Q. GCPにAnthosを置いたらGCPのGKEとは別のAnthos GKEが出来上がるのか
A. No、

https://cloud.google.com/anthos/deployment-options?hl=ja


Q. GCPにAnthosを置いたらAnthos GKEは誰が面倒を見るのか
A. 利用者

https://cloud.google.com/anthos/docs/concepts/gke-shared-responsibility

Q. オンプレAnthos内外のネットワークはどうなるのか
A. PodネットワークはCalico、NodeネットワークはVMware

Q. CloudRunとFunctionsの違い
A. CloudRunはシンプルなコンテナの利用用途、スケールが必要なシンプルなコンテナ向き
Functionsはコンテナも意識しないソースコードの実行




#感想
- 「GKEがあるのになぜわざわざGCPにAnthos？」と思ったけど、GCP, オンプレ, AWSに対して同じAnthosのラッピングで使い分けれできればそれは便利かもしれない
- AnthosとOpenShiftを比べると、あとは事例・将来性・価格とか？
- GCP, オンプレ, AWSで同じラッピングにさせたとして、DBをどうするのかが悩ましい（RDSがいいとなったらAWSしかないし、それならOutpostsでEKSでいいような気もしてくる）



#知りたいこと
- ASM（Anthos Service Mesh）のコントロールプレーン（Google管理）はGCPにある？


#参考
https://cloud.google.com/anthos?hl=ja

https://www.slideshare.net/GoogleCloudPlatformJP/cloud-onair-anthos-gke-onprem-2019829-167420368

https://speakerdeck.com/tikson/plaids-journey-with-multi-cloud-10128526-d75f-41de-98ec-27025f8d35a9
【Android】ViewModel内でUiModelを使おう(その1)[sealed class編]

# はじめに
[ViewModel](https://developer.android.com/topic/libraries/architecture/viewmodel?hl=ja)は現在多くのプロジェクトで利用されているかと思いますが、LiveDataが多くなってくると管理するのが大変になってきます。最終的にはUiModelを使ってLiveDataの数を少なくし、ViewModelに関するコードをすっきりさせるのが目的です。今回は最初の段階として`sealed class`を使ってViewModelをきれいに書く方法です。

# 対象
 - [ViewModel](https://developer.android.com/topic/libraries/architecture/viewmodel?hl=ja)を利用している方(MVVMのViewModelというよりはAndroidのViewModelライブラリ)
 - kotlinが読める方

# LiveDataの型をどうしていますか？
例えば画面に表示する文字列をViewModelで管理する場合、下記のようにLiveDataを用意します。

```Kotlin:MyViewModel
class MyViewModel : ViewModel() {
    private val _text = MutableLiveData<String>("") // 初期化方法は導入しているライブラリによっても違うのでお好きな方法で
    val text: LiveData<String> = _text
    …
}
```

開発中や開発初期の場合はこれでも良いですが、あとから「文字列はサーバから通信して取得したいな」とか「文字列を使用したら空文字にしたりデフォルト値にしたい」とかいろんな要望があとから出てくることもあると思います。今回は通信中を表す`isLoading`を下記のように実装します。

```Kotlin:MyViewModel
class MyViewModel : ViewModel() {
    private val _text = MutableLiveData<String>("")
    val text: LiveData<String> = _test
    private val _isLoading = MutableLiveData<Boolean>(false)
    val isLoading: LiveData<Boolean> = _isLoading
    …
}
```

# LiveDataに状態を持たせる
まだLiveDataは2つなので、そんなに問題にはなりませんが、GUI上で表示したいデータや扱いたいデータが多くなってくるとLiveDataの数がどんどん増えてしまいます。このような場合は新しく`sealed class`、`object`、`data class`を利用してすっきり書けるようになります。下記のようなクラスを用意します。

```Kotlin:TextState
sealed class TextState {
    data class Loaded(val text: String) : TextState
    object Loading : TextState
}
```

# ViewModelをすっきりさせる
`TextState`を作ったことにより、`MyViewModel`は下記のように書き直すことができます。

```Kotlin:MyViweModel
class MyViewModel : ViewModel() {
    private val _textState = MutableLiveData<TextState>(TextState.Loading)
    val textState: LiveData<TextState> = _textState
    …
}
```

このように実装することでLiveDataの数が一つ減って文字列と状態を1つのLiveDataで管理できるようになったので、すっきりしました。あとは通信中の場合`_textState.postValue(TextState.Loading)`、通信完了時は`_textState.postValue(TextState.Loaded("complete"))`とするとLiveDataを観測する側は通信中、通信完了及び取得した文字列を扱えるようになりました。

```Kotlin:FragmentやActivity等
class MyFragment : Fragment() {
    override fun onViewCreated((view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        myViewModel.textState.observe(viewLifecycleOwner) { textState ->
            textView.text = when (textState) {
                is TextState.Loading -> "loading"
                is TextState.Loaded -> textState.text
                // sealed classなのでelseを書く必要がありません
            }
        }
        /*
        これが不要になりました。
        myViewModel.isLoading.observe(viewLifecycleOwner) {
        }
        */
    }
    …
}
```

# まとめ
LiveData内の変数の型をこのように変更するとViewModel内のコードが短くなり、それを観測する側のFragmentやActivityもLiveDataの数だけobserveする必要がなくなったので、見通しが良くなったのではないでしょうか？もし通信に失敗した場合の状態も追加したいのであればTextStateに`object LoadError : TextState`とかを追加すればコードの変更量を少なく、エラー表示にも対応でき、変更に強いViewModelを作ることが可能です。

次回 「[【Android】ViewModel内でUiModelを使おう(その2)[UiModel編]](https://qiita.com/saitoyusuke/items/7828bf10cbca02950954)」
探索的データ解析（EDA）のためのPandas-profilingを試してみた

* 製造業出身のデータサイエンティストがお送りする記事
* 今回は、探索的データ解析（EDA）の一つであるPandas-profilingを試してみた。

##はじめに
探索的データ解析（EDA：Exploratory data analysis）は、機械学習などのデータ分析業務を実施する際に、データの理解を目的として実施する作業を指します。
つまり、現場の問題を解決する際に、どのようなデータセットを扱っているのか、どのような状況にあるのかを、しっかりと理解するのが重要であり、探索的データ解析は上記を目的とした作業です。

##Pandas-profiling実行例
今回は、探索的データ解析ツールの一つである「Pandas-profiling」を使ってみようと思います。

今回もUCI Machine Learning Repositoryで公開されているボストン住宅の価格データを用いてPandas-profilingを実装します。

pythonのコードは下記の通りです。

```php
# 必要なライブラリーのインポート
import pandas as pd
import numpy as np
import pandas_profiling as pdp

from sklearn.datasets import load_boston
```

次にデータを読み込みます。

```php
# データセットの読込み
boston = load_boston()

# データフレームの作成
# 説明変数の格納
df = pd.DataFrame(boston.data, columns = boston.feature_names)

# 目的変数の追加
df['MEDV'] = boston.target

# データの中身を確認
df.head()
```

![スクリーンショット 2020-11-09 20.33.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/2ffa1a41-98dd-2798-1f6d-8f3385bf5f75.png)

次にPandas-profilingを実装します。

```php
report = pdp.ProfileReport(df)
report.to_file('Pandas-profiling_report.html')
```

これで実装は終了です。
後は、出力されたhtmlファイルを使って分析をしていきます。

##Pandas-profilingで分析できる内容

最初にデータの概要が分かります。
データの型や欠損率、サンプル数とかがパッと分かります。

![スクリーンショット 2021-03-16 13.39.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/e8580ee3-eed2-6a38-4240-c2935ae61d00.png)

各カラムの基本情報やヒストグラムも一目で分かります。

![スクリーンショット 2021-03-16 13.41.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/b37d86c7-7129-5788-7312-c1992fd4ebb3.png)

各変数同士の相関関係も分かります。

![スクリーンショット 2021-03-16 13.42.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/0be2acda-bc20-83f7-3839-3128db4d516e.png)

欠損率もカラム別に分かれております。

![スクリーンショット 2021-03-16 13.43.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/efdd7b65-ea88-86f0-5432-effb8c9a2e79.png)

##さいごに
最後まで読んで頂き、ありがとうございました。
探索的データ解析をこんなに簡単にできるのは非常に便利だと思いました。また、htmlファイルに出力されるので、関係者へ結果を共有する際にも便利だと思いました。

訂正要望がありましたら、ご連絡頂けますと幸いです。
Firebase: SDK経由で画像をStorageにアップロードできない。デフォルトのGCPリソースロケーションを最初に設定して困った話。

## 困った内容

開発環境とは別に本番環境を作成しようとしました。先にリソースロケーションを決めてしまおうと思い、下記から asia-northeast1 を選択。その後、HostingやFunctionsで、始めるをクリックしつつ、ReactをデプロイしてApplicationを構築しました。
![instruction-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128706/17bec175-8331-bba9-8d7a-916b05efbab8.png)

構築後、Reactから、Cloud Storage for Firebase にSDK経由で画像をアップロードしようとしたところ、SDK上でエラー(404)が発生して、アップロードできませんでした。

結局、新たにプロジェクトを再作成し、Storageを始めるを押して、その際にリソースロケーションを選択し、再構築しました。

![instruction-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128706/1401775e-d038-8879-37a1-0c06794bc34e.png)

## 原因と思われること。
![instruction02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128706/1fc96da9-e73f-4e73-3462-18b7943a17e6.png)

エラーが発生したプロジェクトでは、
`@gcp-sa-firebasestorage.iam.gserviceaccount.com`
という「Cloud Storage for Firebase サービス エージェント (Cloud Storage for Firebase Service Agent)」 というロールの、サービスアカウントが見つかりませんでした。

基本的に、Firebaseのサービスでは「始める」を押した際に、対応するサービスアカウントが作成されているように見えます。
デフォルトのGCPリソースロケーションを先に設定すると、その時に他のサービスはStorageだけは一緒に作成されている様子です。しかし、Storageのための上記のサービスアカウントは作成されないようです。
さらに、Storageのページでも、「始める」ボタンも表示されなくなってしまうので、Firebase経由で、サービスアカウントを新たに作成することができません。

GCPのコンソールからも、サービスアカウントを作成することは自分はできなかったので、新たにプロジェクトを再作成する道を選びました。

## 参考
* [Google Cloud と統合する](https://firebase.google.com/docs/storage/gcp-integration)

> Google Cloud Storage を使用して Firebase プロジェクトを作成する際に、対応するサービス アカウント（service-\<project number\>@gcp-sa-firebasestorage.iam.gserviceaccount.com.）がプロジェクトですでに使用可能になっている場合があります。

(「可能になっている場合があります。」と言われても..)

* [Google Cloud - Service agents](https://cloud.google.com/iam/docs/service-agents)
* [firebasestorage.serviceAgent ロール](https://cloud.google.com/iam/docs/understanding-roles#firebasestorage.serviceAgent)
let,const,varの使い方について

#はじめに
JavaScriptの``let``,``Const``,``var``の使い方・使い分けについて解説します。


##とりあえず結論から
1.基本的に変数宣言は``const``でOK
2.``var``はもう使わなくてOK
3.変数への再代入をする場合は``let``を使用する

###constについて
 ``const``の特徴は**再宣言/再代入不可**という点にあります。

**再宣言・再代入とは**

```JavaScript
//変数定義
const name = "Naynko";
//再代入
name = "Oneko";
//再宣言
const name= "neko";
//出力
console.log(name);
//エラーとなり実行できない
```

これを出力した場合エラーが出ると思います。
よってconst変数の場合、このような再宣言/再代入は**不可能**という事になります。

###letについて
``let``の特徴は**再宣言不可/再代入可**という点にあります。

```JavaScript

//変数定義
let name = "Naynko";
//再代入
name = "Oneko";
//出力
console.log(name);
//constとは違い実行出来る。
```
####使い分けについて

基本的にconstでいいが、再代入したい場合はlet
for文などの場合、iを再代入することが多いのでletを使うと良いと思います。
Laravelでxdebugを使ってcoverage出来なかったので、代わりにpcovを使った話

#前提のご説明
###環境
OS linux
Laravel 8.15.0
php 7.3.27
phpunit 9.4.3
###何がしたかったか
Laravelでテスト駆動開発を学習する教材をやっていた。
phpunitでxdebugを使ってカバレッジを取ろうとしたところ、

```
$ php artisan test --coverage-html coverage
```

を実行したがhtmlファイルが作成されなかった。  
そこで、xdebugよりpcovを使った方が処理が早いという情報を聞きつけ、pcovを使ったところ無事カバレッジが取れた。

###参考にした記事
[pcovを使用したコードカバレッジ計測](https://gakous.hatenadiary.jp/entry/2021/02/02/225001)
#実際の手順
###pcovをインストール
osによってインストールコマンドが違うので下記を参考にしてください。
https://github.com/krakjoe/pcov/blob/develop/INSTALL.md  
※phpunit7以下の場合はClobberの追加が必要だそうです。
Clobber:https://github.com/krakjoe/pcov-clobber

```
$ composer require pcov/clobber --dev  
$ ./vendor/bin/pcov clobber
```  

###PHPUnitを実行
コマンドは

```
$ php -d pcov.enabled=1 ./vendor/bin/phpunit --coverage-html [出力先path]
```

ですが、長いので```composer.json```ファイルに

``` php:composer.json
  "scripts": {
  //省略
  "test": "php -d pcov.enable=1 ./vendor/bin/phpunit --coverage-html"
  }
```

のように追記しました。

これで、

```
$composer test [出力先path]
```

を実行すればカバレッジが取り出せるようになります。
DockerでKeycloakをサクッと立ててSAML検証環境を構築する

## はじめに

弊社はエンタープライズ向けHRアプリケーションを提供する企業です。エンタープライズ向け、という関係上、認証ではSAML SSOのニーズが高く、弊社で提供するアプリケーションも軒並みSAMLに対応しています。
SAML対応機能の開発やトラシューをするうえで、手元でサクッとIdPを構築出来たら便利だな、と思い、Dockerを使ってSAML IdP機能を持ったOSSであるKeycloakを手軽に構築する手順をまとめました。
Windows環境において、WSL2のセットアップと、WSL2上でのDockerの構築設定を説明した記事も紹介します。

## (Windows向け)WSL2の設定とDocker Desktopの設定
https://qiita.com/cold-wisteria/items/9db8a5560bdec99f428a

上記記事の、[windows 10のバージョンを2004以降に上げる](https://qiita.com/cold-wisteria/items/9db8a5560bdec99f428a#windows-10%E3%81%AE%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%82%922004%E4%BB%A5%E9%99%8D%E3%81%AB%E4%B8%8A%E3%81%92%E3%82%8B)から、[Docker Desktopのインストール](https://qiita.com/cold-wisteria/items/9db8a5560bdec99f428a#docker-desktop%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)までの手順を完了します。
これにより、WSL2の設定と、DockerコンテナをWSL2上のLinux VMで動作させる設定が完了します。

## KeycloakをDockerで立ち上げる
https://hub.docker.com/r/jboss/keycloak/

JBossが用意しているDocker ImageがDocker Hubにありますので、こちらを使うことで一瞬でKeycloakを立ち上げることが可能です。
コマンドラインで以下のコマンドを実行します。

```powershell
docker run -d -p 18080:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin --name keycloak jboss/keycloak
```
これにより、以下の通りKeycloakが構築されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/375883/d89e190e-c8c3-e885-b569-8503fd1b5a12.png)

Docker DesktopのDashboard上でも確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/375883/3ba513c5-cd63-6104-dd59-27a876ded74a.png)

それぞれのオプションは以下のように対応します。

- pオプション: ポート
  - 例では18080ポートで起動
- eオプション: 環境変数
  - KEYCLOAK_USER, KEYCLOAK_PASSWORDはKeycloakの管理者ユーザーの設定
- nameオプション: コンテナ名

## Keycloakの管理画面から設定を行う
以下URLからKeycloakの管理画面にアクセスできます。
http://localhost:18080/auth/admin/
また、ファイアウォール等のネットワーク設定が適切であれば、ローカルネットワーク上の他の端末から、ローカルIPアドレスで接続してもらうことも可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/375883/0603e514-cb02-e9f6-2a40-3bfc09272c01.png)
docker run時に与えた`ID/password`でログインできます。先述の例では`admin/admin` です。

後は以下記事などを参考に、IdP側/SP側の設定を行ってください。
https://qiita.com/katakura__pro/items/1e65e0bde7fda75332a1

## 最後に
この記事で紹介したことは、Docker利用環境のセットアップと、公式KeycloakイメージからのKeycloakの立ち上げにすぎません。
が、IdPの構築、であったり、Keycloakの構築、というググり方をすると、Dockerを使わない結構めんどくさいやり方が出てくることが多いように感じました。
またDockerという言葉は知っていても、IdPの構築、と結び付けられなかったり、Docker環境を作るのが大変そうだな……と考えて諦める方もいるかと思い、一連の流れとして記事にいたしました。
参考になれば幸いです。

## 参考URL
https://qiita.com/katakura__pro/items/1e65e0bde7fda75332a1

https://qiita.com/tadayosi/items/7ad82652809b00abff59

https://developers.redhat.com/blog/2017/10/31/docker-authentication-keycloak/
Google スプレッドシートのQuery関数で列名にBYとするとPARSE_ERRORとなる

GoogleスプレッドシートのQuery関数でSELECTの列名にBYを記述とするとPARSE_ERRORとなったのでメモまで。

## PARSE_ERROR
```
=QUERY(A:BZ, "SELECT BY WHERE A = 'hoge')
```

## 解決
```
=QUERY(A:BZ, "SELECT `BY` WHERE A = 'hoge')
```
cloud9 でのRuby on Rails始め方

#0.はじめに
自分の学習記録として書いている為、ご指摘等ございましたら、教えていただけると幸いです。
この記事のゴールを以下に示します。

<ul>
<li>Ruby on RailsでYay! You’re on Rails!のページを開く
</ul>
※なお、初めのcloud9で「Create Environment」はすでに行なっているものとします。

#1.Ruby on Railsのインストール
ターミナルに以下コマンドを入力します。


```

$ printf "install: --no-document \nupdate: --no-document \n" >> ~/.gemrc

$ gem install rails -v 5.2.4
```

これでRuby on Railsのインストールは完了しました。

#2.新規アプリケーションの作成

```
$ rails new XXX
```
XXXの部分はご自身で好きなアプリケーション名を付けてください。

今回私はこのようにしました。

```
$ rails new demo_app
```

すると左側に沢山のファイルができていると思います。

#3.Yay! You’re on Rails!のページを開く(ゴール)
ゴールはもう少しです。
以下のようにして先ほど作ったディレクトリに移動をします。

```
$ cd XXX
//私の場合は、
$ cd demo_app
```
最後に、

```
$ rails s
```

を実行し、上部にある**preview→preview Running Application**を選択。
下のターミナルの右に小さく画面が出ていると思うので、**右端の□に↗︎がついたマークを押す**と、Yay! You’re on Rails!のページが開きます。

以上です。
#参考ページ
https://yu-nocode.com/wp/rails-1-%E3%80%90%E5%AD%A6%E7%BF%92%E3%81%AE%E7%9B%AE%E6%A8%99aws%E6%96%B0%E8%A6%8F%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E7%99%BB%E9%8C%B2%E3%80%81cloud9%E8%B5%B7%E5%8B%95%E3%80%81rails/

参考にさせていただきました。ありがとうございます。
gcloudコマンドでAPIキーを発行する方法


## APIキーについて

Google Cloud Platformの `APIとサービス` で発行するAPIキーについて。

![認証情報_–_API_とサービス_–_service-infra_–_Google_Cloud_Platform_と__env_sample_—_app__Dev_Container__poster-backend_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3377/781183ab-0a79-35d0-2f39-3280514efc83.png)

用途としては、Google Map APIとかでAPIキーが求められるとケースなどを想定

## コマンド

gcloudコマンドののalpha機能に `api-keys` というのが有るのでそれを使用する

```bash
$ gcloud alpha services api-keys create --display-name <表示名>
```

表示された `keyString` がAPIキーとなる

## 参考

https://stackoverflow.com/questions/60828348/can-i-create-gcp-api-keys-using-terraform
カテゴリー別一覧表示

include~は表示順を降順にしてます。
search以降は検索機能のなのでなくていいです。

```ideas.controller.rb
def index
    @idea2 = Idea.where({category_id: 2}).includes(:user).order("created_at DESC").search(params[:search])
    @idea3 = Idea.where({category_id: 3}).includes(:user).order("created_at DESC").search(params[:search])
    @idea4 = Idea.where({category_id: 4}).includes(:user).order("created_at DESC").search(params[:search])
    @idea5 = Idea.where({category_id: 5}).includes(:user).order("created_at DESC").search(params[:search])
end
```

```index.html.rb
<div class="category bg-success">あ</div>
  <% @idea2.each do |idea| %>
  <%= link_to idea.title, idea_path(idea.id), class: :card__title%>
  <% end %>

  <div class="category bg-success">い</div>
  <% @idea3.each do |idea| %>
  <%= link_to idea.title, idea_path(idea.id), class: :card__title%>
  <% end %>

  <div class="category bg-success">う</div>
  <% @idea4.each do |idea| %>
  <%= link_to idea.title, idea_path(idea.id), class: :card__title%>
  <% end %>
```
これでできました。
[SwiftUI] コード(ViewModelなど)からAlertを表示する方法

# 概要
SwiftUIでView以外のコードからAlertを表示する方法を調べました。
最前面のViewControllerからAlertControllerをpresentすれば良さそうです。

# 実装

```AppDelegate.swift

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    static var me: AppDelegate {
        return UIApplication.shared.delegate as! AppDelegate
    }

    /// 最前面のViewControllerを取得する
    /// https://stackoverflow.com/a/57169802/4791194
    /// https://stackoverflow.com/a/42580981/4791194
    func topController() -> UIViewController? {
        let keyWindow = UIApplication.shared.connectedScenes
                .filter({$0.activationState == .foregroundActive})
                .map({$0 as? UIWindowScene})
                .compactMap({$0})
                .first?.windows
                .filter({$0.isKeyWindow}).first
        var topController = keyWindow?.rootViewController
        while let presentedViewController = topController?.presentedViewController {
            topController = presentedViewController
        }
        return topController
    }
}
```

# 呼び出し例

```HogeViewModel.swift
let alert = UIAlertController(title: "title", message: "message", preferredStyle: .alert)
AppDelegate.me.topController()?.present(alert, animated: true, completion: nil)
```

# 参考

- https://stackoverflow.com/questions/40991450/ios-present-uialertcontroller-on-top-of-everything-regardless-of-the-view-hier/42580981#42580981
- https://stackoverflow.com/questions/57134259/how-to-resolve-keywindow-was-deprecated-in-ios-13-0/57169802#57169802

# 関連
- [SwiftUIでalertを表示するのに便利なExtension
](https://qiita.com/k-yamada-github/items/9319dd7fb51b682e1603)
Reactで複数のinputタグの変更を即座に反映する



結構むずい。Reactの一番めんどくさいところかもしれない。

どゆことかというとReactではformの入力内容をリアルタイムに反映してくれない。

```jsx
function UserFrom(props) {
  if (props.content === 'SignUp') {
    return (
    <UserFromContent onSubmit={props.submit}>
      <FormBlock>
        <label htmlFor="nickname">ニックネーム</label>
        <input type="text" name="nickname" id="nickname" value={props.user.nickname}/>
      </FormBlock>
      <FormBlock>
        <label htmlFor="email">メールアドレス</label>
        <input type="email" name="email" id="email" value={props.user.email}/>
      </FormBlock>
```

こんな感じの一見それっぽいフォームだと入力しても入力した文字がテキストとして画面上に出てこない。
これはinputタグのvalue属性がprops.user.nicknameとなっていることによる。これは親コンポーネントから渡されたデータがここに入りますよ

という意味。そしてこのporpsの変更は子コンポーネントから変更できない。なので以下のようにonChangeイベントで親コンポーネントに定義した関数を動かして親コンポーネントで定義したデータを書き換える必要がある。

```jsx
function UserFrom(props) {
  if (props.content === 'SignUp') {
    return (
    <UserFromContent onSubmit={props.submit}>
      <FormBlock>
        <label htmlFor="nickname">ニックネーム</label>
        <input type="text" name="nickname" id="nickname" value={props.user.nickname} onChange={props.change}/>
      </FormBlock>
      <FormBlock>
        <label htmlFor="email">メールアドレス</label>
        <input type="email" name="email" id="email" value={props.user.email} onChange={props.change}/>
      </FormBlock>
```

親コンポーネントでは以下のようにchange属性を子に付与している。これが子コンポーネントに渡されることで、onChangeイベントのハンドラーとして機能する。

```jsx
render () {
          <UserFrom content={this.props.content} submit={this.formSubtmi} user={this.state.user} change={this.updateForm}/>
   )
```

change属性でupdateFormというメソッドを動かす。その中身がこれ

```jsx
updateForm(e) {
    // ネストされたオブジェクトのuserまでアクセスしておく
    const user = this.state.user;
    console.log(user)
    console.log(e.target.name)
    console.log(e.target.value)

    // eventが発火したname属性名ごとに値を処理
    switch (e.target.name) {
        case 'nickname':
            user.nickname = e.target.value;
            break;
        case 'email':
            user.email = e.target.value;
            break;
        case 'password':
            user.password = e.target.value;
            break;
        case 'password_confirmation':
            user.password_confirmation = e.target.value;
            break;
        case 'avatar':
            user.avatar = e.target.value;
            break;
    }
    this.setState({
      user: user
    })
  }
```

## ポイント…Formのname属性に応じてstateの変化を分ける

今回はあくまでchange属性をフォーム全体に渡して、全てのinputタグのonChangeイベントに同じ関数を付与している。
よってonChangeが発火した入力欄ごとにstateに対して加える変更を分ける必要がある。

inputタグのname属性はe.target.nameで取れるので、e.target.nameの値をcase文で振り分けて、stateの中身を変更する。
stateの中身を変更するのはsetStateを使う必要があり、そのためにまずは変更前のstateのデータを変数化し、変数の中身を書き換え、書き換え後の変数でstateを更新する、というちょっと遠回りした処理が必要になる。


### 参考

https://qiita.com/bmf_san/items/2c68c1de6252c3a5ba7e
【Vue】引数（プロパティ名）なしのv-bindの意味。プロパティ名ありの場合との違い

Vueファイルでデータの受け渡しにv-bindを多用する。v-bindの基本形は`v-bind:プロパティ名="変数名"`（`:プロパティ名="変数名"`）だが、このプロパティ名（属性名）が省略された表記も存在する。

```vue:
v-bind="変数名"
```

これは、**複数の属性と値を一度に渡す**処理になる。


##引数（プロパティ）を省略して直接表記した場合の例

```vue:
<blog-post v-bind="post"></blog-post>

<script>
export default {
    data() {
      post: {
        id: 1,
        title: 'タイトル'
      }
    } 
}
</script>
```

　↓↑ 同じ

```vue:
<blog-post
  v-bind:id="post.id"
  v-bind:title="post.title"
></blog-post>
```

　↓↑ 同じ

```vue:
<blog-post
  :id="post.id"
  :title="post.title"
></blog-post>
```

 ↓ コンパイル結果

```vue:
<blog-post id="1" title="タイトル"></blog-post>
```

＞[Vue公式 オブジェクトのプロパティの受け渡し](https://jp.vuejs.org/v2/guide/components-props.html)



<br>
**▼通常の使い方**

```vue:例1
<a v-bind:href="url"> ... </a>

<script>
export default {
    data() {
      url: "https://example.com"
    } 
}
</script>
```


```vue:例２
<blog-post v-bind:title="post.title"></blog-post>

<script>
export default {
    data() {
      post: {
        id: 1,
        title: 'タイトル'
      }
    } 
}
</script>
```