OmniAICreator/Qiita-1.07M huggingface dataset:
railsチュートリアルコラム　テストを書くときの注意

コラム 3.3. 結局テストはいつ行えばよいのか
それではいつ、どんなふうにテストを行えばよいのでしょうか。この点を理解するために、テストを行う目的をもう一度確認してみましょう。著者は、テストには次の3つのメリットがあると考えます。

テストが揃っていれば、機能停止に陥るような回帰バグ (Regression Bug: 以前のバグが再発したり機能の追加/変更に副作用が生じたりすること) を防止できる。
テストが揃っていれば、コードを安全にリファクタリング (機能を変更せずにコードを改善すること) ができる。
テストコードは、アプリケーションコードから見ればクライアントとして動作するので、アプリケーションの設計やシステムの他の部分とのインターフェイスを決めるときにも役に立つ。
上の3つのメリットは、テストを先に書かなくても得ることができますが、それでもテスト駆動開発 (TDD) という手法をいつでも使えるようにしておけば、間違いなく多くの場面で役に立ちます。テストの手法やタイミングは、ある意味テストをどのぐらいすらすら書けるかで決まると言ってよいでしょう。たいていの開発者は、テストを書くのに慣れてくるとテストを先に書くようになります。その他にも、アプリケーションのコードと比べてテストがどのぐらい書きにくいか、必要な機能をどのぐらい正確に把握しているか、その機能が将来廃止される可能性がどのぐらいあるかによっても異なってくるでしょう。

こういうときのために、「テスト駆動」にするか「一括テスト」にするかを決める目安となるガイドラインがあると便利です。著者の経験を元に、次のようにまとめてみました。

アプリケーションのコードよりも明らかにテストコードの方が短くシンプルになる (=簡単に書ける) のであれば、「先に」書く
動作の仕様がまだ固まりきっていない場合、アプリケーションのコードを先に書き、期待する動作を「後で」書く
セキュリティが重要な課題またはセキュリティ周りのエラーが発生した場合、テストを「先に」書く
バグを見つけたら、そのバグを再現するテストを「先に」書き、回帰バグを防ぐ体制を整えてから修正に取りかかる
すぐにまた変更しそうなコード (HTML構造の細部など) に対するテストは「後で」書く
リファクタリングするときは「先に」テストを書く。特に、エラーを起こしそうなコードや止まってしまいそうなコードを集中的にテストする
上のガイドラインに従う場合、現実には最初にコントローラやモデルのテストを書き、続いて統合テスト (モデル/ビュー/コントローラにまたがる機能テスト) を書く、ということになります。また、不安定な要素が特に見当たらないアプリケーションや、(主にビューが) 頻繁に改定される可能性の高いアプリケーションのコードを書くときには、思い切ってテストを省略してしまうこともあります。
Sass 基礎文法　2

#はじめに
[Sass 基礎文法 1 はこちらをクリック願います。](https://qiita.com/raigakun/items/ea948962a2b00fffb3e5)
フロント実装を学んでいく上で、Sassを用いておりますので、用語等を中心に整理していきます。
もうすでにご存知の方、省略の仕方等ご存知でしたら、ご教授願います。

#Sassのファイル及びフォルダの役割
###①style.css
直接編集せず、sassコマンドを実行し、style.scssファイルを作成・更新する。

###②stylesheetsフォルダ　
全てのscssファイルを管理するフォルダ

###③style.scss
このファイルで全てのscssファイルを@importで読み込む

```qiita.scss
 例）@import "reset";  /*_reset.scssを読み込む */
```

```qiita.scss
@import "./config/variable"; /* configフォルダの中の_variable.scssを読み込む */
```           

###④_reset.scss
- ブラウザによって初めからcssがそれぞれのhtmlに設定されている。　
　→　そのCSSによって、意図しないデザインになってしまうことがある。

- そのようなことを防ぐために、初めにブラウザごとのCSSをすべてリセットする。
　→　このようにブラウザごとのCSSを打ち消すCSSのことをリセットCSSという。

###⑤configフォルダ
プロジェクト設定ファイルやscssで使用する変数を定義するファイルなどを管理するフォルダ

###⑥modulesフォルダ
モジュールを管理するためのフォルダ

- モジュールとは？
　

　→　いくつかの要素をまとめた部品の集合
　→　ヘッダー、フッターのような用途ごとに分けることができる。

###⑦venderフォルダ
ライブラリのファイルを管理するフォルダ

- ライブラリとは？

　　→　あらかじめcssが書かれたフォルダ

###⑧overrideフォルダ
venderフォルダに格納してある外部のライブラリを上書きするためのscssファイルを管理するフォルダ




#さいごに
日々勉強中ですので、随時更新します。
皆様の復習にご活用頂けますと幸いです。
【iOS】UIButtonに波紋エフェクトを付ける

Ripple effectが付いたUIButtonを紹介します。
![ripple.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272677/22a91d08-52d5-7170-acc1-b6b79d7b2410.gif)
# コード
タッチ発生時に座標を取り、円形のUIViewを拡大・うすめながら表示します。

```swift
import UIKit

class RippleButton: UIButton {
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        drawRipple(touch: touches.first!)
    }
    private func drawRipple(touch: UITouch) {
        let rippleView = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
        rippleView.layer.cornerRadius = 100
        rippleView.center = touch.location(in: self)
        rippleView.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
        rippleView.backgroundColor = UIColor(red: 0/255, green: 0/255, blue: 0/255, alpha: 0.4)
        addSubview(rippleView)
        UIView.animate(
            withDuration: 0.5,
            delay: 0.0,
            options: UIView.AnimationOptions.curveEaseIn,
            animations: {
                rippleView.transform = CGAffineTransform(scaleX: 1, y: 1)
                rippleView.backgroundColor = .clear
            },
            completion: { (finished: Bool) in
                rippleView.removeFromSuperview()
            }
        )
    }
}
```

# 使い方
RippleButtonを使うだけです。
Storyboardから使う場合は、UIButtonを置いたあとにカスタムクラスを設定して下さい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272677/ab553881-749c-28fb-ec74-c546e6320d29.png)
なお、以下のようにボタンを角丸などにする場合は`clipsToBounds = true`を設定しないと波紋がはみ出ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272677/b9b49673-682d-4c37-c653-53b2bb06a0ff.png)
【Google Maps JavaScript API】「地図を移動させるには指２本で操作します」の解除方法

## はじめに
**Google Maps JavaScript API**を使っていると、スマホでは**「地図を移動させるには指２本で操作します」**が出てしまいます。

個人的には邪魔:weary:と感じるこの機能を**解除して、指１本スクロールを取り戻す方法**を残します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483292/d569f8e9-78c3-de12-672b-1b1633f3c62c.png)


## 環境
```yaml
iOS: 13.3.1
```
## 結論: `gestureHandling: 'greedy'`を追加
※元のhtmlなどには触れず、ピンポイントでコードを抽出していますのでコピペでは動きません。ご了承下さい。:bow_tone1:

```javascript:sampleMap.js
const map = new google.maps.Map(document.getElementById('map'), {
          gestureHandling: 'greedy', //これを追加
          center: {lat: 40.674, lng: -73.945},
          zoom: 12,
        });
```

これを追加することで、過去デフォルトであった**指１本スクロール**が適用されます。

## おわりに
最後まで読んで頂きありがとうございました:bow_tone1:

どなたかの参考になれば幸いです:relaxed:

## 参考にさせて頂いたサイト（いつもありがとうございます）
- [Controlling Zoom and Pan  |  Maps JavaScript API  |  Google Developers](https://developers.google.com/maps/documentation/javascript/interaction)
railsチュートリアル３章　間違ってrails gとかしたときに元に戻す方法

コラム 3.1. 元に戻す方法
どれほど十分に気を付けていたとしても、Railsアプリケーションの開発中に何か失敗してしまうことはありえます。ありがたいことに、Railsにはそのような失敗をカバーする機能がいくつもあります。

一般的なシナリオの1つは、生成したコードを元に戻したい場合です。例えばコントローラを生成した後で、もっといいコントローラ名を思い付き、生成したコードを削除したくなった場合などです。リスト 3.6のように、Railsはコントローラ以外にも関連ファイルを大量に生成するので、生成されたコントローラファイルを削除するだけでは元に戻りません。自動生成されたコードを元に戻すためには、新規作成されたファイルを削除するだけではなく、既存のファイルに挿入されたコードも削除する必要があります (実際、2.2や2.3でも説明したように、rails generateを実行するとルーティングのroutes.rbファイルも自動的に変更されるので、これも元に戻さなくてはなりません)。このようなときは、「generate」という言葉に因んで、rails destroyというコマンドを実行することで元に戻すことができます。例えば次の2つのコマンドは、自動生成と、それに対応する取り消し処理の例です。

  $ rails generate controller StaticPages home help
  $ rails destroy  controller StaticPages home help
なお第6章でも、次のようにモデルを自動生成する方法を紹介します。

  $ rails generate model User name:string email:string
モデルの自動生成についても、同様の方法で元に戻すことができます。

  $ rails destroy model User
(上のコマンドからわかるように、モデル名以外の引数は不要です。その理由については第6章で説明します)。

また、第2章でも簡単に紹介しましたが、マイグレーションの変更を元に戻す方法も用意されています。詳細は第6章で説明しますが、簡単に紹介すると、まずdb:migrateでデータベースのマイグレーションを変更します。

  $ rails db:migrate
元に戻したいときは、db:rollbackで1つ前の状態に戻します。

  $ rails db:rollback
最初の状態に戻したいときは、VERSION=0オプションを使います。

  $ rails db:migrate VERSION=0
既にお気付きの方もいると思いますが、マイグレーションは逐次的に実行され、それぞれのマイグレーションに対してバージョン番号が付与されます。したがって、上記の0を別の数字に置き換えることによって、指定したバージョンの状態に戻すことができます。

開発中に袋小路に迷い込んでしまった場合でも、これらの機能を使えば元の状態を復元できます。
今日のスクリプト: dhist，dcd

## ◆はじめに
　こんにちは．だんぷてぃ・ダイです．世の中の管理業務はスクリプトでほぼできんじゃね？と思い込んで30年，使い捨てのシェルスクリプトやsedやawkプログラムを何百と書き倒してきました．このシリーズはその中から「これ役に立つんじゃね？」と思ったものをお届けしていきます．
　※おいらは「C-Shell(tcsh)使い」です．なので，Bashについてはあまり自信がありません．できる限り両方カバーするつもりですが…
　　
　今回のは正確にはスクリプトではなくエイリアスです．ディレクトリ移動(cd)した履歴を記録しておき，履歴番号でそのディレクトリに移動，というシロモノです．

## ＄dhist,dcdのアイデア
　change dir(cd)を繰り返していると，何回か前のディレクトリに行きたいことがありませんか．私はあります．ありまくります．

　cdしたら移動前の場所を記録しておいて，それを参照したり過去に移動したディレクトリに一発で移動できると便利だなぁ．
　
　次のようなコマンドです．
>　コマンド：　使い方
>　---------------------------
>　dhist　：　引数なし．番号付きでヒストリーをリスト表示
>　dcd [num]　：　引数1個．ヒストリーの番号でそのディレクトリにcd


## ＄準備作業あり
　上のコマンドをシェルのaliasで実装しますが，あらかじめやっておく作業があります．

1. ~/.dhist という空ファイルを作成しておきます．
    
    ```
    $ touch ~/.dhist
    ```
   .dhistファイルはcdの履歴を入れるファイルです．これがないとシェル様に怒られます(ファイルがなければ勝手に作るプロセスを入れればいいんです．が，エイリアスの中で例外処理するが面倒で．1回作ればいいんですから(^^))．
2. 行番号をつけてファイルの中身を表示するコマンドを用意します．今回は自作スクリプト "num" を使います．簡単なawkスクリプトです．  

    ```plain
    #!/usr/bin/awk -f
      { printf("%4d %s\n",FNR,$0) }
    ```
    スクリプトの中身をaliasに入れ込んでもいいのですが，面倒で(^^)[^smalltool]．

本体を以下に説明します．

## ＄スクリプト本体
　私は今も昔もC-Shell(tcsh)使いです．なので，実装したのはC-Shellのエイリアスです．が，Born-Shell(bash)でもできるので後述します．

###<1> csh版
C-Shell版はaliasだけで完結します．

```plain
alias cd   'echo $cwd >> $HOME/.dhist;chdir \!*;echo $cwd''
alias dhist 'num $HOME/.dhist|tail -20'
alias dcd   'cd `tail -n +\!* $HOME/.dhist|head -1`'
```

履歴サイズは20にしていますが好きに変更して下さい[^histsize]．中身は読んでいただければわかります．が，念の為このaliasの解説は後述します．

###<2> bash版
bashのエイリアスは引数を受け付けられない[^noarg]ので，面倒だけどfunctionで関数を定義します．aliasはこんな感じ．

```plain
alias dhist='num $HOME/.dhist|tail -20'
alias cd='/bin/pwd >> $HOME/.dhist;\cd $@'
```

で，dcd関数は3行です．

```plain
# cd from dir history
　dcd(){
   \cd $(tail --lines=+$1 ~/.dhist|head -1)
　}
```

※ご存知ない方に：aliasは特に別ファイルを用意する必要はなく，~/.bashrcに書けばOKです．これを有効にするにはsourceします．

```plain
$ source ~/.bashrc
```

※使い方はどちらのシェルも同じです．

>% cd hogedir
> 　→ cdは特に意識せずに使って下さい．
>　　※cshのpushd/popdを使うと記録されません．
>% dhist
>052 /hoge/dir/work
>053 /home/mydir
>054 /home/mydir/down
> ......ズラズラ
>071 /home/mydir
>　→ 過去にcdしたディレクトリを番号付きで20行表示．
>% dcd 52
>/home/dir/work
>　→ 履歴5番目のディレクトリに移動．

私にとってはめちゃ便利です．

## ＄やっていること
大したことやってません．
1. cdの都度，今の場所を~/.dhistファイルに追加書出しておく
2. dhistではnumスクリプトに通して番号表示し，tailで20行抜き出し，．
3. dcdでは，tailで.dhistの中から指定された番号の行を指定し，
4. headでその1行だけを表示し，
5. それをcdの引数に放り込む
これだけです．

お楽しみいただければ幸いです．

``` fix
　　だんぷてぃ・ダイ
　　2020-02-18 LastEdit
```
[^smalltool]: これこそUnixの思想，small tools(小さな単機能ツールを沢山用意して，それをつなげて大きな仕事をさせる)ですよ．その結果山のような使い捨てスクリプトが生まれてしまうわけですが(^^)．

[^histsize]: 改良して引数にするのもアリですね．

[^noarg]: これにはびっくりです．cshのエイリアスで何気なく使っていた，記述途中の引数指定が不可能とは．その代わりに「関数」をエイリアスの中に作ることで拡張性をもたせているわけです．cshが使われなくなってしまったのは関数の実装がないからだと言っても過言ではなでしょう．設計思想の違いですなぁ．
コピペで使える！！ブランチ名をコミット名に自動付与

## はじめに

コミットにチケット名入れるの自動化したので共有します。
たとえばこんな感じにします。

```
作業ブランチ
feature/issue/#9

コミットメッセージ
xxxの実装

↓コミット

コミット名
[#9] xxxの実装
```

## 準備

コミットにブランチ名を入れるために、git-hook機能を使います。
以下のコマンド実行してcommit-msgというファイルを作成します。

```
$ touch <repo>/.git/hooks/commit-msg
$ chmod +x <repo>/.git/hooks/commit-msg
```

commit-msgファイル編集
スラッシュ区切りの最後の文字列を入れてるだけです。
アンダーバーとかに変更したい場合は任意に変更してください。  

```bash
#!/usr/bin/env ruby
message_file = ARGV[0]
message = File.read(message_file, :encoding => Encoding::UTF_8)
# remove prefix issue number like [#1234] from COMMIT_EDITMSG
message = message.sub(/^\[#[0-9A-Za-z_].*\]/, "")
# remove comment
message = message.gsub(/^#(?! ------------------------ >8 ------------------------).*\n|^\n/, "")
if message =~ /(?=\A)# ------------------------ >8 ------------------------\n/
  puts "An empty message aborts the commit."
  exit 1
end
# get last path of current branch
current_branch = `git branch | grep '*'`.chomp.sub('* ', '')
current_branch = current_branch[current_branch.rindex("/")+1 .. current_branch.length] # スラッシュ区切りにしてるが任意の文字に変えることも可能
# add [last path of current branch] to commit message
newmessage = "[#{current_branch}] #{message}" # コミットメッセージ作成
File.write(message_file, newmessage)
```

以上です
うっかりサーバーをシャットダウンさせないようにする方法

# 方法
１．対象サーバーにログインしてコマンドプロンプトを起動し、以下コマンド(レジストリ変更)を実行。

`code`
reg add "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer" /v NoClose /t "REG_DWORD" /d "1"

２．一度サインアウトして再ログインする。

これにより、スタートメニューに「シャットダウン」が表示されなくなる。
【Riot.js】cdnで楽々Hello World

**古いバージョンのRiotを使っていたので、[【Riot.js】【訂正版】cdnで楽々Hello World](https://qiita.com/wafuwafu13/items/d40f3f972a4e8b702f78)を書きました。**

[Riot.js](https://riot.js.org/ja/documentation/)の勉強を始めました。
npmやwebpackを使って学習する方法もありますが、エラーが出たり詰まるポイントが多いのでcdnを使って学習します。
ちなみに今回使うRiot.jsのcdnは以下です。
``<script src="https://cdn.jsdelivr.net/npm/riot@3.6/riot+compiler.min.js"></script>``


```html
<html lang="ja">

 <head>
    <meta charset="UTF-8">
    <title>Riot sample</title>
    <script src="https://cdn.jsdelivr.net/npm/riot@3.6/riot+compiler.min.js"></script>
 </head>

 <body>

    <greet></greet>

    <script type="riot/tag">
    <greet>
        <h1>{word}</h1>
        this.word = 'Hello World'
    </greet>
    </script>

    <script>
      riot.mount('greet')
    </script>
 </body>
 
</html>
```

これでhtmlファイル1枚でHello Worldできます！楽チン！
WordPress初心者がカスタムするために用語を簡単にまとめてみた

WordPress初心者がカスタムしていくためには聞き慣れない用語が多くて辛いので簡単にまとめてみようと思います。

今回の用語↓

  * 投稿タイプ
  * カスタム投稿タイプ
  * タクソノミー
  * カスタムタクソノミー
  * カスタムフィールド

# 投稿タイプ
投稿タイプ（post type）とは、WordPress の posts テーブル内で管理されている様々な構造を持つデータ。
ネイティブ（ビルトイン）投稿タイプには、投稿（post）、固定ページ（page）、添付ファイル（attachment）、更新履歴（revision）そして、ナビゲーションメニュー項目（nav-menu-item） がある。

# カスタム投稿タイプ
カスタム投稿タイプとは、自分で新たに作れるオリジナルの投稿タイプ。
`register_post_type()` 関数で定義できる。
カスタム投稿タイプを使うと、ユーザーが簡単にポートフォリオ、プロジェクト、ビデオライブラリー、ポッドキャスト、引用文、チャットなどを投稿・管理できるようになる。

# タクソノミー
タクソノミー は物事を分類する方法。
WordPress では2つの組み込みタクソノミー、「カテゴリー」と「タグ」がある。
タクソノミーは投稿やカスタム投稿タイプを詳細な分類を支援する。

# カスタムタクソノミー
カスタムタクソノミーとは、自分で新たに作れるオリジナルのタクソノミー。
情報の分類を自由に作っていける機能。
`register_taxonomy()` 関数で定義できる。

# カスタムフィールド
WordPressの投稿フォームには、デフォルトで「タイトル」と「本文」の2つがある。
ここに入力する情報を追加できるのがカスタムフィールド。

# 参考
[WordPress用語集](https://wpdocs.osdn.jp/%E7%94%A8%E8%AA%9E%E9%9B%86)
【React】TypeError: Cannot read property '＊＊＊' of undefined の対処法

今回は練習のためにreactでTodoリストを作成していた時にハマったエラーと対処法をメモしときたいと思います。

#TypeError: Cannot read property '＊＊＊' of undefined
これはリストの削除機能を作る時にハマりました。

そのまま翻訳すると「未定義のプロパティ「＊＊＊」を読み取れません」といった感じなんですが、これはちゃんと定義されていないことが問題なようなのでアロー関数で書いてあげれば治りました。

 

```test.js
removeTask(text){
        var updatedTasks = this.state.tasks;
        updatedTasks.splice(updatedTasks.indexOf(text), 1);
        this.setState({tasks: updatedTasks});
}
```

これを以下に変更。


```test.js
removeTask=(text)=>{
        var updatedTasks = this.state.tasks;
        updatedTasks.splice(updatedTasks.indexOf(text), 1);
        this.setState({tasks: updatedTasks});
}
```
 
こんな感じでちゃんと渡してあげたらスッと治りました。
 
 
#Cannot read property 'map' of undefined
このエラーはほとんど普通にタイプミスです。
私の場合は「var tasksList=[];」を「tasks=tasksList」に定義し直していたのを忘れて「tasksList」で進めてしまっていたのでエラーが出たといった感じでした。

 

 

#まとめ
どちらもしょうもないミスなんですが、結構ハマった時間が長かったのでもし困っている方の助けになれたら嬉しいです。
Cloud Cost(AWS,OCI)

AWSとOCIを使用している時に、どっち使うか迷った時用メモ

各サービスの比較マッピングはOracleが下記ページにまとめてくれている。
https://www.oracle.com/cloud/iaas/cloud-service-mapping.html

支払い方法での主な違い
- AWSはリザーブインスタンス価格がある
- OCIはオンデマンドとMonthly Flexの２タイプある
- AWSはリージョンによって価格が異なる、OCIは全リージョン同一価格

コスト計算用サイト
- AWS:[Simple Monthly Calculator](https://calculator.s3.amazonaws.com/index.html)
    - 2020/06/30にAWS Pricing Calculatorに変わる予定
- OCI:[Cloud Cost Estimator](https://www.oracle.com/cloud/cost-estimator.html)

## Object Storage
ストレージ量のみ記載。リクエストやデータ転送量は公式を参照してください。
### AWS
https://aws.amazon.com/jp/s3/pricing/

| S3(標準)   | ドル | 円($1=120円)|
|:--:|:--:|:--:|
|最初の50TB/月|0.025USD/GB| 3 |
|次の450TB/月|0.024USD/GB| 2.88|
|500TB/月以上|0.023USD/GB| 2.76

### OCI
https://www.oracle.com/cloud/ucpricing.html

|Object Storage|ドル | 円($1=120円)|
|:--:|:--:|:--:|
|最初の10GB無料分以降|$0.0255/GB| 3.06|

## NW

### AWS
インターネットからAWSへの通信は無料(IN)
同じAZのEC2とEC2通信は無料。EC2とS３間は同じリージョンで無料
EIPはアタッチしているインスタンスが稼働している場合無料。

### OCI
インターネットからOCIへの通信は無料(IN)
OCIからインターネットへの通信は10TB/月は無料(OUT)
予約済パブリックIPは無料
  - エフェメラル・パブリックIPでもインスタンスの停止(Not 削除)では変わらない。
https://docs.oracle.com/cd/E97706_01/Content/Network/Tasks/managingpublicIPs.htm

## Compute
インスタンスサイズによって違いがあるので料金はそれぞれのサイトで要確認

### AWS

https://aws.amazon.com/jp/ec2/pricing/

### OCI

https://www.oracle.com/cloud/compute/pricing.html

>2020/4/15 release
仮想マシン（VM）インスタンスの最低1分
ベアメタルインスタンスの最低1時間
それ以降、使用量は1秒単位で請求されます。
テーマに正しくjsファイル、スタイルシートを読み込ませる方法

## 結論
cssファイルを読み込むにはwp_enqueue_style、
jsファイルを読み込むにはwp_enqueue_scriptを使用する。

```php:functions.php
function test_scripts() {
  wp_enqueue_style( 'main-style', get_template_directory_uri().'/css/main.css' ); // cssファイルを読み込む
  wp_enqueue_script( 'main-script', get_template_directory_uri().'/js/main.js'); // jsファイルを読み込む
}

add_action( 'wp_enqueue_scripts', 'test_scripts' );
```

## 使用方法
```php
wp_enqueue_style( $handle, $src, $deps, $ver, $in_footer );
wp_enqueue_script( $handle, $src, $deps, $ver, $in_footer );
```
wp_enqueue_style , wp_enqueue_scriptとも関数の規則は同じです。

### $handle
スタイルの名前。
ユニークでないければならない。
既存の名前を入れると、キューに追加されない。

### $src
スタイルシート、スクリプトファイルまでのURL。
外部ファイルを読み込むことも可能。その場合は絶対パスで入力する。

ちなみに内部ファイルを読み込む際、以下の関数は頻出度が高く、覚えておくこと必須。

```
get_template_directory_uri(); // 親テーマのディレクトリを取得
get_stylesheet_directory_uri();　// 子テーマのディレクトリを取得
get_stylesheet_uri(); // 子テーマのstyle.cssを取得
```
詳しくはcodexを見ると良い。
わかりやすく、書かれている。

[関数リファレンス/get template directory uri](https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/get_template_directory_uri)
[関数リファレンス/get stylesheet directory uri](https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/get_stylesheet_directory_uri)
[関数リファレンス/get stylesheet uri](https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/get_stylesheet_uri)

### $deps
このスタイル・スクリプトを読み込む前に、読み込ませたいスタイル・スクリプトの$handleを配列形式で記入する。

### $ver
バージョン番号を指定できる。デフォルトはfalseになっている。

### $in_footer
デフォルトはfalse。
trueの場合、\</body\> 終了タグの前に配置。
falseの場合、\<head\> に置かれる。

## 終わりに
正直、codexを見れば全て書かれている。
[関数リファレンス/wp enqueue style](https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/wp_enqueue_style)
[関数リファレンス/wp enqueue script](https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/wp_enqueue_script)
しかし、いちいち開くのが億劫だ。高頻出関数の引数くらい覚えておきたいという願いを込めてメモ✍️
github用語

<h1>gitとは</h1>
プログラムなどを記述したソースファイルを管理するための「バージョン管理システム」のこと。Gitを使うことで、複数人で開発したソースファイル一式を一元管理することが出来る。

<b>・ファイルの変更履歴を管理
・過去のバージョンに戻せる
・さまざまなファイルを管理できる
・チームで作業を共有できる</b>

<h1>githubとは</h1>
Gitのリポジトリを「Web上のGUI操作でグラフィカルに扱うことが可能」なツール。
(リポジトリとは、ソースファイルが格納されたディレクトリなどを保存する箱のようなもの。)

GitHub上で管理しているプロジェクトをメンバーごとにコピーしてローカルで作業を行い、修正したファイルをGitHub上で共有することが可能。
GitHubでは、「ローカルリポジトリ」「リモートリポジトリ」と言った概念がある。

<b>
・自分のPCで作業する「ローカルリポジトリ」
・GitHubなどでサーバ上で管理する「リモートリポジトリ」</b>


<h1>Git・Github用語</h1>

<b>リポジトリ(repository)</b>
いわゆる貯蔵庫です。システムの開発プロジェクトに関連するデータの一元的な貯蔵庫を意味します。一種のデータベースで、各工程の様々な情報を管理することができる。
***
<b>ローカルリポジトリ(local repository)</b>
Gitのリポジトリはローカルリポジトリとリモートリポジトリに分けられます。ローカルリポジトリは自分のマシン内に作られ、ワーキングツリーが所属するリポジトリのこと。
***
<b>リモートリポジトリ(remote repository)</b>
自身の手元側にあるローカルリポジトリに対して、外部にあるリポジトリのことを指します。サーバなどネットワーク上にあるリポジトリもそれに当たります。公開、共有がスムーズなので複数人での開発に使われたり、個人開発でもネットワーク状にデータを保存したい時、共有したい時に使えます。
***
<b>フォーク(fork)</b>
forkはGitHubが提供する機能のひとつです。fork は他の開発者のリポジトリを github上でclone(クローン）します。また、forkは、fork元への貢献を前提とします。開発を援助する前提の上で使う必要があります。

食器のフォークをイメージするとわかるように、フォーク元とフォークしたリポジトリはそれぞれ独立しており、交わることなくそれぞれの道を歩みます。
***
<b>クローン(clone)</b>
クローンとはリモートリポジトリを手元のマシンの指定した場所に複製します。
***
<b>イニット(init)</b>
リポジトリを新規作成、空のレポジトリが作成されます。また、すでに存在するリポジトリの初期化をしたい場合にも使われます。
***
<b>ワーキングツリー(working tree)</b>
Gitの管理下に置かれた、自分が実際に作業をしているディレクトリのことです。作業ディレクトリ、ワークツリー、様々な呼ばれ方をします。
***
<b>インデックス(index)</b>
コミットする前に更新内容の一時的な保存をする場所のことで、ステージとも呼びます。
***
<b>アド(add)</b>
ワーキングツリーにあるファイルの更新内容を、インデックスに反映するためのコマンドです。コミットする対象を登録する作業です。
***
<b>コミット(commit)</b>
追加・変更したファイルをリポジトリに記録します。ゲームのセーブみたいな感じです。
***
<b>コミットメッセージ(commit message)</b>
コミットした内容を記述します。基本的に必須で書いて行きます。変更内容の要約、変更した理由（内容、詳細）などを記述します。
***
<b>ヘッド(HEAD)</b>
今いるブランチの最新のコミットの代名詞を指します。デフォルトではmasterの先頭を表し、HEADが移動することで、使用するブランチが変更されます。
***
<b>プル(pull)</b>
リモートリポジトリのコミットをローカルリポジトリに送り込みます。データのダウンロードのようなものです。
***
<b>ブランチ(branch)</b>
プロジェクトを分岐させることにより、プロジェクト本体に影響を与えずに開発を行える機能です。ブランチにより、不具合が発生した場合も対応しやすく、１つのプロジェクトを同時進行で作業ができます。
***
<b>マスターブランチ(master branch)</b>
プロジェクトの本流のブランチで、リポジトリに最初のコミットを行うと、masterという名前のブランチを作成されます。その後のコミットはブランチを切り替えるまでmasterブランチに追加されていきます。
***
<b>マージ(merge)</b>
加えた修正を統合する作業をします。変更を加えたブランチを元のブランチにマージして修正します。
***
<b>リセット(reset)</b>
最新のコミットを取り消します。また、ステージされたファイルを取り消します。
***
<b>リバート(revart)</b>
取り消したいコミットに対して、それを打ち消すようなコミットを新しく作成します。ただ、既存コミットの履歴が消えるわけではなく、コミットログには残っています。
***
<b>リベース(rebase)</b>
指定したコミットをブランチを変えて作り直すことができます。また、コミットをひとまとめにしたりして、ログを綺麗にするコマンドです。
***
<b>チェリーピック(cherry-pick)</b>
(これは初心者用語としてはどうかと思いますがσ(^_^;)他のブランチのコミットを自分が今いるブランチに反映させることができます。マージはすべてのコミットが取り込まれますが、チェリーピックは選択したコミットのみ取り込むことができます。
***
<b>スタッシュ(stash)</b>
コミットせずに変更を退避したいときに使います。あるブランチで作業中だけど、いますぐやりたいことができた時、作業するブランチを間違えてしまった時にコミットしていない変更を一時退避することができます。
***
<b>コンフリクト(conflict)</b>
Gitの場合同じファイルの同じ場所への変更が同時にある時に生じるエラーのことを言います。
***
<b>フェッチ(fetch)</b>
リモートリポジトリの最新の履歴の取得を行います。取得を行うのみなので、マージが自動で行われないのがpullとの違いです。
***
<b>チェックアウト(checkout)</b>
今作業しているブランチから出て、他の作業ブランチで作業をしたい場合に使用するコマンドです。
***
<b>プッシュ(push)</b>
ローカルリポジトリの内容をリモートリポジトリに反映させます。
***
<b>プルリクエスト(pull request)</b>
開発者のローカルリポジトリでの変更を他の開発者に通知するGitHubの機能です。会社やチームでコードレビューするときに使います。
jqueryとは何か？

<h1>jqueryについて</h1>
jQueryとは、JavaScriptのライブラリ（便利な機能を使いやすくしたもの）の一種。JavaScriptの書き方などを簡単にすることが出来る、JavaScriptで作成されたライブラリ。

<h1>できること</h1>
- アニメーションをつける。
- 時間によってページの色を変更する。
- ユーザーの動作によってCSSを変更してレイアウトを変える。

<b>作れるようになるといいもの</b>
●ハンバーガーメニュー　
●アコーディオン
●スライダー
●スムーススクロール
●ドロップダウン
●ドロワーメニュー

<h1>使い方</h1>
主に2つのやり方がある。

<b>①jQueryのサイトを開いて、ダウンロードして使う</b>
HTMLファイルにダウンロードしたjQueryファイルを紐づける。
typeはなくてもいい。違いがない。

```html
<head>
<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
</head>
```
<b>②jQueryをダウンロードせずに、他のサーバーにあるものを使用する</b>
GoogleやMicrosoft、jQuery本家などのサーバーが配信しているjQueryを使う。
CDN（コンテンツデリバリネットワーク）アクセス元から近いサーバーと通信をとって高速化をはかるものです。

<b>google</b>

```html
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
```

<b>jquery</b>

```html
<script src="https://code.jquery.com/jquery-3.1.1.js"></script>
```

<h1>記述場所</h1>
・読み込み方法---head内
・記述方法---＜/body＞の直前 　<b>←なぜ？</b>


<b>・Webページの表示速度を早くする</b>
javascriptを読み込んでいる間は、HTMLファイルの読み込みが止まってしまう為、
HTMLファイルをほぼ全部読み込んで表示された後javascriptを読み込む方が表示速度が早くなります。

<b>・並列ダウンロードの妨げになってしまう</b>
これは1.の「表示速度を早くする為」の1つを掘り下げた感じになるかもしれませんが、ブラウザ側では表示速度を上げるために、サーバーから画像等をダウンロードする際には1個1個ダウンロードするわけでなく、一度に何個かダウンロードしています。その何個か同時にダウンロードするということが出来なくなってしまう為、結果表示速度も遅くなってしまいます。

読み込み位置で実行速度にあまり差はない。

***
scriptタグの記述場所は別にどこでも構わないが、bodyタグの終端に記述する理由は以下のような理由がある。

●javascriptファイルを読み込んでいる間は、HTMLファイルを読み込まないため、ページのレンダリングを行わせてからjavascriptファイルを読み込むことで表示速度を早くする。

●CSSはheadタグ中に、javascriptはbodyタグの下にまとめて記述することでわかりやすくなる。
ただし、HTMLが解析される前に実行されるべきjavascriptファイルなどはheadタグ内に記述するべきだと思います。
headタグ内にscriptタグを置いたときには、javascriptファイルが最初に読み込まれるので、そのjavascriptファイルのサイズが巨大だった場合、ページの表示に時間がかかることになります。
***

<h1>外部ファイル</h1>
```html
<head>
<script type="text/javascript" src="〇〇〇.js"></script>
</head>
```

```javascript
alert("Hello World!") これを最初に記述する。
```

***
<h1>CDNとダウンロードについて</h1>
|jquery|メリット|デメリット|
|-----------------|------------------|:------------------|
|CDN|・自分のサーバーにアップロードする必要がない<br>・他のサイトでキャッシュされている可能性がある|・CDNサーバーに不具合があると読み込めない|
| ダウンロード    |オフラインでも動作させることができる|最新バージョンに変更したいときに毎回アップロードしなければならない|

<h1>タイプの違い</h1>
| タイプ       |       説明 | 
|------|:------------------------|
|.js|  ソースが見やすく整形されているタイプです。通常は使用しません。|     
|.min.js| ファイルサイズを小さくすることを目的にソースから改行やスペース等が取り除かれているタイプです。通常これを使用します。|      
|.slim.js|3.x系のみ存在するタイプです。AnimationやAjax等の機能を省いた軽量タイプです。ソースは整形済みです。| 
|.slim.min.js|.slimタイプのソース未整形タイプです。slimタイプを使う場合はmin付きのこちらを使用します。|        

***
レスポンシブ



<h1>レスポンシブについて</h1>
<b>「viewport」の指定をする</b>

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

<b>フォントサイズの指定をする</b>

横並びのコンテンツを縦並びにする
画像だけではなく、サイト全体的に可変を意識してサイズを％で指定します。

```
html {
    font-size: 62.5%;　　/*基準フォントサイズを10pxにするという意味*/
}

body {
    font-size: 14px;
    font-size: 1.4rem;
}

/*pxとremの両方を指定していますが、
 remを利用できないブラウザを考慮してpxとrem両方で指定しています。*/

h1 {
font-size: 4rem; /* 40px */
}

p {
font-size: 1.4rem; /* 14px */
}
```

<b>メディアタイプ</b>

```
screen（一般的ディスプレイ）、projection(プロジェクター)、
print(プリンタ)、tv(テレビ)、all(すべて)など
```

<b>記述の仕方(例)</b>

```
@media メディアタイプ { /*そのメディアでのみ有効となるスタイル*/ }
小～大の順番(モバイルファースト)　大〜小の順番(デスクトップファースト)で記載しなければならない。
携帯、タブレット、PCのブレイクポイントの分岐が必要である。
```
```
@media screen and (min-width:480px) { 
/*　画面サイズが480pxからはここを読み込む　*/
}

@media screen and (min-width:768px) and max-width:1024px) {
/*　画面サイズが768pxから1024pxまではここを読み込む　*/
}

@media screen and (min-width:1024px) {
/*　画面サイズが1024pxからはここを読み込む　*/
 
}

```
TerraformでLambdaのCloudWatchイベントトリガを無効にする

Lambda の CloudWatch イベントトリガーを無効にしたい時、コンソールからならここで操作出来ますが、

![Screenshot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130580/83b4067c-0ec0-0716-b616-f26e206ba0d8.png)


Terraform からどうやるのかと思ったら `aws_lambda_permission.action = "lambda:DisableInvokeFunction"` にする必要がありました。 `enable/disable` みたいなスイッチではないので気づきませんでした。
`aws_cloudwatch_event_rule.is_enabled` ではないので気をつけましょう。

```terraform

resource "aws_lambda_permission" "allow_to_invoke_func" {
  statement_id  = "AllowExecutionFromCloudWatch"
  function_name = "${aws_lambda_function.func.function_name}"
  principal     = "events.amazonaws.com"
  source_arn    = "${aws_cloudwatch_event_rule.minutely.arn}"

  /* 無効にする場合は "lambda:DisableInvokeFunction" を指定する */
  /* action        = "lambda:InvokeFunction" */
  action        = "lambda:DisableInvokeFunction"
}

resource "aws_cloudwatch_event_rule" "minutely" {
  name                = "minutely"
  schedule_expression = "rate(1 minute)"
}

resource "aws_cloudwatch_event_target" "invoke_func_minutely" {
  rule      = "${aws_cloudwatch_event_rule.minutely.name}"
  target_id = "invoke-func"
  arn       = "${aws_lambda_function.func.arn}"
}

resource "aws_lambda_function" "func" {
  filename         = "${data.archive_file.function_zip.output_path}"
  function_name    = "${var.app_name}-function"
  role             = "${aws_iam_role.lambda_exec.arn}"
  handler          = "index.handler"
  source_code_hash = "${data.archive_file.function_zip.output_base64sha256}"
  runtime          = "ruby2.5"
}
```
Google Cloud Platform (GCP)サービスの正式名称・略称・読み方まとめ#4(コンピューティング)

Google Cloud Platform (GCP)のサービスで正式名称や略称はともかく、読み方がわからずに困ることがよくあるのでまとめてみました。


クラウド コンピューティング サービス  |  Google Cloud
https://cloud.google.com/?hl=ja


## Amazon Web Services (AWS)のまとめはこちら！

Amazon Web Services (AWS)サービスの正式名称・略称・読み方チートシート - Qiita
https://qiita.com/kai_kou/items/cb29d261c8acc49fd22a

Amazon Web Services (AWS)サービスの正式名称・略称・読み方まとめ #1 (コンピューティング) - Qiita
https://qiita.com/kai_kou/items/a6795dbab7e707b0d1a6


## まとめルール

まとめルールについては下記を参考ください。

Google Cloud Platform (GCP)サービスの正式名称・略称・読み方まとめ#1(AI と機械学習/AI ビルディング ブロック) - Qiita
https://qiita.com/kai_kou/items/fa930eef23470c2f8f0b


## 概要について

サービス一覧ベージの概要を引用しています。

プロダクトとサービス  |  Google Cloud
https://cloud.google.com/products?hl=ja#product-launch-stages


間違いや、こんな呼び方あるよーなどありましたらコメントお願いします！


## Compute - コンピューティング

### Compute Engine

スケーラブルで高性能な VM。

- 正式名称: Compute Engine
- https://cloud.google.com/compute/
- 読み方: コンピュート エンジン
- 略称: なし
- 俗称: GCE


### App Engine

アプリとバックエンド用のサーバーレス アプリケーション プラットフォーム。

- 正式名称: App Engine
- https://cloud.google.com/appengine/
- 読み方: アップ エンジン
- 略称: なし
- 俗称: GAE
  - 参照: [Google App Engine \- Wikipedia](https://ja.wikipedia.org/wiki/Google_App_Engine)


### Cloud GPUs

機械学習や科学技術計算、3D 表示に活用する GPU。

- 正式名称: Cloud GPUs
- https://cloud.google.com/gpu/
- 読み方: クラウド ジーピーユー
- 略称: なし
- 俗称: なし


### Migrate for Compute Engine

サーバーと VM の Compute Engine への移行（旧称 Velostrata）。

- 正式名称: Migrate for Compute Engine
- https://cloud.google.com/migrate/compute-engine/
- 読み方: マイグレート フォー コンピュート エンジン
- 略称: なし
- 俗称: なし
- 旧称: Velostrata


### Preemptible Virtual Machines

バッチジョブやフォールト トレラントなワークロードに最適な、有効期間が短い手頃な料金のコンピューティング インスタンス。
GCP 上の強化された仮想マシン。

- 正式名称: Preemptible Virtual Machines
- https://cloud.google.com/preemptible-vms/
- 読み方: プリエンプティブル バーチャル マシン
- 略称: Preemptible VMs
- 俗称: なし


### Sole-tenant nodes (単一テナントノード)

コンプライアンス、ライセンス、管理のニーズに対応する専用ハードウェア。

- 正式名称: Sole-Tenant Nodes
- https://cloud.google.com/sole-tenant-nodes/
- 読み方: ソール テナント ノード
  - 参考: Google、単一テナント・クラウドのベータ版開始――ユーザーは物理的マシンを専有できる | TechCrunch Japan https://jp.techcrunch.com/2018/06/08/2018-06-07-google-cloud-announces-the-beta-of-single-tenant-instances/
- 略称: なし
- 俗称: なし
継続的デリバリのための継続的テスト その２ 参加報告

# セミナー参加報告

「継続的デリバリのための継続的テスト：mabl Japan 2」に参加してきました
https://mabl-japan.connpass.com/event/166229/

# セッション内容

## "The Era of Intelligent Testing" “インテリジェントテストの時代”

### QAの世界で起きている様々な変化とイノベーション

今、QAが熱い。
様々なデバイス、アプリケーションなどあり変化がありテストは進化している

mablは DevOpsを導入して開発しており、mablのUIは、22人の開発で1週間で最大100コミットある。

パイプラインを動かし続けることは大事だが、テストがボトルネックとなっている
開発サイクルが短くなり新機能が速いペースででてくるのでテストする時間がない
自動化を高速、容易にすることが必要


データを集めて可視化して、どのようにテストするか（インサイト）、そのテストを最適化するインテリジェンス、そしてテスト結果を分析する本当の意味での自動化が必要になってくる。

* 可視性
単に地図（データ）

* インサイト
案内サイトのようなもの（データの集合？テスト観点とかテストケース？）

* インテリジェンス
Googleマップみたいなもの、事故があったら他の道があったら代替のものを提供するなど
データを利用してどのように最適なテストをするか

* 自動化
テスト結果が正しいか自己分析



以下のようなことがテストで必要となり、自動化されたテスト作成時間の短縮とメンテナンスコストの削減をしていかないといけない
* クラウド上で実行
* テスト作成が容易
* 変更に応じたシームレスたテスト修正
* テストからインサイトが得られる
* テストソリューションがCI/CD



mabl でできること
* Chromeトレース分析
* パフォーマンス分析
* モデル主導の変更検出

mablの今後
* ユーザが実際に何をしているのかを分析
* 主なユーザ手順のカバレッジをあげていく
* デプロイメント自動化
* リスクベースのテストやデプロイメント


重要なのは人間、テスト方法の根本的な変化
すべてがシフトレフトしている
→開発者がテストを実施する


テスト担当者はどのようにシフトレフトするか
（このあたりからスライドが早くて、しかも英語がききとれなかった）


## QA自動化プラットフォームが実現するDevTestOps

アジャイルコーチのふじはらさん
テスト自動化の話が30%程度

なぜDevTestOpsが必要なのか

DevOpsのサイクルすべてのところでテストが必要

QA自動化プットフォーム

プラットホーム活用のメリット
テスト環境などの気にしなくてテストコードに集中できる
→テストする環境を用意しなくてよい

mabl　　　操作性がいい
Autify　　見た目がいい
Testim　　やれることが一番多い


規模に合わせて作戦を選ぶ
品質組織作り、自動化は組織やプロダクトの規模に依存

QA部分を外注
時までQA、SET組織を作る
PO、エンジニア主体の品質保証体制
PO、エンジニア主体の品質保証体制＋テスティングサービスの利用

QAプロセスを導入したい
QA組織を作りたい
自動化したい

俗人性の排除
方法論
テスト手法


テスト＝品質ではない

テストのリードタイムは長くなる

QA作ったら品質の終わりの始まり？
本当に欲しいものを用意するのがQA組織



## LOB, Inc. でのmabl活用事例の紹介

mablを利用してテストを実施するコツなど
* 操作を録画、再実行できる
* テストステップがみやすい



# 感想

英語で始まったので大丈夫かなと思ったけど、資料は日本語だったし通訳がいて助かったｗｗ

mablの製品紹介だけでなく、どのように品質をあげていくか、シフトレフトしていくかを考えていくべきかということを聞けたのがよかった

テストすると品質は上がるとは思うが、テスト＝品質という概念はやっぱり世の中に染みついているんだなと感じた。

品質は生産ラインでつくるものだと思っているので、生産ラインの一部であるテストも必要だけど、そもそも生産ラインで製造するものがバグ、欠品だらけだったら品質は上がるわけがないというのが僕の考え。
Two Uncorrelated Requests, Then Locally-Executed Decision On Victory(TURTLEDOVE)の紹介


巷で話題のPrivacy Sandbox、[Web Advertising Business Group](https://github.com/w3c/web-advertising)で提案されている[TURTLEDOVE](https://github.com/michaelkleber/turtledove)の話です。

# 背景
Chromiumは[ Building a more private web: A path towards making third party cookies obsolete ](https://blog.chromium.org/2020/01/building-more-private-web-path-towards.html)で、お気持ちを表明しています：

* 3rd-party cookieはそのうち廃止するよ（できれば二年）
* プライバシーに配慮しつつ、広告も可能なPrivacy Sandboxを提案しているよ
* GitHubやメーリスで公開しているから、意見ちょうだいね


# TURTLEDOVEとは
「Two Uncorrelated Requests, Then Locally-Executed Decision On Victory」（「２つの相関がないリクエストの後、勝者をローカル実行で決定する」（意訳））の略で、ネット広告の新しい仕組みの**提案**です。


# 概要
名前の通り、２つの広告リクエストを送りローカルで実際に表示する広告を決めます。

1. エンドユーザーの興味に関する情報(interest-group)を含む広告リクエストを送信（interest-group request）
 1. （広告を出すページとは別のページから？）
2. 広告を出すページに関する情報を含む広告リクエストを送信（contextual request）
 1. **interest-groupに関する情報は含まない**
3. ブラウザ上のJavaScript実行で、表示する広告を決める
 4. この時、ネットワークアクセスを禁止
 5. 広告を出すページに関する情報を渡し、interest-groupに合わないページには表示しないことも可能に

# なにが嬉しいの
TURTLEDOVEによって、以下のことが嬉しいと言っています：

* 広告主：
 * 興味関心によって広告が出せる
* エンドユーザー：
 * 渡っている情報を確認・管理出来る
 * 興味のある広告が表示されることを、好む人もいる（らしい）

# 細かい部分
２つのリクエストが「uncorrelated」であるための注意点：

* リクエストタイミングにより、２つのリクエストが「correlate」にならないようにしてね
 * 広告を出すページとは別のページで、interest-group requestは先に送り、キャッシュするなど
 * 広告を描写する時も、ネットワークリクエストが発生しないようにする(WebBundleなど)
* リクエスト元のIPアドレスで紐付けられるのも危ないよね
 * [Willful IP Blindness](https://github.com/bslassey/ip-blindness)などの仕組みが必要

interest-groupの分類に関する注意点：

* interest-groupに属する人数が少ないと、micro-targeting（≒個人の特定）出来ちゃうよね
 * ので、ブラウザベンダーと業界で話し合って、interest-groupの最小の人数を決めようね
* interest-groupに属する人数が多くても、組み合わせるとmicro-targeting出来ちゃうよね
 * ので、interest-group毎に広告リクエストを送るのがいいよね


# 愉快な仲間たち

* [Privacy Sandbox](https://www.chromium.org/Home/chromium-privacy/privacy-sandbox)
 * おやぶん
 * 「Replacing Functionality Served by Cross-site Tracking」にTURTLEDOVEの記述があり、Privacy Sandboxの一部な気がしてます
 * FloC・Willful IP Blindness・Aggregated Reporting APIなどもPrivacy Sandboxの一部？
* [FLoC](https://github.com/jkarlin/floc)
 * ふたご
 * TURTLEDOVEではinterest-groupを手動で誰かが決めますが、FloCではブラウザが自動で決めます
* [PIGIN](https://github.com/michaelkleber/pigin)
 * ごせんぞ
 * TURTLEDOVEの前身らしい
* [Aggregated Reporting API](https://github.com/csharrison/aggregate-reporting-api)
 * ともだち１
 * 計測やフリクエンシーキャップなどが難しくなるので、新しくAPIを作ろうぜ！との感じ
* [WebBundle](https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html)
 * ともだち2
 * Privacy Sandboxとは別に、CDNやAMPの文脈で開発・提案されている機能です
 * Jxckさんの[解説](https://blog.jxck.io/entries/2019-11-12/webbundle.html)がわかりやすいです
Heroku Schedulerの設定方法

はじめまして。
普段はWebサービスの開発をしてます。

 - **[シルトレンド](https://siru-trend.com)**


# 本記事の内容

[Heroku](https://jp.heroku.com/) には、Webサービスを運用する上で便利な機能がたくさんあります。
そのうちのひとつが 「Heroku Scheduler」です。
今回はその Heroku Scheduler について書きます。


# Heroku Scheduler とは
Heroku が提供するジョブスケジューラー機能。
指定した時間間隔で指定したコマンドを定期実行できます。
cronのような機能です。

# Heroku Scheduler 設定方法

Heroku にログインして、ダッシュボードを開きます。

<img width="1218" alt="スクリーンショット 2020-02-18 7.18.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259302/29f84926-3845-9deb-76c5-e13ad6d06be0.png">

***

「Add-ons」テキストボックスに「Heroku Scheduler」と入力します。
すると候補が出てくるので、リンクを押下します。

<img width="1215" alt="スクリーンショット 2020-02-18 8.51.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259302/2ae8c9ef-26a9-d861-e798-776a3efd2ec2.png">

***

ポップアップが表示されるので、「Provision」ボタンを押下します。
これで Heroku Scheduler がアドオンとして、自身のアカウントに追加されます。

<img width="465" alt="スクリーンショット 2020-02-18 7.19.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259302/d9004065-c9e2-c22c-ad12-8131205c7ee0.png">

***

追加された「Heroku Schedular」リンクを押下します。

<img width="1219" alt="スクリーンショット 2020-02-18 8.57.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259302/1e1fb682-1b31-c6ff-4330-0483e7d8e9e3.png">

***

別ウィンドウで Heroku Scheduler の管理画面が開くので、「Add Job」ボタンを押下します。

<img width="1218" alt="スクリーンショット 2020-02-18 7.19.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259302/b364ee15-b852-f6ce-b3bd-5347452014c2.png">

***

画面右側に「Job Editor」ポップアップが出てくるので、
コマンドを実行するタイミングと、実行するコマンドを定義します。
そのあと、「Save Job」ボタンを押下すると、スケジュールが作成されます。

<img width="387" alt="hoge.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259302/38775fa9-940a-6eb1-75e3-8ec7853e6d70.png">


***

以上で Heroku Schedular の設定が完了します。
少しでもご参考になれば幸いです。
[flutter_driver] Flutter統合テストでdriverアクションがフリーズしてしまう問題を解決する

[CircularProgressIndicator](https://api.flutter.dev/flutter/material/CircularProgressIndicator-class.html)などのループアニメーションを含むWidgetがUIにあると、`driver.tap()`や`driver.screenshot()`などのdriverへのアクションはフリーズします。
これは、[flutter_driver](https://api.flutter.dev/flutter/flutter_driver/flutter_driver-library.html)にはUIの更新が終わるまでUIへの操作を待機させる`frame sync`という機構が備わっているからです。

例

```dart
test('test', () async => {
  // UIにプログレスバーなどのループアニメーションがあると実行されない
  // =>テストがタイムアウト
  await driver.tap(find.byValueKey('key'));
});
```

#### 解決方法
`runUnsynchronized`で`frame sync`を無効にすればUIの更新終了を待たずに実行することができます

```dart
test('test', () async {
  await driver.runUnsynchronized(() async {
    // UIが更新途中でも実行される
    await driver.tap(find.byValueKey('key'));
  });
});
```
初心者によるプログラミング学習ログ 243日目

#100日チャレンジの243日目
twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。
100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。
243日目は、

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>243日目<br>・youtubeで、webサイト模写<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1229858159088422912?ref_src=twsrc%5Etfw">February 18, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
[Flutter] LayoutBuilderが無限にビルドされてしまうのを防ぐには

Widgetのサイズを取得するために使用される[LayoutBuilder](https://api.flutter.dev/flutter/widgets/LayoutBuilder-class.html)は、その子Widgetがビルドされると、それに伴ってビルドされてしまいます。
したがって、[FutureBuilder](https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html)など動的にUIを変更するWidgetをLayoutBuilderの子孫に使用するときは注意が必要です。

例えば以下のWidgetはTextがビルドされるごとにLayoutBuilderがリビルドされ、無限にビルドされてしまいます。

```dart

 @override
  Widget build(BuildContext context) => LayoutBuilder(
          builder: (BuildContext context, BoxConstraints constraints) => FutureBuilder<Ranking>(
          future: future,
          builder: (BuildContext context, AsyncSnapshot<Ranking> snapshot) {
            if (snapshot.hasError)
              return Text('error');
            
            if (!snapshot.hasData)
              return Text('loading');
            
            return Text('done');
          },
        ));
```

このことは[FutureBuilder](https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html)のリファレレンスの冒頭に書かれています。

> The future must have been obtained earlier, e.g. during State.initState, State.didUpdateConfig, or State.didChangeDependencies. It must not be created during the State.build or StatelessWidget.build method call when constructing the FutureBuilder. If the future is created at the same time as the FutureBuilder, then every time the FutureBuilder's parent is rebuilt, the asynchronous task will be restarted.

[StatefullWidget](https://api.flutter.dev/flutter/widgets/StatefulWidget-class.html)などを用いてfutureが毎度作成されないようにするなどの対応が必要です。
【Rails】ActiveStorageを使わずにGoogle Cloud Storage（GCS）を使う

## 概要
RailsでGoogle Cloud Storage（GCS）を使うとなると、ActiveStorageを使う方法が挙がりますが、ActiveRecordを使わないケース（*1）や、そもそもActiveStorageを導入するのが手間だったりすることがあると思います。
ので、ActiveStorageを使わず比較的手軽にGCSを使う方法を紹介します。

*1…2020年2月時点だと、ActiveRecordにしか対応してないみたいです。[ActiveStorage and Mongo #31408](https://github.com/rails/rails/issues/31408)

## 事前準備

- [入門ガイド](https://cloud.google.com/storage/docs/how-to?hl=ja)を参考に、GCSのバケットを作成する。
- [Google Cloud Platform のサービスアカウントキーを作成する](https://www.magellanic-clouds.com/blocks/guide/create-gcp-service-account-key/)を参考に、サービスアカウントキーのファイルを取得する。
- google-cloud-storageのライブラリを使うので、[gemをインストール](https://github.com/googleapis/google-cloud-ruby/blob/master/google-cloud-storage/README.md#quick-start)する。


## サンプルの概要
以下のような処理を想定して、GCS使用部分のサンプルを書きます。

- クライアントからmultipart/form-dataでファイルを受け取る。（ファイルの受信部分は[Railsでファイルをアップロードしてpublicディレクトリに保存したあとに表示する](https://cre8cre8.com/rails/upload-image.htm)を参照のこと）
- GCSにファイルをアップロードする。
- アップロードしたファイルのURLを取得する。

## 実装サンプル
### バケットの取得
[Example](https://github.com/googleapis/google-cloud-ruby/blob/master/google-cloud-storage/README.md#example)を参考にして、バケットを取得します。また、事前準備で取得したkeyファイルは、configフォルダ配下に配置しているものとします。

```google_cloud_storage_util.rb
require "google/cloud/storage"

module GoogleCloudStorageUtil

  def getBucket()
    storage = Google::Cloud::Storage.new(
      project_id: "GCPのプロジェクトIDを入力",
      credentials: "config/test_key.json"
    )
    storage.bucket "事前準備で作成したバケット名を入力"
  end
end
```

### ファイルの確認・削除
アップロードするファイルはパス（フォルダ名+ファイル名）で一意にするので、受け取ったファイル名で既に存在する場合は削除します。

```google_cloud_storage_util.rb
  def deleteImageFile(fileName, bucket)
    file = bucket.file("test_folder/" + fileName)
    if !file.nil?
      file.delete
    end
  end
```

### ファイルの追加
指定したパスにファイルを追加します。multipart/form-dataで受け取った場合は、tempfileで送信します。

```google_cloud_storage_util.rb
  def addImageFile(imageFile, fileName, bucket)
    # tempfileを送る
    bucket.create_file(imageFile.tempfile, "test_folder/" + fileName)
  end
```

### 参照用URLの取得
アップロードしたファイルをパブリックで参照するためには、期限付きのURLを取得する必要があります。

```google_cloud_storage_util.rb
  def getImageUrl(fileName, bucket)
    file = bucket.file("test_folder/" + fileName)
    if !file.nil?
      file.signed_url(method: "GET", expires: 60 * 60 * 24)
    else
      nil
    end
  end
```

## 参考記事など
[google-cloud-storage API documentation](https://googleapis.dev/ruby/google-cloud-storage/latest/index.html)
[Google Cloud Storageのファイルを指定したファイル名でダウンロードしたい](https://qiita.com/munaita_/items/e1c7278fe3233de38ad0)
GitHub で草が生えない時の解決策

# commitがcontributionとしてカウントされる条件
* commitに使用されるメールアドレスがGitHubアカウントと連携されていること


# commitしたのに草が生えていない時の対処法
1. リポジトリのcommitを確認できるページにアクセス
2. 自分のGitHubのアカウント名（ユーザー名）でcommitされているか確認
3. 違う名前でcommitされていた場合contributionとしてカウントされないので，commitを行う端末に自分のGitHubのユーザ名，メールアドレスを設定する必要がある


# 作業端末にGitHubのアカウント情報を設定する
ユーザー名やメールアドレスが設定できていない場合以下のコマンドで設定する

```
git config --global user.name "(GitHubのユーザ名)"
git config --global user.email "(GitHubに連携したメールアドレス)"
```
UIViewに角丸と影をつける方法について

#はじめに（とばしても構いません😊）
初めましてりゅーちゃんです！！
今回はUIViewに角丸、影をつける際に困ったことについて共有していきます🙇‍♂️
参考に慣れば幸いです！！
業務で実装する際に詰まってしまったので自分の備蓄として書いていきます！！
もっといい方法があるよという方がいたらコメントしていただけると幸いです😊
#完成画面
<img width="385" alt="スクリーンショット 2020-02-19 1.36.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463811/9a66e9c0-c452-4aa2-b5ad-c1290ea3dddd.png">
この画面を生成していきたいと思います！
それではコードの方を見ていきましょう！！👊
#実装コード
```swift:qiita.swift
import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var sampleView: UIView!
    @IBOutlet weak var shadowView: UIView!
    
    override func viewDidLoad() {:helmet_with_cross:
        super.viewDidLoad()
        
        setUpsampleView()
    }
    
    private func setUpsampleView() {
        let viewRadius: CGFloat = 20.0
        shadowView.layer.cornerRadius = viewRadius
        shadowView.layer.shadowColor = UIColor.red.cgColor
        shadowView.layer.shadowOffset = CGSize(width: 0, height: 0)
        shadowView.layer.shadowRadius = 7
        shadowView.layer.shadowOpacity = 1
        
        sampleView.layer.cornerRadius = viewRadius
        sampleView.layer.masksToBounds = true
    }
}
```
実装のためのコードはこちらになります:eyes:
###ストーリーボード
<img width="770" alt="スクリーンショット 2020-02-19 1.42.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463811/96b7d8d4-8eeb-96cd-471c-d838012b6ae8.png">
ストーリーボード上でのUIViewの配置は画像のようになります！
sampleViewのしたにshadowViewを作成し影、角丸を表示させています:relaxed:

---
####**ちょっと待った！！**
View1つに対して実装できないのか？！と思う方がいるかもしれません:frowning2:

僕も思いました。。。。
だからやって見たんですが。。。

```swift:qiita.swift

mport UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var sampleView: UIView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        setUpsampleView()
    }
    
    private func setUpsampleView() {
        let viewRadius: CGFloat = 20.0
        sampleView.layer.cornerRadius = viewRadius
        sampleView.layer.shadowColor = UIColor.red.cgColor
        sampleView.layer.shadowOffset = CGSize(width: 0, height: 0)
        sampleView.layer.shadowRadius = 7
        sampleView.layer.shadowOpacity = 1
        
        sampleView.layer.cornerRadius = viewRadius
        sampleView.layer.masksToBounds = true
    }
}

```
**これで完璧だ！！完全に理解した！！**と思っていたのですが。。。

<img width="392" alt="スクリーンショット 2020-02-19 2.07.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463811/dc8c86f6-8f50-e4e1-aa88-62a56d2336de.png">

**なんでやねん！！なんでできへんのやて！！**となりました。。。

同じViewに対しては角丸、影をつけることはできないらしいです（調べた記事に関してはQiita外の記事になりますので今回は記載するのはやめておきます:bow_tone1:）
（検索ワード：How to implement rounded corner image view with shadowで検索してみてください！）

##最後に
今回はUIViewに角丸、影をつける処理に関して記載していきました！
ただこれだとView1つ、1つに処理を書かなければいけないのでextensionなどを使うのがいいと思います。。。
この話題に関しては、今回の記事を更新して付け加えておきます。。。
遅かったら催促してください！！:muscle:
ここまで読んでいただいてありがとうございました！
少しでもお役に立てると幸いです！！！！！
FFmpegでタイムコードを書き込んだ動画を作成する

~~先に作ったShaka Streamerの環境で提供されるHLSがどの程度の遅延なのか確認するため、~~タイムコードを書き込んだ動画を作成する。
（よくよく考えたらタイムコードを書き込んだ動画を作成しただけでは遅延が確認するのは難しいことがわかったので、遅延を確認する環境の構築はまた改めて検討したい。なので、本記事ではタイムコードを書き込んだ動画を作成することだけにフォーカスする）

## 参考にしたページ
https://sites.google.com/site/linuxencoding/x264-ffmpeg-mapping
https://trac.ffmpeg.org/wiki/Limiting%20the%20output%20bitrate
https://trac.ffmpeg.org/wiki/FilteringGuide
https://support.apple.com/en-us/HT201749

一番最初のリンクはかなり昔からお世話になっている気がする。

## 使用した環境
- macOS 10.14.6（18G3020）
- ffmpeg version 4.1.4

## ffmpegのコマンド

オリジナルの動画は http://www.caminandes.com/ から拝借。

```
ffmpeg -i 03_caminandes_llamigos_1080p.mp4 \
-vcodec h264 -profile:v main -b:v 1000k -minrate:v 1000k -maxrate:v 1000k \
-bufsize:v 2000k -crf 23 -sc_threshold 0 \
-keyint_min 24 -r 24 -g 48 \
-vf "scale=640:-1, \
drawtext=fontfile=/Library/Fonts/Courier\ New\ Bold.ttf: \
timecode='00\:00\:00\:00': r=24: fontsize=60: fontcolor=white: \
x=(w-tw)/2: y=h-(2*lh): box=1: boxcolor=0x00000000@1" \
-acodec aac -ac 2 -ab 64k -ar 44.1k -y output.mp4
```
(2/20編集、timecodeのシングルクォートが抜けてました)

なんか必要ないオプションも含まれているかもしれないけれども、一応自分では以下のつもりで指定しています。間違ってたら教えて欲しい・・・

- videoのビットレートは大体1000kになるように。
- Frame Rateは24, GOPは2秒ごと
- CRFは指定しなくていいけど（デフォルトも23）、いつか変更することも考慮して入れといた
- width=640, heightはアスペクト比を保ったままwidthに応じてリサイズ

フォントはmacOSだと Font Book というアプリを開き、右クリックのメニュー（コンテクストメニュー）から「Finderに表示」を選択すると、そのフォントファイルの場所がわかります。
<img width="624" alt="スクリーンショット 2020-02-19 1.20.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/375661/7bf28725-9c4a-b7e4-0a27-1026390e6f31.png">

## 確認
ffplayで確認。大体うまくいっている。
<img width="752" alt="スクリーンショット 2020-02-19 1.53.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/375661/9f53f97c-ed4e-4fc0-ab9f-37c636c2ff6b.png">

ちなみにタイムコードは`hh:mm:ss:(フレーム番号)`です。
一番最後はms(milli-sec)ではないのでご注意を。

## 確認(ffprobe)
以下のコマンドでビデオのフレームが期待通りかどうかをざっと確認する。

```
ffprobe -i output.mp4 -select_streams v:0 -show_frames -print_format json
```

I-frameが48フレームごと、且つ2秒ごとなので、うまくいっている気がする。

以上。
docker-composeでWordPress5.3+mysql8.0+PHP7.4+apache2.4を動かす

こんばんは

タイトルの通り、最新バージョンのWordPressを動かしてみた話です。
現時点で最新バージョンのインストール方法が意外と見つからなかったのでメモです。
以下のdocker-compose.ymlでupしてください。

```docker-compose.yml
version: '3'
services:
  db:
    image: mysql:8.0
    environment:
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress
      MYSQL_DATABASE: wordpress
      MYSQL_ROOT_PASSWORD: wordpress
    volumes:
      - ./data/db:/var/lib/mysql
    restart: always
  wordpress:
    depends_on:
      - db
    image: wordpress:php7.4-apache
    ports:
      - "8000:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_PASSWORD: wordpress
```

ポイントは、wordpressイメージのタグを`php7.4-apache`にしている箇所。
タグ一覧はこちらを参照 https://hub.docker.com/_/wordpress/
現状の`latest`では`php7.3`がインストールされ、mysql8で動かそうとすると以下のエラーに見舞われます。

```
The server requested authentication method unknown to the client [caching_sha2_password]")
```
mysql5.7にダウングレードしたり、mysqlの起動オプションを変更したり、設定を読み込ませることでも解決できるようですが、
**php7.4のイメージだと解消するようです。（しました）**
どこかの掲示板にて、php7.4-fpm-alpineを指定しろというコメントも見つけたのですが、
それだとapacheモジュールが含まれないため、別途httpインスタンスを立ち上げないといけない模様です。
面倒なのでapacheの含まれているイメージを指定したところ、一撃でした。

おやすみなさい。
画像アップロード機能実装について

#目的
作成したアプリケーションに画像アップロード機能を実装するための手順や
考え方などを備忘録的に残していきます。

#画像アップロードとは
アップロードとはファイルやデータをPCやスマホからインターネット上のサーバーへ転送することを指します。

#画像アップロードの仕組み
 * ファイル選択ボタンを押して、画像を選択
 * 送信ボタンをおす
 * 画像ファイルを画像パスがリクエストして送信される
 * 画像ファイルはアクセス先コンピューター内に、画像のパスはDBないにあるテーブルに保存される 
 (画像の保存先には外部のストレージを使うことが多い。AWSサービスのS3など..)


#実装の流れ
######ライブラリのインストール
 
```ruby:Gemfile
gem 'carrierwave'
gem 'mini_magick'
```

```
bundle install
```

######アプリの雛形を作成
scaffoldで必要なモデルやコントローラーなど一式を作成します。
モデル名はFeedとし、画像を保存するためにimageカラムを作成します。
 
```
$ rails g scaffold feed image:text
$ rails db:migrate
```

######アップローダファイルを作成
アップローダファイルとは アップロードに関する設定 をするためのファイルです。
アップロードに関する設定とは以下が挙げられます。

* 外部ストレージを連携するかどうか
* 保存形式
* 画像ファイルの保存先の設定
* 画像サイズの調整
 
```
$ rails g uploader Image
```

```ruby:app/uploader/image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick
   # MiniMagickをincludeすると画像サイズ調整ができるようになる
  storage :file # 保存形式の設定。他に使うものとしてはfog形式などがある。
  process :resize_to_limit => [50, 50] # 画像サイズの調整
  # 画像ファイルの保存先の設定
  # 保存先を指定するには `store_dir` というメソッドに定義します。
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end
end
```
保存形式を指定しているのが storage :file という記述です。
file以外の保存形式として クラウドのストレージ が挙げられます。
クラウドのストレージとして、Amazonが提供している S3 というサービスが有名です。file形式は画像が実体として存在しますが、クラウドのストレージにおける画像は実体が存在しません。この場合は専用のgemを利用して storage :fog という記述をします。

最後に該当のモデルにカラムとアップローダを指定します。
Feedモデル内に以下を記述

```ruby:app/model/feed.rb
~省略~
#アップローダ定義
 mount_uploader :image, ImageUploader
~省略~
```
上記の記述をすることで、feedsテーブルの中にあるimageカラムにimageUploaderという名前のアップローダ機能を追加することができます。

#まとめ
アップローダ定義の意味を総括すると以下のようになります。

* feedモデルが関係しているのでfeedsテーブルが関係している
* mount_uploaderは、画像アップロードの宣言をしている
* :imageはfeedsテーブル内の画像パスが入っているカラム名を指している
* ImageUploaderは、ImageUploaderファイル内の設定を元にアップロードすることを意味している
配列で便利なメソッドを紹介するぞpart1

#whereメソッド基本形

```rb
User.where(admin: true)
```

この場合、adminがtrueのユーザーを全て取得することができる。

#whereメソッドの配列で指定

```rb
User.where(kind: [1,2])
```

この場合、kindが１、または２のユーザーを全て取得することができる。

#where.notメソッド

```rb
User.where.not(id: 2)
```
この場合、idが2のユーザー以外を取得することができる。

#whereメソッドで比較

```rb
User.where("kind" > "?", 1)
```
これでkindが1より大きいユーザーを全て取得することができる。

#whereメソッドでorを使う

```rb
User.where('kind = ? or name = ?', 0, 'yamada')
```
この場合、kindが0かnameがyamadaのユーザーを全て取得することができる。

#whereメソッドでandを使う

```rb
User.where('kind = ? and name = ?, 0, "yamada")
```
この場合、kindが0かつ、nameがyamadaのユーザーを全て取得することができる。

#whereメソッドでメソッドチェーンを使う

```rb
User.where(kind: 0).where(name: 'yamada')
```
この場合、意味は先ほどのandと同じになる。


#distinct uniqメソッド

これは配列の中で被っている要素をなくすメソッド。

```rb
Sample.select(:last_name,:first_name).distinct

#レコード件数を数える場合
Sample.select(:last_name).distinct.size
```

```rb
[1,1,2,2,3,3].distinct

=>[1,2,3]
```
こんな感じで使う。

uniqメソッドも使えるが、どうやら非推奨らしい。


#sampleメソッド

sampleメソッドは配列の中からランダムで要素を取り出すメソッド。

```rb
配列.sample
配列.sample(2)
```
引数がない場合は1つだけ要素を取り出す。