前提・実現したいこと
ここに質問の内容を詳しく書いてください。
rails6で住所を投稿し、その内容をDB(MySQL)に登録して、その内容を表示させる、ということを実装しようとしています。
Column | Type | Options |
---|---|---|
name | string | null: false |
comment | text | null: false |
address | integer | null: false |
longitude | integer | |
latitude | integer |
発生している問題・エラーメッセージ
localhost:3000/maps/newのページから住所と場所の名前とコメントを投稿した際に、以下のエラーが発生しました。
Mysql2::Error: Field 'latitude' doesn't have a default value
ターミナル上では以下のメッセージが出ていたため、API通信がうまくいっていないことが原因で、addressからlongitudeとlatitudeの変換が行われておらず、latitudeが空ですよ、というエラーが出ていると推測しています。
Google API error: request denied (The provided API key is invalid.).
該当のソースコード
app/models/map.rb
ruby
1class Map < ApplicationRecord 2 geocoded_by :address 3 after_validation :geocode, if: :address_changed? 4 # has_many :messages 5 6 with_options presence: true do 7 validates :address 8 validates :name 9 end 10end 11
app/views/maps/new.html.erb
ruby
1<%= render "shared/header" %> 2<h1>場所投稿フォーム</h1> 3 4 <%= form_with model: @map, url:maps_path, local: true do |f| %> 5 <p> 6 <%= f.label :name %> 7 <%= f.text_field :name, size: "50x1" %> 8 <%= f.label :address %> 9 <%= f.text_field :address, size: "50x1" %> 10 <%= f.label :comment %> 11 <%= f.text_field :comment, size: "50x1" %> 12 </p> 13 14 <%= f.submit "送信"%> 15<% end %> 16 17<%= render "shared/footer" %> 18
app/controllers/maps_controller.rb
ruby
1class MapsController < ApplicationController 2 def index 3 @maps = Map.all 4 @map = Map.new 5 end 6 7 def new 8 @map = Map.new 9 end 10 11 12 def create 13 @map = Map.new(map_params) 14 15 if @map.save 16 redirect_to action: :index 17 else 18 redirect_to action: :new 19 end 20 end 21 22 def destroy 23 map = Map.find(params[:id]) 24 map.destroy 25 redirect_to action: :index 26 end 27 28 private 29 def map_params 30 params.require(:map).permit(:address, :name, :comment) 31 end 32end
config/initializers/geocoder.rb
ruby
1Geocoder.configure( 2 # Geocoding options 3 # timeout: 3, # geocoding service timeout (secs) 4 lookup: :google, # name of geocoding service (symbol) 5 # ip_lookup: :ipinfo_io, # name of IP address geocoding service (symbol) 6 # language: :en, # ISO-639 language code 7 use_https: true, # use HTTPS for lookup requests? (if supported) 8 # http_proxy: nil, # HTTP proxy server (user:pass@host:port) 9 # https_proxy: nil, # HTTPS proxy server (user:pass@host:port) 10 api_key: ['GOOGLE_MAP_API_KEY'], 11 # cache: nil, # cache object (must respond to #[], #[]=, and #del) 12 # cache_prefix: 'geocoder:', # prefix (string) to use for all cache keys 13 14 # Exceptions that should not be rescued by default 15 # (if you want to implement custom error handling); 16 # supports SocketError and Timeout::Error 17 # always_raise: [], 18 19 # Calculation options 20 # units: :mi, # :km for kilometers or :mi for miles 21 # distances: :linear # :spherical or :linear 22)
app/views/shared/_map.html.erb
ruby
1<input id="address" type="textbox" value=""> 2<input type="button" value="地図を検索" onclick="codeAddress()"> 3<div id="display"></div> 4 5<div id='map'></div> 6 7 8 9<script> 10 let map 11 12 const display = document.getElementById('display') 13 14 // mapの表示関数 15 function initMap() { 16 geocoder = new google.maps.Geocoder() 17 18 // mapの初期位置, 縮尺を定義 19 map = new google.maps.Map(document.getElementById('map'), { 20 center: { 21 lat: 35.57973, 22 lng: 139.55869 23 }, 24 zoom: 13, 25 }); 26 27 // mapsテーブルにあるそれぞれのレコードをmap上に表示 28 <% @maps.each do |m| %> 29 (function(){ 30 var contentString = "住所:<%= m.address %>"; 31 32 // マーカーを立てる 33 var marker = new google.maps.Marker({ 34 position:{lat: <%= m.latitude %>, lng: <%= m.longitude %>}, 35 map: map, 36 title: contentString 37 }); 38 39 // 情報ウィンドウ(吹き出し)の定義 40 // 投稿の詳細ページへのリンクも 41 var infowindow = new google.maps.InfoWindow({ 42 position: {lat: <%= m.latitude %>, lng: <%= m.longitude %>}, 43 content: "<a href='<%= map_url(m.id) %>' target='_blank'><%= m.address %></a>" 44 }); 45 46 // クリックしたときに情報ウィンドウを表示 47 marker.addListener('click', function() { 48 infowindow.open(map, marker); 49 }); 50 51 })(); 52 <% end %> 53 } 54 55 let geocoder 56 57 // 地図検索関数 58 function codeAddress() { 59 let inputAddress = document.getElementById('address').value; 60 61 geocoder.geocode({ 62 'address': inputAddress 63 }, function (results, status) { 64 if (status == 'OK') { 65 map.setCenter(results[0].geometry.location); 66 var marker = new google.maps.Marker({ 67 map: map, 68 position: results[0].geometry.location 69 }); 70 71 display.textContent = "検索結果:" + results[ 0 ].geometry.location 72 } else { 73 alert('該当する結果がありませんでした:' + status); 74 } 75 }); 76 } 77</script> 78 79<script 80 src="https://maps.googleapis.com/maps/api/js?key=<%= ENV['GOOGLE_MAP_API_KEY'] %>&callback=initMap" 81 async defer> 82</script> 83 84<h3>公園一覧</h3> 85<% @maps.each do |t| %> 86 87 <p>住 所 : <%= t.address %></p> 88 <p>公園名称 : <%= t.name %></p> 89 <p>コメント : <%= t.comment %></p> 90 <p><%= link_to "削除する", map_path(t.id), method: :delete %></p> 91 <hr> 92<% end %> 93<% if user_signed_in? %> 94<%= link_to '新規投稿', '/maps/new', method: :GET %> 95<% end %> 96
試したこと
- GoogleMapAPIキーの制限がGeocodingAPIとMapsJavascriptAPIが有効になっていることを確認。
- .envに間違いなくAPIキーが記述されていることを確認。
- gem 'geocoder'が記述してあり、bundle installしてrails sした
- コントローラー のcreateアクションのif @map.saveの手前でbinding pryして@mapの中身を確認(latitudeとlongitudeはnilだった)
補足情報(FW/ツールのバージョンなど)
こちらの記事を参考に実装を進めておりました。
https://qiita.com/MandoNarin/items/aa91ffae373a8cfc85d2
こちらの記事を参考に経度と緯度の精度の問題を疑いましたが、こちらは実施しても解決しませんでした。
https://qiita.com/roark/items/2fedc1ebac763e72d70b
ここにより詳細な情報を記載してください。
あなたの回答
tips
プレビュー