Tích hợp Geocoder để hiển thị và tìm kiếm vị trí cho ứng dụng Rails
Bài đăng này đã không được cập nhật trong 2 năm
Source gem Geocoder
Có thể tìm kiếm vị trí theo tọa độ, địa chỉ, hoặc thậm chí đo khoảng cách giữa các địa điểm và tìm địa điểm gần đó.
Geocoder
tương thích với rất nhiều nền tảng khác nhau :
- Ruby các version 1.9.3, 2.x, JRuby
- Nhiều cơ sở dữ liệu : MySQL, PostgreSQL, SQLite, MongoDB
- Rails 3, 4, 5
Việc cài đặt hết sức đơn giản cũng như hầu hết các gem khác là thêm gem 'geocoder'
vào Gemfile trước khi tiến hành bundle, hoặc chạy lệnh bundle install geocoder
Trước tiên, hãy chuẩn bị sẵn một ứng dụng đơn giản để sử dụng gem Geocoder
nhé.
Tạo ứng dụng.
Mình xây dựng ứng dụng này trên Ruby 2.3, Rails 5 và MySQL 5.7
Tạo một app mới có tên là simple-geocoder, có model Place
với các trường cụ thể như sau :
address
: Textlatitude
: Floatlongitude
: Float
Tiến hành bundle install và khởi tạo database (bước này đơn giản nên mình ko đưa vào cụ thể)
Tạo controller mới.
# app/controllers/places_controller.rb
class PlacesController < ApplicationController
def index
@places = Place.order(created_at: :desc)
end
def new
@place = Place.new
end
def create
@place = Place.new(place_params)
if @place.save
flash[:success] = "Place added!"
redirect_to root_path
else
render "new"
end
end
private
def place_params
params.require(:place).permit(:address)
end
end
Định nghĩa router.
#config/routes.rb
Rails.application.routes.draw do
resources :places, only: [:index, :show, :new, :create]
root "places#index"
end
Tạo ra một vài view
<!-- app/views/places/index.html.erb -->
<header><h1 class="display-4">Places</h1></header>
<%= link_to "Add place", new_place_path, class: "btn btn-primary btn-lg" %>
<div class="card">
<div class="card-block">
<ul>
<% @places.each do |place| %>
<li>
<%= link_to place.address, place_path(place) %>
</li>
<% end %>
</ul>
</div>
</div>
<!-- app/views/places/new.html.erb -->
<header><h1 class="display-4">Add Place</h1></header>
<%= form_for @place do |f| %>
<fieldset class="form-group">
<%= f.label :address, "Address" %>
<%= f.text_field :address, class: "form-control" %>
</fieldset>
<%= f.submit "Add!", class: "btn btn-primary" %>
<% end %>
<!-- app/views/places/show.html.erb -->
<header><h1 class="display-4"><%= @place.address %></h1></header>
<p>Coordinates: <%= @place.latitude %> <%= @place.longitude %></p>
<!--add static map-->
<%= image_tag "http://maps.googleapis.com/maps/api/staticmap?center=#{@place.latitude},#{@place.longitude}&markers=#{@place.latitude},#{@place.longitude}&zoom=15&size=640x400&key=GOOGLE_MAP_API_KEY", class: "img-fluid img-rounded", alt: "#{@place.title} on the map" %>
Bạn có thể vào đây để sinh ra GOOGLE_MAP_API_KEY
cho mình
Ok, đến đây ta có thể start server lên và thấy một giao diện đơn giản như hình là đã xong bước chuẩn bị.
Tích hợp Geocoder.
Trước tiên, ta thêm gem "geocoder"
vào Gemfile và tiến hành install.
Khai báo Geocoder
cho model Place
ở trên :
#app/models/place.rb
geocoded_by :address
after_validation :geocode, if: ->(obj){ obj.address.present? && obj.address_changed? }
Đến đây hãy thử vào server và tạo mới một bản ghi mới với một vị trí, ở đây mình tạo mới điểm Trường Đại học Bách khoa Hà Nội, Đại Cồ Việt, Hanoi, Vietnam
. Bạn có thể tìm một vài địa điểm có tên trong Google map rồi tiến hành tạo mới với tên đó. Sau khi lưu vào database thì ta sẽ có thế này.
Dễ thấy được là Geocoder
đã tự động tìm ra tọa độ của vị trí theo tên mà ta đã nhập và lưu vào trường latitude
và longitude
trong database của bạn.
Bên cạnh khả năng tìm ra tọa độ từ tên địa điểm, ngược lại, Geocoder còn hỗ trợ người dùng tìm ra vị trí từ tọa độ bằng cách sử dụng reverse_geocode
. Bạn có thể đọc thêm ở đây.
#app/models/place.rb
...
reverse_geocoded_by :latitude, :longitude
after_validation :reverse_geocode, unless: ->(obj) { obj.address.present? },
if: ->(obj){ obj.latitude.present? && obj.latitude_changed? && obj.longitude.present? && obj.longitude_changed? }
Tạo form để nhập vào 2 tọa độ latitude
và longitude
là bạn có thể tạo mới các vị trí cho database. Bạn có thể vào geocoder map để kiểm tra xem là ứng dụng của bạn có làm việc chính xác không nhé
Bạn cũng có thể tham khảo qua bài viết khác của mình để xem cách tích hợp một map động vào page chứ không đơn giản là map tĩnh như trên nữa
Tham khảo.
- https://www.sitepoint.com/geocoder-display-maps-and-find-places-in-rails/
- https://github.com/alexreisner/geocoder
Cảm ơn bạn đã đọc bài viết!
All rights reserved