Tích hợp Geocoder để hiển thị và tìm kiếm vị trí cho ứng dụng Rails
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 , ...
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 : Text
- latitude : Float
- longitude : 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
<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>
<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 %>
<header><h1 class="display-4"><%= @place.address %></h1></header> <p>Coordinates: <%= @place.latitude %> <%= @place.longitude %></p> <%= 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!