Rails5でGeocorderとGeolocationを使って周辺の施設を検索する方法
Rails5でGeocorderとGeolocationを使って周辺の施設を検索する方法:
Railsでアプリケーションを作っている時に位置情報を使って周辺の施設(自分の場合は飲食店)を検索する機能を付けたいと思ったので今後、位置情報を使う時にメモの代わりになればいいかなと思ったので書きます。
最後の方で壊滅的な事に気づいたのでそれも書きますww
ではやっていきましょう!!
Rails 5.0.0
Ruby 2.5.3
下記を含むモデルがある事
ブラウザに位置情報を使用する事が許可されている事
gem導入
↓
住所をgeocording
↓
緯度経度をそれぞれカラムへ保存
↓
現在地情報をgeolocationを使って取得
↓
検索
モデルにfloat型でlatitudeとlongitudeを追加
ここで気づいたのですが実はgeocorderはスポットに強い代わりに住所に対して弱く
どういう事かというと「スカイツリー」で緯度経度を保存しようとすれば正確な緯度経度が出るのですが
「東京都墨田区押上1丁目1−2」で保存しようとすると緯度経度が出ず、「東京都墨田区」までしか出ませんwww
結論を述べるとgeocorderでは無く、googleのAPIを使用する方が正確な緯度経度を取得出来ます。
自分もそれに手を付け始めたので完成したらその記事はまた書きます!(今書けよ、、)
自分の場合は住所をそれぞれ都道府県、市、区、町村、番地とそれぞれ別のカラムに保存したので都道府県、市、区までのカラムから緯度経度を出します。
なので、自分はgeocording用にaddressカラムを作ってその中に、都道府県、市、区の3つだけを入れました。
その前にgeocorderにどのカラムから緯度経度を出すか教えてあげましょう!
この2行をモデルに追加してあげます。
下の行はどのタイミングでgeocordingするかです。この書き方だと住所が編集された時となります。(これ以外知らない、、)
これは自分の場合ですが一応書いときます。
下はHTMLに組み込まれてるAPI(自信はない、、)を使用するスクリプトです。
これを書き込んだViewにはこんな感じのボタンを入れてください。
途中のajaxの記述は別に無くて大丈夫です。
興味本位でajaxとwindow.location.hrefを比較してました。(結果は後者の方が記述が少なくてわかりやすいから採用)
window.location.href の部分は書き方は参考までに書きますが、適宜修正してください。
渡すURLはコントローラーのアクションを呼び出します。
先ほど記述したURLからコントローラのアクションを呼び出します。
ポイントはlatitudeとlongitudeをfloat型で受け取っている所です。
@locationsに半径500m以内にある施設(自分の場合は飲食店)を配列で入れます。
.within_boxはgeocorderのメソッドで
という使い方が出来ます。これで半径マイルのが出せます。
ちなみに0.310686はメートルに直すと500mです。
初めて記事を書いてみましたが恐ろしいほど復習になりました。
間違っている箇所もあるとは思いますが優しく教えてください!
ありがとうございました。
Railsでアプリケーションを作っている時に位置情報を使って周辺の施設(自分の場合は飲食店)を検索する機能を付けたいと思ったので今後、位置情報を使う時にメモの代わりになればいいかなと思ったので書きます。
最後の方で壊滅的な事に気づいたのでそれも書きますww
ではやっていきましょう!!
前提
Rails 5.0.0Ruby 2.5.3
下記を含むモデルがある事
t.string "prefecture" 都道府県 t.string "address_city" 区市 t.string "address_street" 町 t.string "address" 都道府県+区市
手順
gem導入↓
住所をgeocording
↓
緯度経度をそれぞれカラムへ保存
↓
現在地情報をgeolocationを使って取得
↓
検索
gemの導入
Gemfile
gem 'geocoder'
住所をgeocording
モデルにfloat型でlatitudeとlongitudeを追加モデル.rb
t.float "latitude" t.float "longitude"
どういう事かというと「スカイツリー」で緯度経度を保存しようとすれば正確な緯度経度が出るのですが
「東京都墨田区押上1丁目1−2」で保存しようとすると緯度経度が出ず、「東京都墨田区」までしか出ませんwww
結論を述べるとgeocorderでは無く、googleのAPIを使用する方が正確な緯度経度を取得出来ます。
自分もそれに手を付け始めたので完成したらその記事はまた書きます!(今書けよ、、)
緯度経度をそれぞれカラムへ保存
自分の場合は住所をそれぞれ都道府県、市、区、町村、番地とそれぞれ別のカラムに保存したので都道府県、市、区までのカラムから緯度経度を出します。なので、自分はgeocording用にaddressカラムを作ってその中に、都道府県、市、区の3つだけを入れました。
その前にgeocorderにどのカラムから緯度経度を出すか教えてあげましょう!
この2行をモデルに追加してあげます。
下の行はどのタイミングでgeocordingするかです。この書き方だと住所が編集された時となります。(これ以外知らない、、)
モデル.rb
geocoded_by :address after_validation :geocode, if: :address_changed?
コントローラ
def create @shop = Shop.new(shop_params) @shop.address = @shop.prefecture + @shop.address_city @shop.address = @shop.address.gsub(/\d+/, "").gsub(/\-+/, "") @shop.save end
現在地情報をgeolocationを使って取得
下はHTMLに組み込まれてるAPI(自信はない、、)を使用するスクリプトです。これを書き込んだViewにはこんな感じのボタンを入れてください。
View
<button onclick="getPosition();">Find!!</button>
適宜使いたいView
<script> // 現在地取得処理 function getPosition() { // 現在地を取得 navigator.geolocation.getCurrentPosition( // 取得成功した場合 function(position) { window.location.href = "/shops/search_location?latitude="+position.coords.latitude+"&longitude="+position.coords.longitude // $.ajax({ // url: "/shops/search_location", // type: "GET", // dataType: 'html', // data: {latitude : position.coords.latitude, // longitude : position.coords.longitude}, // }); }, // 取得失敗した場合 function(error) { switch(error.code) { case 1: //PERMISSION_DENIED alert("位置情報の利用が許可されていません"); break; case 2: //POSITION_UNAVAILABLE alert("現在位置が取得できませんでした"); break; case 3: //TIMEOUT alert("タイムアウトになりました"); break; default: alert("その他のエラー(エラーコード:"+error.code+")"); break; } } ); } </script>
興味本位でajaxとwindow.location.hrefを比較してました。(結果は後者の方が記述が少なくてわかりやすいから採用)
window.location.href の部分は書き方は参考までに書きますが、適宜修正してください。
モデル.rb
window.location.href = "渡すURL?latitude="+position.coords.latitude+"&longitude="+position.coords.longitude
検索
先ほど記述したURLからコントローラのアクションを呼び出します。ポイントはlatitudeとlongitudeをfloat型で受け取っている所です。
@locationsに半径500m以内にある施設(自分の場合は飲食店)を配列で入れます。
.within_boxはgeocorderのメソッドで
Model.within_box(マイル, 緯度, 経度)
ちなみに0.310686はメートルに直すと500mです。
コントローラ
def search_location latitude = params[:latitude].to_f longitude = params[:longitude].to_f @locations = Shop.within_box(0.310686, latitude, longitude) end
終わり
初めて記事を書いてみましたが恐ろしいほど復習になりました。間違っている箇所もあるとは思いますが優しく教えてください!
ありがとうございました。
コメント
コメントを投稿