Rails6でMapboxを導入する

## はじめに
最近railsでMapboxを使った地図アプリをつくる機会があったので、はじめの**導入部分**を共有します。

## 開発環境
rails 6.0.2
ruby 2.6.5

## 最低限のセットアップ

**※必要に応じてファイル名等変えてください**

rails new アプリ名 -d postgresql  
yarn add mapbox  
yarn add mapbox-gl  
yarn add dotenv  
rails db:create  
rails g controller maps  

## Apiキーの取得
以下のサイトでアカウントを取得し、Apiキーを取得します。
[Mapbox](https://www.mapbox.com/)

## .envファイルの作成
.envファイルを作成し、Apiキーを記します。（これは架空キーです）

```rails:.env
MAPBOX_API_KEY=pk.eyK6PjoiZnVqaW8iLCJhIjoiP2szcGJ5MDFkMDFzazNlbGZzZ2ozbzhyMCJ9._IgaTSsbe6sdkLQeeqJRahw
```

.gitignoreに.envを書きます。


```rails:.gitignore
(省略）
.env
```

##コードの記述
- app>views>layouts

#####地図読み込みのための記述をします。
```rails:application.html.erb
<head>
  (省略)
  <%= stylesheet_link_tag    'application', media: 'all'%>
  <%= stylesheet_pack_tag 'application', media: 'all' %>
  <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
　<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.6.1/mapbox-gl.js">　　</script>
　<link href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.6.1/mapbox-gl.css" rel="stylesheet" /></script>
</head>
<body>
  (省略）
  <%= javascript_include_tag 'application' %>
  <%= javascript_pack_tag 'application' %>
</body>
```
#####地図を反映させるためのdivを用意します。
- app>views>maps

```index.html.erb
<div class="container">
  <div id='map' class='target'>
    <p>私の地図</p>
  </div>
</div>
```

#####packsディレクトリにjsを記述していきます。
- app>javascript>packs>plugins

```map.js
import mapboxgl from 'mapbox-gl';

const showMap = () => {
  const map_div = document.getElementById('map');
  if (map_div) {
    mapboxgl.accessToken = process.env.MAPBOX_API_KEY
      window.map = new mapboxgl.Map({
        container: 'map',
        style: 'mapbox://styles/mapbox/streets-v11',
      });      
    }
  };

export { showMap }
```
- app>javascript>packs

```application.js

import 'mapbox-gl/dist/mapbox-gl.css';
import { showMap } from './plugins/map';
showMap();
```

#####root画面を設定します。def indexをmapsコントローラに書きます（説明のための便宜上）
- config

```rails:routes.rb
Rails.application.routes.draw do
  root to: 'maps#index'
end
```

- app>controllers

```rails:maps_controller.rb
class MapsController < ApplicationController
  def index; end
end
```


#####assetsディレクトリに追記します。
- app>assets>config

```rails:manifest.js
(省略)
//= link_directory ../javascripts .js
```

- app>assets>javascripts

```rails:applicaton.js
//= require rails-ujs
//= require_tree .
```

#####stylesheetsの記述です
- app>assets>stylesheets>components

```rails:maps.scss
#map {
  list-style: none;
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100%;
  z-index: 1;
}

body p {
  font-size: 20px;
}
```
- app>assets>stylesheets (application.cssを書きかえ)


```rails:applicaton.scss
@import 'components/maps';
```

#####webpackディレクトリの設定をします
- config>webpack

```rails:environment.js
(省略)
environment.loaders.delete('nodeModules');

const webpack = require('webpack')
const dotenv = require('dotenv')
const dotenvFiles = [
  `.env.${process.env.NODE_ENV}.local`,
  '.env.local',
  `.env.${process.env.NODE_ENV}`,
  '.env'
]
dotenvFiles.forEach((dotenvFile) => {
  dotenv.config({ path: dotenvFile, silent: true })
})

environment.plugins.prepend('Environment',
  new webpack.EnvironmentPlugin(
    JSON.parse(JSON.stringify(process.env))
  )
)
(省略)
```

##### ここまでの出力です
世界地図が現れました。

<img width="1184" alt="root画面.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558790/50711509-b32c-9f2d-b655-b75b056725d5.png">

##### 地図をアレンジします
-　衛星写真に変え、東京駅に中心を合わせ、地図を拡大してみます。
地図属性をURLで指定し、centerにcenter_pointという変数で座標を設定、zoomの値をあげて地図を拡大させます。

- app>javascript>packs>plugins

```map.js
(省略）
  if (map_div) {
    mapboxgl.accessToken = process.env.MAPBOX_API_KEY
    var center_point = [139.767125, 35.681236]
    window.map = new mapboxgl.Map({
      container: 'map',
      style: 'mapbox://styles/mapbox/satellite-v9',
      center: center_point,
      zoom: 13
    });
（省略）

```
##### ここまでの出力です

<img width="1188" alt="root画面2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558790/abd4706c-5c28-e3cf-bae9-46e5c87e825a.png">

##### 地図上にマーカーを打ち、ポップアップを加え、少し拡大します（マーク場所は東京ステーションホテル）

```map.js
（省略)
　　mapboxgl.accessToken = process.env.MAPBOX_API_KEY
    var center_point = [139.767125, 35.681236]
      window.map = new mapboxgl.Map({
        container: 'map',
        style: 'mapbox://styles/mapbox/satellite-v9',
        center: center_point,
        zoom: 17
      });
      var marker = new mapboxgl.Marker()
      var hotel_point = [139.76595173, 35.68089883]

      var popup = new mapboxgl.Popup({ offset: 25 }).setHTML(
        '<strong>東京ステーションホテル</strong><p>国指定重要文化財である
         東京駅・丸の内駅舎の中に位置する<a href="https://www.tokyostationhotel.jp/"
         target="_blank" title="Opens in a new window">ステーションホテル</a>は、
         100年以上の歴史を誇る唯一無二の名門ホテルです</p>'
        );

      new mapboxgl.Marker(marker)
      .setLngLat(hotel_point)
      .setPopup(popup)
      .addTo(map);
（省略）

```

##### ここまでの出力です

<img width="1086" alt="root画面3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558790/ade75471-2f7b-d585-84f2-6b099cafeba8.png">

##その他のアレンジ
その他多くのカスタマイズができます。
以下のサイトでサンプルコードを見ることができます。
[Mapbox](https://docs.mapbox.com/mapbox-gl-js/examples/)

##最後に
Rails6で実装しましたが、Rails5以下で実装する場合は'webpacker'が必要です。
最後まで読んでいただきありがとうございました。