Добавление фильтра близости к поиску пользователей

В нашем приложении настроен поиск пользователей, пока что он основан только на запросах текстового контента.

Итак, вот что у меня есть:

в моделях/user.rb

def self.search(query)
  where("description ilike ?", "%#{query}%")
end

в приложении/контроллеры/users_controller.rb

class UsersController < ApplicationController
  before_action :authorized?
  def index
    @users = User.all
    if params[:search]
      @users = User.search(params[:search]).order("created_at DESC")
    else
      @users = User.all.order('created_at DESC')
    end
  end

в представлениях/index.html.erb

<%= form_tag(users_path, :method => "get", id: "search-form") do %>
  <%= text_field_tag :search, params[:search], placeholder: "Search Users" %>
  <%= submit_tag "Search", :name => nil %>
<% end %>

Мы используем рельсы и postgres. Геокодер установлен. Мы храним текущую широту и долготу в отдельных столбцах.

Как мне добавить фильтр поиска близости и какие шаги я предприму с точки зрения MVC?

локация хранится в нашей схеме вот так

 create_table "users", force: :cascade do |t|
    t.float    "latitude"
    t.float    "longitude"

person Keyvman    schedule 20.06.2015    source источник


Ответы (2)


Да, на домашней странице геокодера не так много информации. Я нашел более подробную информацию в фактическом README:

https://github.com/alexreisner/geocoder#readme

Если вы хотите искать по почтовому индексу, вам нужно добавить текстовое поле для ввода в форму — назовем его zip_code. Если вы хотите, чтобы переменное расстояние также добавило тег выбора с числовыми значениями, представляющими расстояние в милях, назовите это поле distance.

Затем на стороне сервера вам нужно преобразовать почтовый индекс в широту и долготу.

zip_result = Geocoder.search(params[:zip_code])
# Is an array of results, take the first one
if zip_result 
  result = zip_result.first
  lat = result.latitude
  lon = result.longitude

  # now we can search with our model: we are asking
  # Show me all Users within "distance_in_miles" of this geocoded
  # zip code
  distance_in_miles = params[:distance].to_i
  User.search(params[:query]).near([lat, lon], distance_in_miles)
end

Это не имеет проверки ошибок или проверки - это в основном доказательство концепции.

person Cody Caughlan    schedule 20.06.2015
comment
я не могу найти в документах ничего конкретного о добавлении фильтра к поиску с близостью. - person Keyvman; 21.06.2015
comment
Могу ли я добавить это к методу индекса выше? - person Keyvman; 23.06.2015
comment
Я отредактировал свой вопрос, чтобы показать, как сохраняются широта и долгота. Я считаю, что это доступно через модель. Я думаю, что мне следует либо добавить к приведенному выше методу User.search(params[:query]).near([широта, долгота], Distance_in_miles) (поправьте меня, если я ошибаюсь), но тогда мне интересно, как получить пользовательский ввод для близости. Я не хочу, чтобы это был статический номер, управляемый серверной частью, а то, что пользователи могут контролировать из представления. - person Keyvman; 23.06.2015
comment
@ user3576650 Я ответил на ваш вопрос о близости. Вы показываете меню ВЫБОР с различными параметрами, геокодируете почтовый индекс пользователей, а затем спрашиваете, можете ли вы спросить свою модель: показать мне всех пользователей в пределах X миль от этого почтового индекса. - person Cody Caughlan; 23.06.2015
comment
я не использую почтовый индекс, у меня есть конкретные координаты. - person Keyvman; 23.06.2015
comment
Если у вас есть конкретные координаты, чем вы хотите использовать подход ограничивающей рамки: distance = 20 center_point = [40.71, 100.23] box = Geocoder::Calculations.bounding_box(center_point, distance) User.within_bounding_box(box) - person Cody Caughlan; 23.06.2015
comment
я не могу сделать радиус от моего местоположения current_user? - person Keyvman; 24.06.2015

понятно. Я изменил свою индексную функцию на пользовательском контроллере на

if params[:search]
  @users = User.search(params[:search]) \
    .near([current_user.latitude, current_user.longitude], 10) \
    .order("created_at DESC")
end
person Keyvman    schedule 23.06.2015