Google Cloud PlatformにGoogleアカウントでログインしてAPIキーを取得してください。
手順は以下の通りにお願いします。
mrradiology.hatenablog.jp
記述追加 GemFile(70行目)
#googleマップ gem 'geocoder', '~> 1.4'
GemFile
source 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby '2.6.3' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 6.0.3' # Use postgresql as the database for Active Record gem 'pg', '>= 0.18', '< 2.0' # Use Puma as the app server gem 'puma', '~> 4.1' # Use SCSS for stylesheets gem 'sass-rails', '>= 6' # Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker gem 'webpacker', '~> 4.0' # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks gem 'turbolinks', '~> 5' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder gem 'jbuilder', '~> 2.7' # Use Redis adapter to run Action Cable in production # gem 'redis', '~> 4.0' # Use Active Model has_secure_password # gem 'bcrypt', '~> 3.1.7' # Use Active Storage variant # gem 'image_processing', '~> 1.2' # Reduces boot times through caching; required in config/boot.rb gem 'bootsnap', '>= 1.4.2', require: false group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] end group :development do # Access an interactive console on exception pages or by calling 'console' anywhere in the code. gem 'web-console', '>= 3.3.0' gem 'listen', '~> 3.2' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' end group :test do # Adds support for Capybara system testing and selenium driver gem 'capybara', '>= 2.15' gem 'selenium-webdriver' # Easy installation and use of web drivers to run system tests with browsers gem 'webdrivers' end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] # Bulma gem 'bulma-rails', '~> 0.7.4' gem 'bulma-extensions-rails', '~> 1.0.30' #デバイス gem 'devise' # 日本語化 gem 'rails-i18n' # アマゾンS3 gem "aws-sdk" #googleマップ gem 'geocoder', '~> 1.4'
コマンド
bundle
コマンド
rails g migration AddFieldsToRoom latitude:float longitude:float
コマンド マイグレーション
rails db:migrate
記述追加 app\models\room.rb(8行目)
geocoded_by :address after_validation :geocode, if: :address_changed?
app\models\room.rb
class Room < ApplicationRecord belongs_to :user has_many_attached :photos has_rich_text :description geocoded_by :address after_validation :geocode, if: :address_changed? validates :home_type, presence: true validates :room_type, presence: true validates :accommodate, presence: true validates :bed_room, presence: true validates :bath_room, presence: true end
GoogleマップAPIの埋め込み
取得したキーを「key=」から「&callback」の間に埋め込んで下さい。
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBojDcZmScBkIOISjoYREjgid99iZUL2Tk&callback=initMap" type="text/javascript"></script>
このscriptタグをサイトに埋め込みます。
1.記述追加 app\views\rooms\show.html.erb(188行目)
<!-- GOOGLE マップ --> <div class="row"> <div id="map" style="width: 100%; height: 400px"></div> <script src="https://maps.googleapis.com/maps/api/js"></script> <script> function initialize() { var location = {lat: <%= @room.latitude %>, lng: <%= @room.longitude %>}; var map = new google.maps.Map(document.getElementById('map'), { center: location, zoom: 14 }); var marker = new google.maps.Marker({ position: location, map: map }); var infoWindow = new google.maps.InfoWindow({ content: '<div id="content" class="image is-128x128"><%= image_tag room_cover(@room) %></div>' }); infoWindow.open(map, marker); } google.maps.event.addDomListener(window, 'load', initialize); </script> <script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBojDcZmScBkIOISjoYREjgid99iZUL2Tk&callback=initMap" type="text/javascript"></script> </div>
2.記述追加 app\views\rooms\show.html.erb(227行目)
<!-- 近くのお部屋を検索 --> <div class="row"> <h3>お近くのお部屋</h3> <br/> <% for room in @room.nearbys(10) %> <div class="col-md-4"> <div class="image is-128x128"> <%= image_tag room_cover(room) %> </div> <span> <%= link_to room.listing_name, room %><br/> (距離:<%= room.distance.round(2) %> Km) </span> </div> <% end %> </div>
app\views\rooms\show.html.erb
<section class="section"> <div class="container"> <div class="columns"> <!-- 写真 --> <div class="card"> <div class="card-content"> <div class="content"> <%= image_tag room_cover(@room) %> </div> </div> </div> <br/> </div> </div> </section> <section class="section"> <div class="container"> <div class="columns"> <!-- 左側 --> <div class="column is-two-thirds"> <div class="columns is-multiline"> <div class="column"> <div class="card"> <div class="card-content"> <div class="box"> <article class="media"> <div class="media-content"> <div class="content"> <!-- お部屋の名前 --> <div class="row"> <div class="col-md-8"> <h1><%= @room.listing_name %></h1> <h2><%= @room.address %></h2> </div> </div> </div> </div> </article> </div> <div class="box"> <article class="media"> <div class="media-content"> <div class="content"> <span class="title is-5"><%= @room.user.full_name %></span> <figure class="image is-96x96"> <%= image_tag avatar_url(@room.user), class: "is-rounded" %> </figure> </div> </div> </article> </div> <div class="box"> <article class="media"> <div class="media-content"> <div class="content"> <!-- 部屋のインフォメーション --> <div style="white-space: nowrap"> <span class="col-md-3"> <i class="fas fa-home fa-3x" style="color: #1dbf73"></i> <span class="col-md-3"><%= @room.home_type %></span> </span> <span class="col-md-3"> <i class="fas fa-user fa-3x" style="color: #1dbf73"></i> <span class="col-md-3"><%= pluralize(@room.accommodate, "人") %></span> </span> <span class="col-md-3"> <i class="fas fa-bed fa-3x" style="color: #1dbf73"></i> <span class="col-md-3"><%= pluralize(@room.bed_room, "台") %></span> </span> <span class="col-md-3"> <i class="fas fa-bath fa-3x" style="color: #1dbf73"></i> <span class="col-md-3"><%= pluralize(@room.bath_room, "部屋") %></span> </span> </div> </div> </div> </article> </div> <!-- お部屋の詳細 --> <div class="box"> <article class="media"> <div class="media-content"> <div class="content"> <h3>お部屋の詳細</h3> <p><%= @room.description %></p> </div> </div> </article> </div> <!-- アメニティー --> <div class="box"> <article class="media"> <div class="media-content"> <div class="content"> <div class="row"> <div class="col-md-3"> <h4>アメニティ</h4> </div> <div class="col-md-9"> <div class="row"> <div class="col-md-6"> <ul class="amenities"> <li class="<%= 'text-line-through' if !@room.is_tv %>">テレビ</li> <li class="<%= 'text-line-through' if !@room.is_kitchen %>">キッチン</li> <li class="<%= 'text-line-through' if !@room.is_internet %>">インターネット</li> </ul> </div> <div class="col-md-6"> <ul class="amenities"> <li class="<%= 'text-line-through' if !@room.is_heating %>">暖房</li> <li class="<%= 'text-line-through' if !@room.is_air %>">エアコン</li> </ul> </div> </div> </div> </div> </div> </div> </article> </div> </div> </div> </div> <!-- カルーセル表示 --> <div class="column is-full"> <div class="card"> <div class="card-content"> <div class="hero-carousel" id="carousel-photo"> <% @room.photos.each do |photo| %> <div class="carousel-item has-background image is-16by9"> <%= image_tag url_for(photo), class: "is-background", width: "100%" %> </div> <% end %> </div> </div> </div> </div> <div class="column"> <div class="card"> <div class="card-content"> <!-- googleマップ --> <div class="box"> <article class="media"> <div class="media-content"> <div class="content"> <!-- GOOGLE マップ --> <div class="row"> <div id="map" style="width: 100%; height: 400px"></div> <script src="https://maps.googleapis.com/maps/api/js"></script> <script> function initialize() { var location = {lat: <%= @room.latitude %>, lng: <%= @room.longitude %>}; var map = new google.maps.Map(document.getElementById('map'), { center: location, zoom: 14 }); var marker = new google.maps.Marker({ position: location, map: map }); var infoWindow = new google.maps.InfoWindow({ content: '<div id="content" class="image is-128x128"><%= image_tag room_cover(@room) %></div>' }); infoWindow.open(map, marker); } google.maps.event.addDomListener(window, 'load', initialize); </script> <script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBojDcZmScBkIOISjoYREjgid99iZUL2Tk&callback=initMap" type="text/javascript"></script> </div> </div> </div> </article> </div> <!-- 近くのお部屋 --> <div class="box"> <article class="media"> <div class="media-content"> <div class="content"> <!-- 近くのお部屋を検索 --> <div class="row"> <h3>お近くのお部屋</h3> <br/> <% for room in @room.nearbys(10) %> <div class="col-md-4"> <div class="image is-128x128"> <%= image_tag room_cover(room) %> </div> <span> <%= link_to room.listing_name, room %><br/> (距離:<%= room.distance.round(2) %> Km) </span> </div> <% end %> </div> </div> </div> </article> </div> </div> </div> </div> </div> </div> <!-- 右側 --> <div class="column"> <div class="columns is-multiline"> <!-- 予約 --> <div class="column is-full"> <div class="card"> <div class="card-content"> <div class="media"> </div> </div> </div> </div> </div> </div> </div> </div> </section> <script> BulmaCarousel.attach('#carousel-photo', { slidesToScroll: 1, slidesToShow: 1 }); $(document).ready(function() { $('#tabs li').on('click', function() { var type = $(this).data('tab'); $('#tabs li').removeClass('is-active'); $(this).addClass('is-active'); $('.tab-content').hide(); $('#tab-' + type).show(); }) }) </script>
「config\initializers」フォルダに「geocoder.rb」ファイルを新規作成します。
config\initializers\geocoder.rb(新規作成したファイル)
Geocoder.configure( units: :km )
ブラウザ確認
お部屋を登録するときに住所を入力すると自動で位置情報が保存されます。(Geocordingの機能)
ただし、日本の住所に対する変換が貧弱なので「北海道札幌市中央区」くらいまでしか認識してくれません。
http://localhost:3000/rooms/1/location
住所を入力して位置情報が更新されるか確かめてみます。
部屋を2つ以上登録して公開します。
http://localhost:3000/rooms/new
お部屋のページを確認します。
http://localhost:3000/rooms/1