Nhúng google map vào ứng dụng rails với gem Geocoder
Bài đăng này đã không được cập nhật trong 8 năm
Hôm nay mình sẽ chuyển qua Rails và trình bày một cách đơn giản để sử dụng bản đồ trong ứng dụng rails với gem Geocoder. Về google map api mọi người có thể tham khảo bài viết Google map API .
Get Google API key
Để sử dụng được Google Maps API, chúng ta cần phải đăng ký app project trên Google API Console và get API key để dùng.
Mọi người có thể get key đơn giản bằng cách click vào nút get a key qua link sau:
Quick start to get API key
hoặc có thể đăng ký và quản lý key cho project qua Googel API Console
Sau khi get key xong chúng ta cần thêm đoạn script để dùng API của Google như sau:
<script src="//maps.google.com/maps/api/js?v=3.27&key=AIzaSyDEHpTjzc2CyFPY_m-_QCBWDI25w2pbnYM"></script>
Note: ở đây mình chỉ định luôn là Google map api version 3.27. đoạn script này chúng ta có thể thêm ngay trong phần view cần dùng.
Geocoder
Ok vậy là bước chuẩn bị key đã xong. Trước hết mình sẽ giới thiệu qua gem geocoder và tại sao mình dùng nó mà không phải 1 gem khác như gmaps4rails.
Trước hết Geocoder là một giải pháp mã hóa địa lý trong Ruby. Nó có một vài tính năng cụ thể như sau:
- Chuyển đổi địa điểm thành tọa độ địa lý và ngược lại
- Tìm địa điểm gần vị trí cho trước
- Chuyển đổi địa chỉ IP thành vị trí
Trước đó khi chuẩn bị làm task này mình nghĩ đến gem gmaps4rails nhưng rồi đọc tìm hiểu thì thấy cần thêm cả thư viện js ngoài như underscore để custom map hay việc tạo và generate JSON để tạo map khá phức tạp. Trong khi cái mình thực sự cần là latitude (vĩ độ) và longitude (kinh độ). Rồi tìm hiểu thì mình thấy geocoder làm đơn giản và khá mạnh nếu mình khai thác thêm như mấy chức năng cơ bản mình nêu trên. À ngồi vọc còn thấy ngoài author chính là Alexreisner thì còn có chị Phạm Thu Trang là contributor (xếp thứ 2 và có quyền merge pull request
).
Instruction
- Database Migration
Mình xin bỏ qua bước cài đặt gem. Chúng ta thêm 2 trường
latitudevàlongitudevào trong bảng mà chúng ta dùng để lưu vị trí. Cụ thể ở đây mình lưu ở bảngAddress. Note: lưu ý chính tả nhé. khi tạo database migration team-mate mình thuận miệng và tạo là.longtitude - Modify model:
Migrate xong thì chúng ta thêm đôi dòng như sau:
ở đây mình sẽ dựa vào trườnggeocoded_by :address after_validation :geocode, if: :address_changed?addressđể lấy vĩ độ và kinh độ cho địa điểm. vàafter_validationlà để generate lại kinh độ và vĩ độ khiaddressthay đổi. Cũng không quá khó hiểu lắm - Generate latitude and longitude
Cái này cũng khá giống với việc re-index trong
elasticsearchđó là chúng ta chạy lệnh để generate vĩ độ và kinh độ cho địa chỉ có sẵn trong database:rake geocode:all CLASS=Address SLEEP=0.25 BATCH=100 - Get location
Mọi việc gần như xong rồi. giờ thì chúng ta sẽ dựa vào kinh độ và vĩ độ để tạo map trên project của chúng ta.
Đầu tiên là trong controller chúng ta sẽ trả về
jsonđể dựa vào đó chúng ta vẽ bản đồ tương ứng cho từng địa điểm. Cụ thể ở bài viết này mình sẽ vẽ địa điểm của 1 công ty nào đó, vì vậy trong actionshowởCompaniesControllermình trả về như sau:
Vậy là xong việc việc trả về dữ liệu. chúng ta chuyển quadef show if request.xhr? render json: { addresses: @company.addresses } end endview. Đơn giản chỉ tạo 1 div chứa map và style cho nó:
Hoàn tất công việc bằng cách viết Javascript để xử lý dữ liệu trả về và tạo bản đồ tương ứng:<div id="map" class="map"></div>
Ở file javascript trên mình chia thành 2 function là$(function() { getLocation.initialize(); }); var getLocation = { initialize: function() { getLocation.fetch_data(); }, fetch_data: function() { var url_path = window.location.pathname; $.get(url_path, function(data) { var addresses = data['addresses']; const latitude = addresses[0].latitude; const longitude = addresses[0].longitude; getLocation.draw_map(latitude, longitude); }, 'json'); }, draw_map: function(lat, lng) { var companyLatlng = new google.maps.LatLng(lat, lng); var mapOptions = { zoom: 15, center: companyLatlng, mapTypeId: google.maps.MapTypeId.ROADMAP } var map = new google.maps.Map(document.getElementById('map'), mapOptions); var marker = new google.maps.Marker({ position: companyLatlng, map: map }); } }fetch_datađể lấy dữ liệu trả về vàdraw_mapđể tạo bản đồ. Về phầndraw_mapthì mình chỉ custom thêm cái marker thôi. Cũng không có gì là khó hiểu nhỉ.
Conclusion
Mình đã nói qua về các tính cơ bản của Geocoder và nó còn khá nhiều tính năng thú vị nữa nên mọi người có thể tìm hiểu thêm qua Geocoder. Happy coding !
All rights reserved