QRコードで出勤管理システムを作成してみた

# 出勤管理システムを作成してみた

イメージはこんな感じです。これをログインして読み取れば時間とユーザーIDがデータベースに保存されます。

そもそもQRコードじゃなくても良くない？とかいう話は置いておいてください🙇‍♂️


![スクリーンショット 2023-05-12 12.08.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3324306/f42ef4a8-0788-319e-f6c2-38d18bfda1f1.png)

前提条件として、deviseでuserを作成しているので、`current_user`を使用できるようになっています。もちろん、自分でそれを実装するのも良いと思いますが、時間省略のために今回はdeviseを使用しました。

今回は出勤用に作成したので、退勤は用意していません。
ただ、退勤を作成するとしても、同じような流れなのですぐにできると思います。

# バージョン情報
ruby 2.6.3
Rails 5.2.8.1

# Gemのインストール
今回はQRコードの作成に、gemのrqrcodeを使用しました。
Gemfileにrqrcodeを追加して、`bundle install`を実行します。
```
#Gemfile
gem "rqrcode", "~> 2.0"
```

# モデルの作成
次にモデルを作成します。
userは外部キーとして関連づけ、到着時刻を日付も欲しいので`datetime`で保存します。
日付だけなら、`date`、時間だけなら`time`です。極論言えば基本は更新しないので、`timpestamp`でもいけそうですが。

```
rails g mode user:references arrival_time:datetime
```

```db/migrate/20230000000000_create_arrive_companies.rb
class CreateArriveCompanies < ActiveRecord::Migration[5.2]
  def change
    create_table :arrive_companies do |t|
      t.datetime   :arrival_time, null: false
      t.references :user, foreign_key: true

      t.timestamps
    end
  end
end
```

# ルーティングの設定
ルーティングは以下のように設定しました。
```routes.rb
  resources :users, only: %i(index new show create) do
    post :arrive_company, on: :member
    get  :arrive_qr_code, on: :collection
  end
```

# QRコードの生成&コントローラーの記述
SVG、PNG、ANSI形式がありますが、今回はSVG形式で表示します。
コントローラーは今回は`users_controller`に記述しています。必要に応じて変更してください。

今回、渡ってくるパラメータのスコープが思ったものと違うためストロングパラメータを使用できませんでした。どうやったらいいんだろう...とりあえず暫定処理としてこの`id`を`user_id`に受け取り、使用しました。

```
#今回渡ってきたパラメータ
{"authenticity_token"=>"省略", "id"=>"25"}
```

コントローラの記述はご覧の通りです。
```users_controller.rb
.
.
.
  def arrive_company
    @arrival_time = ArriveCompany.new(arrival_params)
    @arrival_time.arrival_time = Time.current
    
    if @arrival_time.save
      redirect_back(fallback_location: root_path)
    else
      raise 'error has occurred!!'
    end
  end
  
  def arrive_qr_code
    qrcode = RQRCode::QRCode.new(arrive_company_user_path(current_user))
    @qrcode = qrcode.as_svg(
      color: "000",
      shape_rendering: "crispEdges",
      module_size: 6,
      standalone: true,
      use_path: true
    ).html_safe
  end

   private  
    def arrival_params
      { user_id: params[:id] }
    end
```

# ビューの記述
ビューでQRコードを表示します。
```arrive_code.html.haml
= qrcode
```

以上でQRコードを読み取ればデータは保存されるはずです。
ローカル環境なのでQRコードを読み取って検証できませんでしたが、`link_to`で確認したところ保存できていたので、おそらく機能するはずです。時間があったら本番環境にあげて検証したいと思います。

# 余談：QRコードのオプション
このgemでは、以下のようなオプションがあるようです。


| オプション名       | 説明                                               | デフォルト値      |
|:-:|:-:|:-:|
| offset           | QRコード周りのパディングをpx単位で指定できます。           | 0                |
| fill             | QRコードの背景色を指定できます。                           | なし             |
| color            | QRコードの色を指定できます。                              | 000              |
| module_size      | QRコードのサイズをpx単位で指定できます。                    | 11               |
| shape_rendering  | SVGのshape-rendering属性を指定できます。                   | crispEdges       |
| standalone       | 完全なSVGファイルとして扱う(true)か、他のSVGファイルに埋め込むためのSVGとして扱う(false)かを選択できます。 | true             |
| use_path         | SVGのレンダリングにパスで描画する(true)か四角形で描画する(false)かを選択できます。 | false            |
| viewbox          | svg.widthとsvg.heightをsvg.viewBoxに置き換えるか選択できます。 | false            |
| svg_attributes   | カスタムでSVGの属性を設定できます。    | {}               |