OmniAICreator/Qiita-1.07M huggingface dataset:
Rubyで土日（週末）を判定するプログラム　〜いかに初心者な書き方から脱するか〜

# やりたいこと
どうも、初心者Ruby書きです。
先日、モジモジしながら社内で

`「土日を判定するRubyのメソッドを書いたのですが、どうも初心者臭さが抜けなくて...」`

と、投げかけたところ、鬼殺隊の柱のような先輩たちが優しく教えてくれて、そのSlackのやりとりが超楽しかったのでメモ。

僕のような未経験者であっても基本的人権を尊重してくれて、楽しく教えてくれる会社、それが[株式会社Fusic](https://fusic.co.jp/)です。

https://fusic.co.jp/

# 実装！

今回の要件は下記です。
(1) 今日が土日かを判定する（日本時間で！）
(2) 土日ならば処理を終了する

## 0. 初心者（出発点）
私が違和感を感じながらも提示したコードがこちらです。
やりたいことはできるけど、絶対にダサい！でも、どう改善したらいいかわからない！

```ruby:
def weekend?
  today = Time.now.localtime("+09:00") # Time#localtimeでUnix時間を日本時間に合わせる
  if today.saturday?
    true
  elsif today.sunday?
    true
  else
    false
  end
end

return if weekend?
```
こんなコード晒すのが恥ずかしいですが...
これからこれを一歩ずついい感じにしていきます。


## 1. とりま初心者から一歩抜け出す
ひとまず、8行あった土日判定の処理がたったの3行になります...

```ruby
def weekend?
  today = Time.now.localtime("+09:00")
  return true if today.saturday? || today.sunday?
  false
end

return if weekend?
```

**学ぶべきこと**

- ifの条件文はOR（`||`）文で書けるので一行でイケる
- if文はネストしやすいので`return if 条件`の形が見やすくなって善い

知っていたのに、ここでの使い方が思いつかなかったです。悔しい！恥ずかしい！

## 2. 初心者から二歩抜け出す
もう一行減らせます。

```ruby
def weekend?
  today = Time.now.localtime("+09:00")
  today.saturday? || today.sunday?
end

return if weekend?
```

**学ぶべきこと**

- Rubyのメソッドは`return`を付けなくともその値を返すので、`return true`とか`false`とか書かなくて良い
- プロを目指す人のためのRuby入門の一節も復習↓

> Rubyは最後に評価された式がメソッドの戻り値になるのが特徴です。returnのようなキーワードは不要です。（中略）Rubyではreturnを使わない書き方の方が主流です。

>「プロを目指す人のためのRuby入門」伊藤淳一著p37


## 3. さらにもう一歩。オープンクラス！
```ruby
class Time
  def weekend?
    saturday? || sunday?
  end
end

today = Time.now.localtime("+09:00")
return if today.weekend?
```

**学ぶべきこと**

- 既存のクラスに自分でメソッドを作って追加してしまう！:satisfied:（今回だと[Timeクラス](https://docs.ruby-lang.org/ja/latest/class/Time.html)）
- 「オブジェクト指向的にもこれが一番綺麗」らしい。
- これをメタプログラミングと呼ぶらしい。


## 4. ダメ押しの一歩。祝日対応！

今回の要件とは少し外れますが、祝日まで判定したい場合はRailsにはこんなgemがあるそうな。

https://github.com/holiday-jp/holiday_jp-ruby

# 最後に
何かご指摘などあればぜひよろしくお願いします。
coreserver で cron の設定

coreserver に ssh でログインして、crontab で cron を設定しても、しばらくするとその設定は消えます。
2021-4-15 に確認しました。
こちらにも、同じ体験をした方がいらっしゃいました。
[CORESERVERでMovable Typeの指定日投稿を使う](https://blog.grimonet.com/articles/2011/05/coreservermovable_type.php)

```text
しばらく経つと cron の設定が消えてる...
```

解決策は、
1) ssh でログインして、スクリプトの作成、テストを行う。
2) cron の実行日時の設定は、web の管理画面で行う。
![cron_apr15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/67580955-4fb3-0081-3e61-08a5cc85d1e8.png)
Javascript 備忘録8<モジュール>

■モジュールについて
→モジュールには2種類存在する
→ESMとCJS

■ESMとCJSの比較
→ESMはimport/exportを使用
→CJSはrequire/exportsを使用

■EMでモジュールを使用する

```moduleA.js
export let hello = 'hello';

export function helloFn() {
    console.log('hello')
}
```

```moduleB.js
// 別のモジュールからimportする
import { hello, helloFn } from './moduleA.js';
// 下のように as を使用して別の変数名にすることが可能
import { hello as ya, helloFn as fn }from './moduleA.js';

// 変数と関数が使用できるようになる
console.log(hello);
helloFn();
```
GooglePhotoへランダムに写真をLine送信する

## やりたいこと

- GooglePhotoの写真を取得し、Lineへ送信する。週に1回送信をする
- フォトフレームに送信するなどできます。
- 3日間ほどかかった。。。世界中の先人たちに感謝


## 環境
Gas
Line

## 初期ロードマップ
- 1　アルバム名を取得
 - 1-1　googlePhotoで取得したアルバム名をgooglespreadsheetのセルへ一覧で書き出す
 - 1-2　共有アルバムのIDを取得し、googlespreadsheetのセルへ一覧で書き出す 

- ３　画像をURLで保持
- 4　Lineへ送信
 - 4-1 sampleLine送信する(テキスト)
 - 4-２ sampleLine送信する(URL化の画像一枚)
 - 4-３ Line送信する(URL化の画像一枚)

## ソースは以下のMain。
https://github.com/hide6974/GoogleGas/blob/main/main.gs

コツはちいさくできることから少しづつやることでしたね。

PropertiesService.getScriptProperties().getProperty　→最初はこの意味が不明。3時間後プロパティかと納得

作成は、以下を利用。

https://qiita.com/hiteto/items/f63584045df31dff31d2
SwiftUIでVideoplayerを使ってみた

ios14からswiftUIでVideoPlayerが使えるようになったので使ってみました。swiftUIのコードのみの表示と、UIViewControllerRepresentableを継承したコードが必要になるところを記載しました。

## SwiftUIのコードのみでの表現


```swiftUI
import SwiftUI
import AVKit

struct ContentView: View {
    // play river.mp4
    private let player = AVPlayer(url: Bundle.main.url(forResource: "river", withExtension: "mp4")!)
    
    var body: some View {
        HStack{
            VideoPlayer(player: player)
            .onAppear() {
                self.player.play()
　　　　　　　}.onDisappear() {
                self.player.pause()
            }.edgesIgnoringSafeArea(.all)
        }
    }
}
```

## 画面表示

- mp4ファイルで動画を再生しました。
- 気づきとして以下二点があります。 （[コードで利用している動画の引用元](https://www.pexels.com/ja-jp/video/4762374/)）
  - 下画像のように動画の黒いフレーム(青枠部分)が残る.  
  <img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152489/ade34640-6002-1ae9-cbe6-c8b0358f5014.png"> 
  - 下画像のように動画の再生や停止等を制御するUI部品が表示される  
  <img width="200" align="left" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152489/19737e33-aa94-83e2-3efd-83795858271e.png" >

例えば、ログイン画面の背景としてフルスクリーンで動画を表示したい場合に、フルスクリーンで、動画の再生、停止のUI部品を消すことを検討するかとと思います。2021年4月時点では、SwiftUiのみのコードでは消せず、UIViewControllerRepresentableを利用してAVPlayer,AVPlayerViewControllerを利用して、それらの部品を消す必要がありそうです。


## AVPlayer,AVPlayerViewControllerを利用、UIViewControllerRepresentableを継承したコードが必要になるところ

コードは以下です。

```swiftUI

import SwiftUI
import AVKit

struct ContentView: View {
    //play river movie
    private let player =
        AVPlayer(url: Bundle.main.url(forResource: "river", withExtension: "mp4")!)
    var body: some View {
        PlayerViewController(player: player)
            .onAppear(){
                self.player.play()
            }.edgesIgnoringSafeArea(.all)
    }
}

struct PlayerViewController: UIViewControllerRepresentable {
    
    func makeUIViewController(context: Context) -> AVPlayerViewController {
        let player =
            AVPlayer(url: Bundle.main.url(forResource: "kawa", withExtension: "mp4")!)
        let controller =  AVPlayerViewController()
        controller.modalPresentationStyle = .fullScreen
        controller.player = player
        controller.videoGravity = .resizeAspectFill
        controller.showsPlaybackControls = false
        return controller
    }
    
    func updateUIViewController(_ playerController: AVPlayerViewController, context: Context) {
        //none
    }
}
```

## 画面表示
セーフエリアも含めて動画を表示できるようになりました。下記はそのスクリーンショットです。
（[コードで利用している動画の引用元](https://www.pexels.com/ja-jp/video/4762374/)）
  <img width="200" align="left" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152489/25b64660-20e0-7e1e-6703-c1a6bf0235fd.png" >

## 今後の期待
今後のSwiftUIのバージョンアップで、SwiftUIのコードのみで記載できる部品が多くなることを期待しております。
トライアスロン型開発のすゝめ

# 初編
ウォーターフォール型、アジャイル型など、開発手法はいくつか存在するが、古代ローマから存在した開発手法である「トライアスロン型開発」について説明しようと思う。

# パフォーマンスは同等なること
本開発手法は、段階的に環境を困難なものへと移し、優秀なエンジニアだけを厳選していく手法である。
厳選のためのステップを増やすことで、よりスキル・ストレス耐性ともに非常に高いエンジニアを厳選できる。
厳選したエンジニアは、どんな環境でもパフォーマンスを落とすことがない。

# 怨望の人間に害あるを論ず
多少の環境の違いで、不平不満を言うエンジニアは、百害あって一利なしである。
さっさと篩から落とすべきである。

# スキルを疑いて取捨を断ずること
エンジニアの採用は、面接ではスキルの良し悪しは分からないものである。
まず採用した後、本手法で厳選することで、優秀なエンジニアを獲得できる。

# 手近く独立を守ること / 心事と働きと相当すべきの論
なんだマシンスペックが悪いだの、お気に入りのソフトウェアが使えないだの能書きを垂れるエンジニアは、不要である。
vimの設定ができるだけで喜びを感じるような侘び寂びの分かる真のサムライエンジニアを獲得すべきである。

# おわりに
本手法で厳選したエンジニアは大変優秀ではあるが、深海魚がすぐに水面では生きられないように、ストレスフリーな環境に移すと、二度と戻ってこないか当たり前の環境に対応できなくなっている可能性があります。
また古きいい伝えに「その型紅き炎をまといて、灰色の野となすべし」とあるように災いを招くことがございます。
Javascript 備忘録7<非同期処理>

■同期処理と非同期処理
→同期処理とは、１スレッドの中で上から下へとソースコードが実行されること
→同期処理では一つの処理が終了するまで、他の処理は行われない
→非同期処理は、メインスレッドから外れて別の処理を裏で実行する
→完了後、再度メインスレッドに戻ってくる
→非同期処理を裏で行っている際に、メインでは別の処理を行うことができる

■非同期処理について
→非同期処理はタスクキューにファーストイン・ファーストアウトの形で処理される
→コールスタック（メインスレッド）に処理が残っている間は、タスクキューに積まれた処理は実行されない
→コールスタックが空になると、やっとタスクキューの処理が実行されれる

■Promiseについて（ES6以降）

```js
function sleep(callback, val) {
    setTimeout(function() {
        console.log(val++);
        callback(val);
    }, 1000)
}

sleep(function(val) {
    sleep(function(val) {
        console.log('callback done')
    }, val)
}, 0)
```
→sleepを何回も呼び出すことで、非同期処理のチェーンを作成することができる
→しかし、今は２回で住んでいるが１００回となるとソースが助長的になり、ネストも深くなってしまう
→その際にPromiseを使用する

```js
// promiseの構文
new Promise(function() {
    
}).then(function(data) {
    // 非同期処理
}).catch(function(data) {
    // 非同期処理
}).finally(function(){
    // 非同期処理
});
```
敢えていま読む「仕様書の基本と仕組み」とシステム開発全体の流れ markdownサンプル

[図解入門 よくわかる最新システム開発者のための仕様書の基本と仕組み[第3版] | 智明, 増田 |本 | 通販 | Amazon](https://www.amazon.co.jp/dp/4798057428)
より、要点、キーワードをメモしたもの。

<img src="https://images-na.ssl-images-amazon.com/images/I/515O+55vcuL._SX354_BO1,204,203,200_.jpg" height="50%" width="30%">

## システム開発全体の流れ とは

- プロジェクトの流れ
    - 時間軸
        - 要求定義
        - 要件定義
        - 設計工程
            - 外部設計
            - 内部設計
        - 検証
        - 実装工程
        - 試験工程
        - 納入
    - マイルストーン
- 成果物の流れ
    - 要件定義での成果物
    - 設計工程・検証での成果物
    - 実装工程での成果物
    - 試験工程での成果物
    - それぞれの工程を結びつける成果物
- 情報の流れ
    - 要求定義・提案書
    - 要件定義
    - 基本設計
    - 外部設計
    - 内部設計
    - 実装工程
    - 試験工程


## サンプル

Markdownで表現すると以下のようになる。


```要求定義書サンプル.md
## はじめに
要求定義の前置きを書く。

## システム構築の目的
- システム構築をする際の目的

## システム構築の制限事項
- システム構築をする際の制限事項を記述する。
- 移行プロジェクトの場合は、外部システムの記述など

## システム機能要件定義
- システムを構築する際の機能要件

## システム機能外要件
- 性能要件などの機能外要件

## システム構築スケジュール
- システム構築から運用までのスケジュール
``` 



```システム概要仕様書サンプル.md

## システム機能要件
- システムの機能要件を列記
- システムの機能要件を列記
- システムの機能要件を列記

## システム機能概要
### 共通ライブラリ
- 詳細

### ユーザーインターフェース
- 詳細

### データの永続化
- 詳細

### データのバックアップ、復旧
- 詳細

等
```



## 用語、関連記事
https://qiita.com/sunstripe2011/items/61df719fb1f6178b2605

https://qiita.com/chocode/items/fd51dd8f561e2a0fbd70

https://qiita.com/mikakane/items/b8045a11dba8d08e5fe4

https://qiita.com/aki_number16/items/c1e3e3198198aafbac35

https://qiita.com/Saku731/items/741fcf0f40dd989ee4f8


## 参考

自分は以下のようなものを書くことのほうが多かった。またAmazonではこんな説明資料を作るという話。

https://qiita.com/e99h2121/items/d690ea1fb7e9f9eb9ad4

[「カタログ」概論 - Qiita](https://qiita.com/e99h2121/items/2e992ba08be2ad324124)

https://forbesjapan.com/articles/detail/38145/2/1/1

比較しつつ読んだ本、記事の読書記録でした。

追記: [[Doc] 要件定義書テンプレート・要件定義書の書き方 - Qiita](https://qiita.com/syantien/items/9a8a7cbaeca2be3ef0d7)

参考になればさいわいです。
(簡単解説)bit全探索-部分和問題(Python)

#はじめに
自分が勉強してきた過程で分かりにくかった箇所を簡単に解説するために投稿しています．
bit全探索とは大体どういう感じのものなのかを簡単に解説しております．
特にプログラミングを学びたての方を対象としております．
#bit全探索とは
bit全探索とは、n個の要素からなる集合の部分集合を全て調べ上げる手法のことです．
分かりにくいですよね．．．

早速例題にいきましょう

#部分和問題
3つの数字{1,2,8}の中から何個でも良いので自由に数字を選んで10を作れるか？
と言う問題をbit全探索という手法を用いて解いていきます！
#手計算で解く方法
この問題を全て書き出して解くと，{},{1},{2},{8},{1,2}{1,8},{2,8},{1,2,8}の8通りを書き出して，各々の和が10になるかを調べれば解けます．
2と8の2個({2,8})を選ぶ時に和が10となります．
#bit全探索を用いた考え方

bit全探索では，**0の場合は値を未選択，1の場合は値を選択**していると考えます．
今回の問題の場合，{0,0,0}だと未選択，{0,0,1}だと8のみを選択，{0,1,0}だと2のみを選択していることになります．つまり，{0,0,0},{0,0,1},{0,1,0},{0,1,1},{1,0,0},{1,0,1},{1,1,0},{1,1,1}の8通りを調べ，各々の和が10になるかを調べれば解けます．(手計算だとここまででおわりです．)
この8通りを調べたあと，どの場所に1があるのかを調べないといけません．(プログラムの場合)
そこで，扱うのが**論理積(&)**と呼ばれるものです．これは**1と1の場合のみ**Trueを返すものです．
つまり，1を各々の値に照らし合わせていき，Trueとなった場合に値が選択されていることがわかります！
例えば，{0,0,1}だと1を各々の値に照らし合わせていくと，8の箇所のみTrueとなります．つまり，8が選択されていることがわかります！
以上をまとめると，
**1.値の選び方を全通り列挙する**
**2.論理積を用いて，どの箇所に1があるかを調べる**
**3.調べた組み合わせの和のうち10となったものが正解となる**
また，2と8の2個({0,1,1})を選ぶ時が答えとなります!

#コード
コードを載せた後に詳しく説明していきます．(分かりやすく説明する為に少し冗長に記述しております)

```python:rensyu.py
n=3
k=10
a=[1,2,8]
for bit in range(2**n):
    sum2 = 0

    for i in range(n):
        # bitにフラグが立っているかどうかを判定
        if bit & (1 << i):
            # フラグが立っていればsumに加算
            sum2 += a[n-1-i]

    if sum2 == k:
        print("Yes")
        #プログラムを終了
        exit()
print("No")
```
1行目：
nは数字の個数(3つ)．
kは作りたい値，
aは3つの数字の配列(リスト)を表しています．

2行目：for bit in range(2**n):
ここの部分でなぜ2のn乗までをループの範囲としているかというと，bit全探索では0と1で値を選択しているかどうかを判断していると話しました．つまり，各々の値(3つの値)に0or1の可能性があります．ですので，2*2*2=2の3乗をループの範囲としています．
bitには，0,1,2...7まで順番に入っていきます．この順番が上の方で書いた{0,0,0},{0,0,1},{0,1,0},{0,1,1},{1,0,0},{1,0,1},{1,1,0},{1,1,1}に対応しています．(000,001,010,011,100,101,110,111のように2進数と考えると対応していることがわかると思います)

3行目:sum = 0
選択した値の合計値を格納する変数を定義しています．

5行目：  for i in range(n):
ここの部分は上の方でも説明したように，1を移動させて，どこに1があるか(どの値が選択されているか)を調べるために，個数(3つ)をループ範囲としています．

7,9行目：  if bit & (1 << i):,sum += a[n-1-i]
<<は左シフトを表しており，1を順番に1つずつ左に動かしています．({0,0,1},{0,1,0},{1,0,0})
これがTrueとなる場合1があることがわかるので，sumに該当箇所の値を加算しています．

11行目〜：if sum2 == k:
この箇所でsum2が目的の値である１０と一致しているかを判定しています．

#おわりに
もし間違っている箇所やこうした方がもっとわかりやすくなるなどご意見がございましたらコメントしていただけると助かります！！
React Native + Expo CLI + Axiosを用いてAPIを実装

## React Native + Expo CLI開発
以前の投稿でReactNative+Expoの開発環境を整えたのでAPIデータを取り扱えるようにする
React Native + Expo CLI 環境構築 Windows編
https://qiita.com/tworks_front/items/4d3c22a758cc457388a0

## Axiosとは
そもそもAxiosとはjavascriptやnode.jsで使用可能で、Promiseを返すライブラリ(プロトコル：HTTP)です。
ReactのプロジェクトでRestAPIを使用する際に使っていて慣れ親しんでいるので今回Expoでも使用する。

## Axoisのインストール
npmでインストールするだけで使用可能

```
npm i -g axios
```

## News API
News APIは世界中のニュースを扱っていて、言語や条件で必要な情報に絞込みAPIで取得できる。
個人利用では無料のため、Expo + Axiosでニュースの表示まで実装する。
NewsAPIサイト
https://newsapi.org/

サイトにアクセスしGet API KeyよりAPIのKeyを取得する。
初回は登録必要
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1035014/92b32de1-3c10-d9d6-95ed-7fab7830ea49.png)

![capt1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1035014/1e08eb54-ee45-0a8a-312d-3006e73486d4.jpeg)

APIのリクエストサンプルがサイトにアクセスすると載っている。
今回は日本語のヘッドラインニュースを取得する。
リクエストサンプル
https://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=xxxxxx
countryを日本に変更しcategoryは絞らないでリクエストを行う。

## 実装
urlはひとまず以下のようにして取得する(取得確認して定数化する)

```
const url = "https://newsapi.org/v2/top-headlines?country=jp&apiKey=" + (newsAPIで発行されたAPIKey)
```

axiosをimportしあとは axios.get(リクエストURL)で取得可能。
非同期処理で、async awaitを用いることが可能。

```
import axios from 'axios';

useEffect(() => {
            getArticles();
        }, []);

    const getArticles = async () => {
        try {
            const response = await axios.get(url);
　　　　　　 console.log("response:",response)
        } catch (error) {
        }
    }
```

developlerToolsで出力したログを確認するとdataオブジェクト内にarticlesとしてニュースデータが入っている。totalResults:30など件数表示に必要なデータなども返っている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1035014/6ab778cf-810b-b16b-0252-4d8d0ca17d75.png)

あとは以下のようにデータを回して、Listコンポーネント(画像とタイトルを表示するコンポーネントを別途作成)でニュース画像、タイトル、本文など必要なものを表示する。

```
    return (
        <View >
            {_.map(articles, (value: any) => {
                return <List articles={value}/>
            })}
        </View>
    );

```

android端末で以下のような表示がされる
![123fas.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1035014/1a037f27-ba7c-32c7-d005-5c47c9b401b4.jpeg)

## まとめ
今回はAxiosを使えることの確認のためGetの実装を行った。
Axiosのインストールと実装まで迷う箇所がなく、シンプルに実装可能。
thenを用いて後続処理を行ったり、try catchの例外処理など実装すれば、expoでも使用可能であることが確認できた。
JSONデコードして保存とは

#■JSONデコードして保存とは

データを認識できるように変換して保存する事


実際のJSONデータはこちら

``` 
 { //2段階保存 配列
   “weather”:[
            “id”:804
             “main”:”Clouds”
             ]
　//2段階保存
    “main”:{
             “temp”:282.29
             }
　//1段階
    “name”: “London”
 }
```

#■上のJSONデータをデコードしてstructに保存
メソッドにして引数Data型を持し外部からDataをひっぱてくる。

■なんとか.swift の中

``` swift
func paseraJSON(weatherData: Data)
let json = JSONDecode()

do { let decoder = try json.decode(保存場所.self, flom: weatherData)
       
    }catch {
  print(error)
   }
```


#■structでの保存のしかた (保存する新規ファイルを作成したとする)

■Codableプロトコルを使用　データをデコードしてstructに保存できる用になる。
■Data.swiftの中　デコードしてあるデータなので実際にはここのデータを直接は表示しない

``` swift
struct Data: Codable {
   
//1段階やからこのまま
   let name:String

//2段階の保存先Struct名を書く    
　　let main: Main 

//2段階保存の配列やから新規struct名を[]で囲む
 　let weather: [Weather]
}

//2段階保存やから新たにstruct作るイメージはmainの中のtemp
struct Main: Codable {
  let temp: Double
}

//2段階保存かつ配列　まあ上とここは変わらない
struct Weather: Codable {
     let id: Int
}
```



#■strct Dataにデコードして保存した値を実際に使いやすいように
  　■また新規ファイル(WeatherModel)作ってそこに保存し直す

　WeatherModelの中 実際に使う名前や温度などのデータを保存

``` swift
struct WeatherModel {

   let  cityName: String
   let  conditionID: Int
   let   temperatrue: Double

　　　var conditionName:String {
   //取得したIDの数字によってコンデイションを文字列型にして分けて取得 後でこの文字と同じ画像を使う
        switch conditionID {
          
        case 200...232:
            return "cloud.bold"
        case 300...321:
            return "cloud.drizzle"
        case 500...531:
            return "cloud.rain"
        case 600...622:
            return "cloud.snow"
        case 701...781:
            return "cloud.fog"
        case 800:
            return "sun.max"
        case 801...804:
            return "cloud.bold"
        default:
            return "cloud"
        }
    }
}
```



#■func paseraJSON(weatherData: Data)を改造

デコードして保存したnameやtempやidなどを
ここで取り出し変数にいれて
新たなstructに入れ込む
返り値を持して 全てデータを入れ込んだstructを返す
  
``` swift
func paseraJSON(weatherData: Data) -> WeatherModel?{

let json = JSONDecode()

do{
         let decodeData =  json.decode(weatherData.self,flom:データ名)
         let name = decodeData.name
         let temp =  decodeData.main.temp
         let id = decodeData.weather[0].id

let weather = WeatherModel(cityName: name , temperatrue: temp, conditionID: id )
return weather

} catch {  

     print(error)
　return nil
}
```


後はsession.dataTaskメソッドの中のタスク等で データを入れたpaseraJSONメソッドを 使用する。
BulletinBoardを使ってiOSの半モーダルビューを再現

# はじめに
BulletinBoardを使ってAirPods同期のときとかに出てくる半モーダルビュー?(正式名称不明)を再現します
↓これ
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237483/7b92f538-cdc3-dc94-3d05-d1756af31138.png" width=30%>

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [BulletinBoardのインストール](#bulletinboardのインストール)
1. [BLTNPageItemの作成](#bltnpageitemの作成)
1. [BLTNPageItemのボタンにHandlerを設定](#bltnpageitemのボタンにhandlerを設定)
1. [BLTNItemManagerの作成](#bltnitemmanagerの作成)
1. [BLTNItemAppearanceを設定](#bltnitemappearanceを設定)
1. [コード全体](#コード全体)
1. [完成](#完成)

<a id="#インストール"></a>
# BulletinBoardのインストール
CocoaPods

```Podfile.
pod 'BulletinBoard'
```

Carthage

```Chartfile.
github "alexaubry/BulletinBoard"
```

<a id="#作成"></a>
# BLTNPageItemの作成
```swift
let item = BLTNPageItem(title: "AirPods Pro")
item.image = UIImage(systemName: "airpodspro")
item.actionButtonTitle = "一時的にオーディオを共有"
item.alternativeButtonTitle = "iPhoneに接続"
```

<a id="#作成"></a>
# BLTNPageItemのボタンにHandlerを設定
```swift
item.actionHandler = { _ in
    print("actionButton押された")
}

item.alternativeHandler = { _ in
    print("alternativeButton押された")
}
```

<a id="#作成"></a>
# BLTNItemManagerの作成
```swift
let manager = BLTNItemManager(rootItem: item)
manager.showBulletin(above: self)
```

<a id="#設定"></a>
# BLTNItemAppearanceを設定
BLTNItemAppearanceを変更すると見た目を変えれます

```swift
item.appearance.actionButtonColor = .lightGray
item.appearance.actionButtonTitleColor = .black
item.appearance.titleTextColor = .black
```

<a id="#作成"></a>
# コード全体

```swift
class ViewController: UIViewController {
    
    var manager: BLTNItemManager = {
        let item = BLTNPageItem(title: "AirPods Pro")
        item.actionButtonTitle = "一時的にオーディオを共有"
        item.alternativeButtonTitle = "iPhoneに接続"
        item.image = UIImage(systemName: "airpodspro")?.resize(size: CGSize(width: 350, height: 350))
        item.appearance.actionButtonColor = .lightGray
        item.appearance.actionButtonTitleColor = .black
        item.appearance.titleTextColor = .black
        
        item.actionHandler = { _ in
            print("actionButton押された")
        }

        item.alternativeHandler = { _ in
            print("alternativeButton押された")
        }
        
        return BLTNItemManager(rootItem: item)
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    @IBAction func show(_ sender: Any) {
        manager.showBulletin(above: self)
    }

}
```
<a id="#完成"></a>
# 完成

　　　　　　　　　←理想　現実→
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237483/7b92f538-cdc3-dc94-3d05-d1756af31138.png" width=30%><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237483/a4da4e3b-a63b-c608-d98a-2dbac3b74070.png" width=28%>

ありがとうございました。
巨大なGitリポジトリの git clone に失敗する場合の対処法


# これは何？

```sh
$ git clone [巨大なリポジトリ]
```

の実行結果が `fatal: the remote end hung up unexpectedly` というエラーになってしまい、クローンに失敗する場合の対処法をまとめてみました。

# 対処法

## Step1. postBuffer の拡張

http.postbuffer の設定値が小さすぎることが原因の場合があるので、拡張します。

```sh
$ git config --global http.postbuffer 4M
```

4M〜16M あたりまで試して無理なら、この対処法での解決は諦めて、次のStepに移ります。

## Step2. リポジトリの最新断面だけを取得する

Step1だけで解決しない「巨大なリポジトリ」は、経験的には5年以上継続して追加修正の開発が行われているような歴史のある（或いは歴史は長くないがコミットされているファイルのサイズが大きい）リポジトリであることが多いように思われます。

解決方法としては、まず最初に最新の断面だけを取得し、過去のコミットログが必要であれば、徐々に遡りながら何度かに分けて取得するアプローチをとります。

リポジトリの最新断面だけを取得する。

```sh
$ git clone --depth 1 [巨大なリポジトリ]
```

main（旧: master）ブランチ以外のブランチに関する最新断面も取得しておきたい場合は、次のコマンドです。

```sh
$ git clone --depth 1 --no-single-branch [巨大なリポジトリ]
```

最新断面だけ取得すれば、今後の開発が続けられるとか、最新断面だけが欲しいという用途であれば、これで完了です。

過去のコミットログをすべて取得したい場合は、次のStepです。

## Step3. データ取得範囲を限定して徐々に過去のコミットログを取得する

最新断面のみをcloneした対象のリポジトリの過去のコミットログを遡及して取得するには、やりかた色々ありますが、ここでは2パターン紹介しておきます。

まずは、clone したディレクトリに移動しておきます。

```sh
$ cd [Step2.で clone した巨大なリポジトリ]
```

### 残りのコミットログをすべて取得する

残りのコミットログが一気に取得できるサイズであれば、このコマンド一発で済みますが、そもそもリポジトリ全体を `git clone` できなかったような巨大リポジトリなので、これを先に実行しても同様のエラーになると思います。

```sh
$ git fetch --unshallow
```

次の手順を一定程度繰り返した上で、残りを一気に...みたいな使い方ができる、という参考までに載せておきます。


### コミット数を指定して徐々に取得する

例えば、1000コミット分ならエラーにならずに取得できるサイズだとして「更に1000コミット分の履歴を遡及して取得する」というコマンドが以下のコマンドです。

```sh
$ git fetch --deepen 1000
```

これをループ処理で実行するなどして、小刻みにコミットログを過去に遡及して取得していく、というアプローチです。

```loop-sampl.sh
while true
do
  git fetch --deepen 1000
done
```

最終的にすべてのログを取得し終えて、これ以上取得するログが無くなった場合は、上記コマンドの結果が

```
remote: Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
```

となります。サンプルの無限ループは終了条件をサボっているので、 `Ctrl + C` で止めてください。

以上で、めでたしめでたし、です。

## 参考サイト

https://zenn.dev/snowcait/articles/d44d6b2bed2e4b29ada4
[Bootstrap] table の 列 を非表示にする(レスポンシブ対応)

##環境設定
Ruby 2.6.6
Rails 6.1.2.1
slim
Bootstrap5


##躓いたところ
・Bootstrap で table 作成時に境界線が直線にならない(画像内First Columnの下)
[bp ≧ 768px(md)]
![スクリーンショット 2021-04-14 22.46.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561297/aa80e3f1-b667-bc93-5127-979a37b77467.png)
[bp < 768px ]
![スクリーンショット 2021-04-14 22.55.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561297/746105ec-024b-d917-b9c2-58be59ed2634.png)

```slim:*.html.slim
.container
  .row
    .col-12
      table.table
        thead
          tr
            th scope="col"
              p #
            th.d-none.d-md-block scope="col"
              p First
            th scope="col"
              p Last
            th scope="col"
              p Handle
        tbody
          tr
            th scope="row"  
              p 1
            td.d-none.d-md-block
              p Mark
            td
              p a
            td
              p b
          tr
            th scope="row"  
              p 2
            td.d-none.d-md-block
              p Mark
            td
              p c
            td
              p d

```

##解消方法

```:*.html.slim
- td.d-none.d-md-block
+ td.d-none.d-md-table-cell
```

##背景・原因など
・任意の画面幅の大きさの時に、テーブルセル(tr,td)を表示する場合は、

```slim:slim
tr.d-[ブレイクポイント(md/lgなど)]-table-cell"
```

・"bootstrap table 列 非表示" でググるも期待した結果を得られず..
 -> "bootstrap table column hide"で解決策を見つけた。

・あとで"bootstrap table 列 非表示 レスポンシブ"で検索したら出てきた。言葉足らずでした...

##参考URL
https://getbootstrap.jp/docs/5.0/utilities/display/#notation

https://stackoverflow.com/questions/48292516/hide-table-columns-using-bootstrap-4
Veturがうまく動かない。files.associations正しく書きましたか？

VSCodeでVeturがちゃんと動かなくてVueファイルの中でTS書くと

    Type annotations can only be used in TypeScript files.

とか出るんですよ。「なんでだ、なんでだ」とさんざん調べた結果、原因は拡張子vueのファイルがhtmlとして認識されていたからでした。

VSCodeのsettings.jsonがこうなってた。↓

```json
    "files.associations": {
        "*.vue": "html"
    }
```

こうしたらなおった。↓

```json
    "files.associations": {
        "*.vue": "vue"
    }
```

なんだよhtmlって。そんなの書いた覚えないんだけど…。（書いたんだろうけど）

settings.jsonを手書きしなくてもVSCodeのSettings[⌘,]からCommonly UsedのFiles: Associationsでも設定できます。
![スクリーンショット 2021-04-15 0.38.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164374/b603bd06-258b-64d3-a629-6b1cf2c8eb75.png)
いくらググってもこの情報が出てこなかったのはそんなところでハマる人がいないからなんだろうけど、もしもどこかに同じ内容で困っている人がいたら是非ここに辿り着いてほしい。ではでは。
railsでruby組み込みライブラリを拡張する


任意のフォルダに拡張ファイルを配置

```ruby:lib/core_ext/string.rb
class String
  def hoge
    self+" fuga"
  end
end
```


'config/initializers'配下に以下のようなファイルを配置

```ruby:config/initializers/core_ext.rb
Dir.glob(File.join(Rails.root, 'lib', '*_ext', '*.rb')) do |file|
  load file
end
```

これで Strinig.hoge が使えるようになった。
以下がとても参考になった
https://dev.classmethod.jp/articles/ruby-object-to-boolean/
インターフェースについて

`インターフェース`というよく聞くけど、正しく理解できてない言葉の解像度を深めようと思います。ただ、あまり踏み込みすぎず、あくまでも基本だけに留めます。

まずは、英語としての意味から、

```
interface
〔異質な物の間の〕接合部分、接触［境界］面［部・領域］
接点、仲立ち、連絡（係）、橋渡し（役）

結び付ける、結合させる、つなぎ合わせる
```

###ようするにインターフェースは、「つながりの部分、橋渡しの部分」と解釈していいかなと思います。

「何」と「何」をつなぐのかによって以下のように区別がつけられています。

**ハードウェアインターフェース**：機械と機械をつなぐ
・USB、マウス、キーボード、プリンター、外付けHDD
・パソコンと液晶ディスプレイを接続するHDMI


**ソフトウェアインターフェース**：プログラムとプログラムをつなぐ
・OS
・ミドルウェア
・プラグイン
・API

**ユーザーインターフェース**：人とデバイスをつなぐ
・人が使う装置全般

とまぁ色々あります。

ウェブの世界に関わりの深いインターフェースと言えば間違いなくこの２つですね。
**API**：Application Programming Interface
**UI**：User Interface


**API**
ソフトウェア同士が互いに情報をやりとりするのに使用するインタフェースの仕様。
外部に向けて公開することにより、第三者が開発したソフトウェアと機能を共有できるようにしてくれる。

**UI**
UIと呼ばれるものは人間が使うもの全部と考えていいらしいのですが、ウェブの場合は、ユーザーが実際に触る画面です。特にボタンとか入力フォームとか**何かしらの操作**に使う部分が重要です。

では、マウス、キーボードなどもユーザーインターフェースなのかなと思いましたが、ヒューマンインターフェース（人間が機械を操作するための道具）と呼ばれているそうです。

**では、UXは？**
ユーザーインターフェースなどを通して得られる 機器やソフトウェアの有効さ、効率、満足度の総合的な指標を ユーザビリティ、購入前・利用前の期待感から利用後までの印象を含む より包括的な概念を ユーザーエクスペリエンス、略して UXといいます。

以上簡単ですがまとめてみました。要はインターフェースは「つながり・接点」と言う事ですね。
APIに関してはもっと掘り下げて別で記事にまとめたいと思います。
Fragmentのwidth, heightの簡単な取得方法

#はじめに
FragmentのonActivityCreated等でビューの横幅、高さを取得しようとすると0が返ってくると思います。

これはビューの大きさが確定する前に取得しようとしているのが原因なのですが、
この解決策として、今までOnGlobalLayoutListener#onGlobalLayout()を使用していました。

ただこの方法ですと、コード量がちょっと多いです。
postを使ってより短く書ける方法がありましたので、そちらを共有します。

#環境
AndroidStudio 4.1
kotlin 1.3.72

#コード
```kotlin
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import androidx.fragment.app.Fragment
import com.example.kotlinsample.R

class SampleFragment : Fragment() {

    companion object {
        private const val TAG = "SampleFragment"
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_sample, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        // 0. 対策なし
        Log.d(TAG, "[0] width${view?.width}, height:${view?.height}")

        // 1. OnGlobalLayoutListenerを使う方法
        var globalLayoutListener: ViewTreeObserver.OnGlobalLayoutListener? = null
        globalLayoutListener = ViewTreeObserver.OnGlobalLayoutListener {
            Log.d(TAG, "[1] width${view?.width}, height:${view?.height}")

            // リスナ解除
            view?.viewTreeObserver?.removeOnGlobalLayoutListener(globalLayoutListener)
        }
        view?.viewTreeObserver?.addOnGlobalLayoutListener(globalLayoutListener)

        // 2. postを使う方法
        view?.post {
            Log.d(TAG, "[2] width${view?.width}, height:${view?.height}")
        }
    }
}
```

#結果
```
[0] width0, height:0
[1] width1080, height:1776
[2] width1080, height:1776
```
対策なしで取得した場合が0になり
OnGlobalLayoutListenerを使う方法、postを使う方法で横幅、高さが取得できました。

常に正しく取得できるかは未検証ですが、コード量がシンプルになるので積極的に使っていきたいですね。
CGMサービスでユーザ独自のGAを利用させる設計手法について

[先日リリースしたドクセル](https://qiita.com/ku_suke/items/7702c7b25aa31672a2bf) ですが、本日ユーザが自身のGoogleAnalyticsを設定して、スライドのアクセス解析を行えるようにしました。その方法について、CGMサービスではどのように設計するのがよいかという事例の一つになると考え、Qiitaで記事にしました。

> なお、Qiita様に置かれましては、ドクセルの埋め込みパーツ対応をいただけますよう切に願っております。Zenn、Connpass、PR TIMES様にも対応いただけないかのお願いを不躾ながら投げ込みさせていただいております。なにとぞ前向きなご検討をお願いいたします・・！！

# 作った機能概要

今回もベースをmikkameさんが爆速で作った後、僕の方でユニバーサルアナリティクスとGA4の切り分け対応を以下の方法で対応しました。

![20210414-exg9b プロフィール編集 _ ドクセル - Google Chrome.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8727/79e377bf-834d-e194-7eb3-2046540d2a6a.png)

このようなフォームに自身のGAIDを記入すると、ご自身のスライドを誰かが閲覧したときにGAによるページビューの送信が行われます。ついでにスライドをめくったタイミングでもページビューになるようにしてみました。

# 基本的な構成

基本的には、ユーザにGAのID（ユニバーサルアナリティクスならUA-XXX、GA4ならG-XXX）をフォームに記入いただいて、その有無でGAを追加起動するか判断します。

その際の起動ルールとしては、直接ページルールとして設定するのではなく、GTM（Google Tag Manager）を使って設定を行います。

https://tagmanager.google.com/?hl=ja

このGTMというものは簡単に言うと、アクセス解析や広告測定用のJSを、管理画面から追加投入できるシロモノなのですが、様々な条件でタグを発火させる・させないの制御が可能になっています。

そこで、今回はGTMに用意されているdataLayerという仕組みを利用しました。dataLayerにスライド作成者がGAのIDを設定している場合はそれをセットし、GTM側でセットされている場合はGoogle analyticsのページビューイベントを発火させるという設定を行ったわけです。

# ユニバーサルアナリティクスとGA4の違いを吸収

基本的には上の通りなのですが、現在Google AnalyticsはGA4が出たばかりでして、世の中のWebマスターの皆様はどちらも使っている場合があります。見分け方はそれぞれプロパティというかIDが、 `UA-` から始まるのか、 `G-` から始まるのかという点です。

今回はその違いを持って発火し分けることにしました。

まず、それぞれのタグを用意し、トリガーの欄にページビュー、条件をすべてのページビューではなく一部のページビューを選択します。すると条件を選択できる欄があるので、 `dataLayer変数XXXXXXがUA-と前方一致する` というような条件を書くのです。

すると、dataLayer変数がない（スライド作成者が設定していない）場合は何も起こらず、UA-から始まるIDを設定している場合はユニバーサルアナリティクスのタグを発火、G-から始まるIDを設定しているユーザはGA4のタグを発火という設定が可能になります。

文字で説明するとわかりにくいのですが、こんな感じです。

![20210415-afnnf Google タグ マネージャー - Google Chrome.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8727/d5446b88-a553-b76b-a394-12e74af0f30a.png)

一番上が運営側のGA4、その下２つがGA4とユニバーサルアナリティクスを切り替えている個所になります。なお、トリガーがもう一つあるのは、ページがロードされた時ではなく、スライドがめくられてhashchangeイベントが発生した段階でもページビューを飛ばすための設定です。hashchangeだとわかりやすいのですが、日本語環境だと「履歴の変更」となっている点が注意ですね。

# まとめ

このように、アクセス解析というプロダクトの本筋ではない機能はできるだけ外部の管理機能に追いやることで、プロダクトの設計をすっきりさせることができます。

また、現在このようなCGMサイトにおけるGA対応のコードを利用させる場合、GA4とユニバーサルアナリティクスの混在に対応する必要があるでしょう。間違ってもユーザに自由にScriptタグを書かせて好きなアクセス解析コードを埋め込めるようにしてはいけません。サイトの作りにもよりますが色々取れちゃいますからね。

今後は、法人向けに各種MAツールに対してコンバージョンを飛ばせるような機能を作っていきたいと思いますが、この機能の応用で作れるため、プロダクトチームは単にdataLayerに変数をはいておけば後のことは知らないと責務を分離することが可能になります

それでは、今後ともドクセルをよろしくお願いたします！

https://www.docswell.com
【Swift】UITableViewを下から描画する（LINEのトーク画面・ライブ配信のコメントみたいに

UITableViewを使ってトークアプリのように下からアニメーションを使ってCellを追加する方法をご紹介します。

⬇️ 作りたいのはこんなレイアウトです
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305854/cb58c8ad-1e61-0945-f323-6b027cace900.gif" width=30%>

## 実装
やり方はとても簡単です！

1. UITableViewをアフィン変換を使って回転させる
2. UITableViewCellをアフィン変換を使って回転させる
3. 必要に応じてCellの追加をアニメーションぽくする

### 1. UITableViewをアフィン変換を使って回転させる
```CustomTableView.swift
class CustomTableView: UITableView {
    // レイアウトのイニシャライザで呼ぶ
    // これでTableViewの上下が逆転する
    func setTransform() {
        transform = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: 0)
    }
}
```

### 2. UITableViewCellをアフィン変換を使って回転させる
1のままCellを描画すると上下が反対のままになってしまっている。
⬇️ 実際に描画したらこんな感じ
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305854/8f9ef409-df82-f81c-3bfd-8058bdc9f077.jpeg" width=30%>
これを直すために、Cellの描画時にアフィン変換を行ってCellを回転させます！

```CustomTableView.swift
// cellForRowAtで行う
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: R.nib.customCell.identifier, for: indexPath) as! CustomCell
    cell.transform = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: 0)
    return cell
}
```

### 3. 必要に応じてCellの追加をアニメーションぽくする
新しいCellが追加された時に、`reloadData()`をするとTableView全体が再描画されるため、追加されたCellだけいい感じにアニメーションっぽく追加させます。

```swift
func addItem(_ item: Item) {
    // TableViewはitemsを元に描画されています。
    // 今回は下から追加したいのでIndexPath(row: 0, section: 0)ですが、任意の場所に設定してください
    items.insert(item, at: 0)
    beginUpdates()
    insertRows(at: [IndexPath(row: 0, section: 0)], with: .automatic)
    endUpdates()
}
```

これで最初に紹介したようなTableViewの完成です✨
（そのうちサンプル作ろうとは思いますが、いつになるか未定…
huskyを使っているプロジェクトでApp Engineへのデプロイが失敗するときの対処法

# 現象
コミット時に lint を走らせるために husky を設定しているプロジェクトも多いと思います。
huskyを設定すると npm scripts に`"prepare": "husky install"`が設定されます。
これにより、`npm install`などが走ったあとに`husky install`が実行されるため、 全開発メンバーが git-hooks を割と確実に設定することができるようになります。
しかし、この npm scripts のせいで、App Engineへのデプロイ中に以下のエラーがでるようになってしまいました。

```bash
husky: not found
```
この対処法を思いついたので、備忘録として記事に残します。

# 環境
- Mac
- Node 14
- husky 6.0.0

# 解決方法
```json:package.json
"prepare": "node --eval 'process.exit(process.env.NODE_ENV === `production` ? 0 : 1)' || husky install",
```
日本語にすると「NODE_ENV環境変数がproductionではないときだけ`husky install`を実行する」となります。APP Engineでは`NODE_ENV=production`が設定されているため、`husky install`がスキップされます。

# 解説
## node --eval
JavaScriptのコードをインラインで実行することができます。

```bash:例
node --eval 'console.log("foo")'
# -> foo
```

## process.exit(process.env.NODE_ENV === `production` ? 0 : 1)
NODE_ENV 環境変数が `production` のとき、正常終了し、そうでない場合は、終了コード1を出して失敗します。

## ||
前のコマンドが失敗したときに、後ろのコマンドを実行します。

# まとめ
App Engineは強い。
Progate railsコース1・2まと

rails g controller home top
これで、homeコントローラーとtopアクションが作れる。
さらに、viewsファイルにtop.html.erbができる。
同じ名前のコントローラーファイルなどは作れない。
さらに、同時にscssファイルも作られる。

画像はpublicディレクトリに保存しておくと、
簡単に指定してHTML内で使える。

リンクの作り方
同じサイト内のリンクは、ルーティングのURL部分と同じに指定すると、リンク先を指定できる。

stylesheets内のcssにコードを書けば、全てのviewに適用される。
コントローラーごとなどに役割を分けてcssを描いた方が良い。

アクションに変数を定義する。
変数の定義は、通常アクショ内に定義する。
書き方は
＠変数　＝　["なんたら","なんちゃら"]
のように書く。
注意
＠変数のように書く意味は、通常アクションで定義した変数はviewで使えないが、＠から始めることでビューでも使用できる特殊変数になるから。

viewに変数を定義or変数を使う
viewで変数を定義する時は、
<% 変数　＝　"なんたら"  %>
のように書く。
アクションや、views内で設定した変数を使う時は、
<% = 変数 %>
のように、％の横に＝を書いて使う。
＝をつければ、Rubyコードの中身を表示、
　　つけなければ、変数の定義と思えば良い。

データベースにデータを保存する方法
まず、データベースに変更を指示できる、
マイグレーションファイルとテーブルを作成する。
rails g model Post coetent:text
のように書く。
postsテーブルを作成する場合、上のようにPostと単数形にする。
content:textは、
コンテンツカラムが作られ、そこにはtext(長い文字列)が入るということを意味してる。
このコマンドを実行すると、dbディレクトリのmigrateディレクトリにpostsテーブルに関する
マイグレーションファイルが作成される。
rails g modelの際にすでに、Postモデルが生成されている。

注意
このコマンドを実行したあと、ターミナルで
rails db:migrateとすると、マイグレーションファイルを読み込み、マイグレーションの指示通りにテーブルを作ってくれる。
データベースに反映されてないマイグレーションファイルrails db:migrateをしないとマイグレーションエラーが発生するから、かならずしなければいけない

ApplicationRecordを継承したものをモデルという。
ApplicationRecordら、データベースにRubyでアクセスできるActiveRecordクラスを継承してるから、モデルはRubyのコマンドでデータベースにアクセスするためのファイルということになる。

簡単にまとめると、
rails g model Post content:textを実行すると、
1.post.rbという、postモデルが定義されたファイルと、
2.データベースの設定や変更を書くためのposts.rbマイグレーションファイルの二つができる。
そして、最後にrails db:migrate
することによって、postテーブルが作られる。

ApplicationRecordを継承しているのでRailsでは
saveメソッドでデータベースに保存できる。

post = Post.firstのPostのようにデータベースにアクセスする時なぜ最初大文字なのかと言うと、モデルファイルに定義されてるクラスが大文字だから。

全てのindexデータをデータベースから自動で取り出して、表示する方法
id順に表示される


Rails内の共通のHTMLは、
views/layouts/application.html.erb
にまとめて共通のレイアウトとして書いておける。ここに書けば、サイト全体に適用される。
APIGatewayでカスタムドメイン利用時に繋がらない問題で同じ轍を踏んだのでメモしておく

あ〜もう。むっちゃやることたくさんあるのにつまんないことでハマったのでメモしておきます。これ絶対また同じ轍を踏むので。

## 現象
APIGatewayでカスタムドメイン利用時、何度設定を見直しても正しく繋がっているはずなのにAPI叩くと

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140599/4775f28d-8f74-2f29-a341-bcfa7333bc61.png)

`403 Forbidden`が返ってくる。しかも認証もしていないAPIなのに`Missing Authentication Token`ってなんだよ･･･
どのAPI叩いても403ですよ。。。とほほ。

## 原因
調べてみると[Developers.ioの2015年！の記事](https://dev.classmethod.jp/articles/api-gateway-with-custom-domain/)にあたりました。
>(本来は入力必須ではありませんが、後述の理由から必ず入力してください）

もうClassmethodさんには足向けて寝ません。
API Gatewayの独自ドメイン設定で、ベースパスマッピングを指定しないとAPIに繋がらないという~~バグ~~仕様でした

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140599/83b39fa2-b4c1-8c3e-96f9-f90260a8559e.png)

上記赤丸で囲った箇所を省略すると403が返ってきますorz
ってかこれ2015年からずっとあるからもう仕様だよね。（オプション）って書いてあるけど必須項目だよね・・・

ってなわけで、ここには値を設定してください。**絶対に!!**

## 設定場所
最近またコンソールの画面が変わったので迷える子羊ちゃんたちのためにも今現在（2021年4月15日現在）のスクショで設定場所を貼っておきます。

1. APIGateway→カスタムドメイン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140599/2efea502-26de-506c-b4b1-5098187f0281.png)

2. APIマッピングタブを押す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140599/867ef325-ad1e-a434-976f-8736a4e6925f.png)

3. APIマッピングを設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140599/46acbdb8-b526-2010-d17e-1611032dbc5e.png)

4. パス（オプション）欄に値を設定しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140599/83b39fa2-b4c1-8c3e-96f9-f90260a8559e.png)

5. この手順で設定を行い、**APIのデプロイを忘れずに実行する**と

```
https://customdomain/パス（オプション欄に設定した値)/apiリソース
```

でアクセスできます。
昔リリースしたシステムの設定を見てみたらちゃんと設定してあったので多分**数年前の自分も同じ轍を踏んでいた**と思います。
【JavaScript基礎】文字列を検索するメソッド

JavaScriptにおける「文字列を検索する」メソッドについて、自己の忘備録としてまとめています。

## 参考URL
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference

## 参考著書
https://www.amazon.co.jp/JavaScript-%E3%82%B3%E3%83%BC%E3%83%89%E3%83%AC%E3%82%B7%E3%83%94%E9%9B%86-%E6%B1%A0%E7%94%B0-%E6%B3%B0%E5%BB%B6/dp/4297103680/ref=sr_1_7?dchild=1&keywords=javascript&qid=1618412284&sr=8-7

## 文字列の検索①　〜インデックスを調べる〜

文字列がどの位置にあるかを調べたい時に使用するメソッドです。

### indexOf()
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf

indexOf（）メソッドは、「対象の文字列」から「検索する文字列」が最初に現れたインデックス（位置）を返します。
__インデックスは０から始まり、値が見つからない場合は−１を返します。__

```js
const myStr = 'JavaScriptの基礎';

//  検索した文字が含まれる場合
const result1 = myStr.indexOf('JavaScript');
console.log(result1); // 結果:0

const result2 = myStr.indexOf('基礎');
console.log(result2); //結果：11

//検索した文字が含まれない場合
const result3 = myStr.indexOf('CSS');
console.log(result3); //結果：-1

const result4 = myStr.indexOf('j')
console.log(result4); //結果：-1  => 大文字と小文字が区別されるため
```

### lastIndexOf()
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/lastIndexOf

lastIndexOf（）メソッドは、「対象の文字列」から「検索する文字列」が最後に現れたインデックス（位置）を返します。



```js
const myStr = 'JavaScriptの基礎';

const result1 = myStr.lastIndexOf('a');
console.log(result1); //結果：3
```

検索開始インデックスを指定すると、指定されたインデックスから検索します。
インデックスを省略した場合は、検索開始のインデックスは０となります。

```js
const myStr = 'JavaScriptの基礎';

const result1 = myStr.indexOf('JavaScript', 3)
console.log(result1); //結果：-1
```

### search()
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/search

search()メソッドは、正規表現で一致するかどうかを調べるメソッドです。

```js
const myStr = 'JavaScriptの基礎';

const result1 = myStr.search(/JavaScript/)
console.log(result1); //結果：0

const result2 = myStr.search(/CSS/)
console.log(result2); //結果:1-
```

## 文字列の検索②　〜含まれているかを調べる〜

文字列が含まれているか調べたい時や、入力フォームなどで不適切な語句が含まれていないかを調べるときに使用します。

### includes()
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/includes

includes()メソッドは、文字列がどこかに含まれている場合にtrueとなります。

```js
const myStr = 'JavaScriptの基礎';

const result = myStr.includes('JavaScript')
console.log(result); //結果：true
```

### startsWith()
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith

startsWith()メソッドは、文字列の最初が引数と同じであるかどうかを調べます。

```js
const myStr = 'JavaScriptの基礎';

const result1 = myStr.startsWith('JavaScript');
console.log(result1); //結果：true

const result2 = myStr.startsWith('基礎');
console.log(result2); //結果：false
```

### endsWith()
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith

endsWith()メソッドは、文字列の末尾が引数と同じであるかどうかを調べます。

```js
const myStr = 'JavaScriptの基礎';

const result1 = myStr.endsWith('JavaScript');
console.log(result1); //結果：false

const result2 = myStr.endsWith('基礎');
console.log(result2); //結果：true
```
pycopg2のインストールエラーとopensslについて

psycopg2をインストールしようとした際に下記エラーが発生

```
ld: library not found for -lssl
clang: error: linker command failed with exit code 1 (use -v to see invocation)
error: command 'clang' failed with exit status 1
```
どうやらpsycopg2がC言語ベースの拡張モジュールなので、コンパイル作業が行われるわけですが、その際にリンカがsslライブラリを見失っている、というのがエラーの原因のようです。
ですので、このリンカが参照する箇所を環境変数として指定してあげれば良いようです。

C言語をやっているとmakefileなんかで指定する下記のフラグ

```
export LDFLAGS="-L/usr/local/opt/openssl/lib"
export CPPFLAGS="-I/usr/local/opt/openssl/include"
```
をそれぞれ指定します。
なおopensslなどがインストールされていない場合は適宜インストールしてください。
簡単に言うと（というか簡単にしか理解できてない）、LDFLAGSはリンカ（LD)が参照するフラグを指定し、
CPPFLAGSはC/C++が参照するフラグです
※Cのみの場合はCFLAGSですかね。psycopg2の中身を見たわけではないのでCPPFLAGSの方が無難かなと思ってます

これで再度brewなりpipなりでpsycopg2をインストールすればきっと成功するはずです。

#参考
PostgreSQL12.5でDB2台の非同期レプリケーションの設定

#◆概要
PostgreSQL12.5でDB2台の非同期レプリケーションの設定をする
##前提
2台のサーバにインストール済み。
　マスタ：192.168.11.110
　スタンバイ：192.168.11.111

#1.マスター側ホストの設定
##postgresql.confの設定
```
vi /var/lib/pgsql/data /postgresql.conf
```
 59行目：コメント解除して変更
```
listen_addresses = '*'
```
 193行目：コメント解除　レプリケーションを有効にする
```
wal_level = replica
```
 198行目：コメント解除　スタンバイサーバーの同期レベルを設定
```
synchronous_commit = on
```
 286行目：コメント解除 レプリケーションリクエストを受ける接続最大値
```
max_wal_senders = 10
```
 288行目：コメント解除して変更 アーカイブログのファイルセグメント数の最小値
```
wal_keep_segments = 10
```
 300行目：コメント解除して変更	同期サーバを指定なし（全て受付）にする。
```
synchronous_standby_names = '*'
```
##pg_hba.conf設定
　最終行にレプリケーション用サーバの許可を指定する
```
vi /var/lib/pgsql/data /pg_hba.conf
```
 最終行：既存設定はコメント化して追記 (接続許可の設定)　スタンバイサーバのIPとユーザを記載する

```
# host replication [レプリケーションユーザー] [接続許可IP] [認証方式]
#host    replication     all             127.0.0.1/32            ident
#host    replication     all             ::1/128                 ident
host    replication     rep_user        192.168.11.111/32        md5
```

##レプリケーション用ユーザ作成。
　スタンバイサーバからログインするユーザ
　レプリケーション権限とログイン権限を付与する

```
su – postgres
psql
CREATE ROLE rep_user replication LOGIN; 
\q
exit
```

##DB再起動
``` 
systemctl restart postgresql.service
```

起動しない場合は、設定ファイルを再確認すること

#2.スレーブ側ホストの設定
　・サービス停止
```
systemctl stop postgresql.service
```

　・既存データを削除。–rf ディレクトリを対象、メッセージ非表示
```
rm -rf /var/lib/pgsql/data
```

・マスタからバックアップ取得。実行するユーザに注意
```
su - postgres
pg_basebackup -R -h 192.168.11.110 -U rep_user -D /var/lib/pgsql/data -P
```

・スレーブ用ファイルを配置　これが無いとマスタで起動する
```
touch /var/lib/pgsql/data/standby.signal
```

##・postgresql.confの設定
```
vi /var/lib/pgsql/data/postgresql.conf
# 59行目：コメント解除して変更　接続できるアドレス
listen_addresses = '*'
#310行目　スタンバイサーバがプライマリサーバに接続するための接続文字列を指定
primary_conninfo = 'host=192.168.11.110 port=5432 user=rep_user application_name=node01'
# 315行目：コメント解除　ホットスタンバイを有効にする
hot_standby = on
#ホットスタンバイのフィードバックを有効にする。なくてもよさそう
hot_standby_feedback = on
```

再起動する
```
systemctl start postgresql-12.service
```

マスタ側でデータ投入して反映確認する

以上

★更新履歴 
21/4/14 新規作成
24/12/31 微修正
楽してAndroid/iOSアプリ個人開発

# はじめに

どうも、@nittannittanです。

趣味でAndroid/iOS/Webアプリを作成しているアニメオタクです。

今まではAndroid/iOSアプリはそれぞれJava, Kotlin, Objective-c, Swiftなどの言語でそれぞれ開発していました。
しかし、どちらか一方を開発して公開したあとにまた同じようなことを繰り返すのは勉強にはなりますが、仕事の合間にやる個人開発ではあまり楽ではないなーと感じていました。

そこで「最近マルチプラットフォームも流行ってきているようだし、そろそろ本腰を入れてみるかー」という軽い気持ちからFlutterでAndroid/iOSアプリを同時開発することにしました。

# Flutterを選んだ理由

Googleが開発しているからまずAndroidは間違いなく相性は良いだろうし、個人開発でFirebaseを使わないわけがないので、Flutterを採用しました。WebアプリでReact使っているわけでもないし、iOS版に対応していなかった時代を知っているのでReact Nativeは今回はやめました。

ReactでWeb開発してたらReact Nativeを選んだのかもしれません。

# 参考にしたサイト

まずはDartを知る必要があるため言語の公式ドキュメントをさらっと読みました。深くは読み込みません、私のやり方的に実際に手を動かして覚えるほうがやりやすくてわからなくなった時に再度読みます。手を動かさないとモチベーション維持も難しいですし、個人開発だとやる気が下がったらおしまいですからね。

https://dart.dev/samples

ぱっとソースを見た時に全然わからないと投げ出しそうになったUIの構築方法も公式のドキュメントを見たらあっさり理解できました。慣れたらxmlやStoryboardでUIを作るのが面倒に思えてきます。特にStoryboardはgitでの差分確認がよっぽどの超人じゃないとできないですしね。

https://flutter.dev/docs/reference/tutorials

私が作ろうとしていたアプリはTODOアプリの作り方が参考にできそうだったので下記を見ながらベースを作りました。

https://www.flutter-study.dev/

利用パッケージの参考にしたのは下記。

https://pentagon.tokyo/app/2937/#toc_id_3_1

https://qiita.com/kazumaz/items/876e162cf429014661d8

# 最終的に利用したパッケージ


```yaml:pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.0
  # MVVMで作るのに利用
  provider: ^4.3.3
  # データベースにデータ保存するのに利用
  moor: ^4.1.0
  sqlite3_flutter_libs: # Also use the latest version.
  path_provider:
  path:
  # アイコンを表示するのに利用
  flutter_icons: ^1.1.0
  # ダイアログの見栄えを良くするのに利用
  awesome_dialog: ^1.3.2
  # アプリからブラウザを開くために利用
  url_launcher: ^6.0.3
  # 必要なアプリアイコンを自動生成するのに利用
  flutter_launcher_icons: ^0.9.0
  # スプラッシュ画面を自動生成するために利用
  flutter_native_splash: ^1.1.5+1
  # Firebase関連
  firebase_core: ^1.0.2
  firebase_analytics: ^7.1.1
  firebase_crashlytics: ^1.0.0
  firebase_auth: ^1.0.3
  google_sign_in: ^5.0.1
  # GoogleDriveにバックアップファイルを保存するのに利用
  googleapis: ^2.0.0
```

# 楽したポイント

## moor

AndroidとiOSで差が出やすかったデータベースへのデータ保存もパッケージを利用することで簡単に対応できました。何も悩まずにマルチプラットフォームでデータ保存が実現できたのは衝撃的でした。

https://moor.simonbinder.eu/docs/getting-started/starting_with_sql/

https://qiita.com/niusounds/items/e4d731af58201ad5fe6f

## awesome_dialog

参考サイトでも紹介されていたパッケージですが、こちらも少ない工数でダイアログの見栄えが劇的に良くなるのでおすすめです。

https://pub.dev/packages/awesome_dialog

## flutter_launcher_icons

iOSアプリをApp Storeに公開したことがある人ならわかると思いますが、iOSアプリは用意しなければならないアプリアイコンの数がとても多いです。それを画像一つ用意するだけで自動設定できるのはまたまた衝撃的でした。Androidのアダプティブアイコンにも対応しているのでかゆいところに手が届きます。

https://pub.dev/packages/flutter_launcher_icons

## flutter_native_splash

このパッケージもスプラッシュ画面が画像一つで表示できるようにできるのでとても楽ができます。

https://pub.dev/packages/flutter_native_splash

# 開発したトラウマ解消アプリの紹介

トラウマ解消アプリは、ふとした瞬間にフラッシュバックするトラウマを認知行動療法によって解消するためのアプリです。

使い方は以下です。

+ まずは、トラウマがフラッシュバックした時にそのトラウマに名前をつけて保存しましょう。

+ フラッシュバックした時に詳細な情報まで記録できるとは限らないと思います。名前以外の詳細は時間があるときにゆっくり書き出しましょう。

+ トラウマに名前をつけたり、詳細を書き出すことによって客観的に考えを整理することができ決めつけでネガティブになっていたことに気がついたり、バランスがいい考え方ができるようになります。


https://play.google.com/store/apps/details?id=jp.nittan.trauma_buster

https://apps.apple.com/jp/app/id1561470464
ちょっとしたReactでのアニメーション

#ちょっとしたReactでのアニメーション

`※この記事は、ガッツリすごいアニメーションをやるものでは、ありません！`
TypeScriptでReactなどWebフロントを実装している際、ちょっとした変化を持たせたいなと思って書きました。
##ちょっとした変化
* 文字の色を変えたい
* 変位をゆっくりしたい
* 見た目の変化

HTML、CSSは、インターネットが始まって成長してきた言語です。
非常に簡単に書くことができる。
なので、色んな人が、様々な技巧でWebサイトを面白く、美しく見せてきました。
React、Vue などフレームワークが変わっても土台は、変わっていません。

##React で実装してみよう
細かいことは、置いといてどうやるのか？

```ts
import React, { useState } from "react";
import { css } from "emotion";
// css in js

export function Animation() {
  const [isFlag, setFlag] = useState(true);

  const color = isFlag ? "red" : "blue";
  const size = isFlag ? "100px" : "300px";
  const textcolor = isFlag ? "Black" : "White";

  const animation_style = css({
    width: size,
    backgroundColor: color,
    transition: "1s",
    color: textcolor,
  });

  return (
    <div className={animation_style}>
      <p>test</p>
      <button onClick={() => setFlag(!isFlag)}>Change</button>
    </div>
  );
}

```
上記のコードで、実行するとボタンを押すと`サイズ`が変化する。その変化は、`1秒`で行われます。

```
transition 
```
この要素は、変化にかかる時間を指定しています。
`CSS in JS`では、変数を組み込むことができるので、
CSSに変数を組み込んでboolなどで要素の状態を制御しています。

## あとがき
この書き方は、一般的なのかどうかは、知りません。
自分の考える動きを起こせるアニメーションのライブラリを探す過程で、よく先人のCSSの実装を説明しているサイトに行きます。

自分の環境で実現できるのであれば、こういった書き方で、ちょっとしたものは、実現して探す時間を他の作業に当てようと思いました。

## 参考ページ
https://developer.mozilla.org/ja/docs/Web/CSS/transition
Golangでスライスから最大値、最小値を取得する方法

#なぜ書いたか
Goにはmax関数とmin関数が用意されていないので。

#答え
ソートして頭かお尻を取れば良い。

```go
import "sort"

func max(s []int) int {
    sort.IntSlice(s).Sort()
    return s[len(s)-1]
}

func min(s []int) int {
    sort.IntSlice(s).Sort()
    return s[0]
}
```
Salesforce App bulider：AppExchange

#AppExchangeとは
アプリケーションや Lightning コンポーネント、フローソリューションなど、Salesforce のすべての機能が揃うマーケットプレイスです。

##AppExchangeソリューションの共通点
・Salesforceの機能を拡張します。
・他の人に配布することができます。
・Salesforceプラットフォームで実行します。
・ソリューション開発を加速します。

##コンポーネント
アプリケーション全体必要じゃなく、Webページ、アクション、ボタンなど機能別のみ利用したい場合、コンポーネント利用
###コンポーネント作成優先順位
標準機能実現可能＞AppExchange＞コーディング

##アプリケーションインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/c01ebe89-50a7-876b-d367-9a1c7799acf1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/b3121bf6-5c3b-7ebb-de99-58e34ef00dd8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/a6ceb1f8-131f-ad05-98cb-5a72ffed3a9c.png)
・salesforceログイン
　　省略
・インストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/7109312b-11da-c218-5d02-c20d413ddf66.png)
・インストール後利用
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/7fc0cd66-99c3-4515-cf90-5b4c1185291f.png)
Add [ ] to fillable property to allow mass assignment onの解決方法

laravelでレコード追加機能を実装しデータベース反映まで確認済みだったのですが、諸事情によりidのカラム名を変更後、再度レコード追加しようとした際に今回のエラーが発生しました。

```
Add ['カラム名'] to fillable property to allow mass assignment on
```

このエラーはデータベースにデータを保存する時に発生するエラーで、原因はEloquentで`Mass Assignment`の設定をしていないからのようです。

##`Mass Assignment (マス アサインメント)`とは
Webアプリケーションのアクティブなレコードパターンが悪用され、パスワード、許可された権限、または管理者のステータスなど、ユーザーが通常はアクセスを許可すべきでないデータ項目を変更するコンピュータの脆弱性。

Web上から入力されてきた値を制限することで不正なパラメータを防ぐ仕組みになっていて、laravelでは`Mass Assignment`の対策がされていることから今回のエラーが発生しました。

##解決方法
エラーで指摘されたモデルに、下記2つの方法でどちらかを設定することで解決できます。

`ホワイトリスト方式:保存したいカラム名を設定`

```
namespace App;
 
use Illuminate\Database\Eloquent\Model;
 
class モデル名 extends Model
{
    protected $fillable = ['name']; //保存したいカラム名が1つの場合
　  protected $fillable = ['name','price','number']; //保存したいカラム名が複数の場合
}
```

`ブラックリスト方式:書き込みを禁止したいカラム名を設定`

```
namespace App;
 
use Illuminate\Database\Eloquent\Model;
 
class モデル名 extends Model
{
    protected $guarded = ['name']; //１つのカラムを書き込み禁止
　  protected $guarded = ['name','price','number']; //複数のカラムを書き込み禁止
}
```

私の場合、今回はホワイトリスト方式でレコード追加時の入力項目であるカラムを全て設定したことで解決しました!



参考記事はこちら
https://qiita.com/mutturiprin/items/fd542128355f08727e45
https://nextrevolution.jp/add-to-fillable-property-to-allow-mass-assignment-on/
SceneKitで読み込んだUSDZのアニメーションを止める

自分で作ったUSDZファイルじゃない場合じゃない場合、中身はよくわからんけどとりあえずアニメーションして欲しくない時とかありますよね。ありますよね。

```swift
usdzNode.enumerateChildNodes { (node, pointer) in
    print(node.name)
    node.removeAllAnimations()
}
```

これで止まります。特定のnodeを止めたいときは、プリントしたnodeの名前であたりをつけてremoveAllAnimationsすれば止まります。

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)