0

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, 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

<!-- 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 latitudelongitude 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 độ latitudelongitude 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.

Cảm ơn bạn đã đọc bài viết!


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí