Обновлять широту и долготу геокода при каждом обновлении адреса - PullRequest
2 голосов
/ 27 октября 2010

У меня есть это в моем shop.rb:

def geocode_address
  if !address_geo.blank?
    geo=Geokit::Geocoders::MultiGeocoder.geocode(address_geo)
    errors.add(:address, "Could not Geocode address") if !geo.success
    self.lat, self.lng = geo.lat,geo.lng if geo.success
  end
end

# Checks whether this object has been geocoded or not. Returns the truth
def geocoded?
  lat? && lng?
end

И в моем shops_controller.rb:

def update
@shop = Shop.find(params[:id])
if @shop.update_attributes(params[:shop])
  flash[:notice] = "Successfully saved."
  redirect_to shop_path(@shop, :type => @shop.shop_type)
else
  render :action => :edit
end
end

Теперь, когда пользователь впервые создает запись, адрес геокодируетсяс широтой и долготой, сохраненными в базе данных.

Но когда пользователь обновляет адрес, широта и долгота больше не будут геокодироваться, и, таким образом, все еще будут использоваться старая широта и долгота, которая является первым сохранением.

Как мне написать, чтобы Rails повторно геокодировал каждый раз, когда запись обновляется?

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

Я использую геокит, Gmaps, Google Maps ...

Спасибо.

Ответы [ 4 ]

2 голосов
/ 27 октября 2010

Я положил это в моей модели:

  before_validation_on_update :geocode_address
0 голосов
/ 08 мая 2019

Лучше использовать Geocoder Gem https://github.com/alexreisner/geocoder

На самом деле в вашей модели shop.rb вам нужно будет добавить следующее, чтобы поля долготы и широты обновлялись в таблице вашего магазина каждый раз, когда пользовательобновляет адрес в вашем представлении.

Gemfile

gem 'geocoder', '~> 1.4'

Вы должны добавить два поля в таблицу Shop, долготу и широту, убедитесь, что они оба являются плавающими,выполнить миграцию, если вы еще этого не сделали.

Предполагая, что address - это поле, и оно существует в вашей таблице магазинов, и предполагая, что location.html.erb - это представление в вашем магазине, и в этом представлении у вас есть что-то вроде

<%= f.text_field :address, placeholder: "Your Shop's Address", class: "form-control", required: true, id: "shopaddress" %>

Я также предполагаю, что при создании модели магазина вы добавили свойства active:boolean и user:references, чтобы узнать, является магазин активным или нет, и знать, к какому пользователю принадлежит магазин.,Таким образом, у одного пользователя есть много магазинов.

Адрес магазина ID, я включаю его на всякий случай, если вы хотите использовать Geocomplete gem с Google Maps API с Библиотекой мест.Но вам это здесь не нужно.

В shop.rb

geocoded_by :address
# Will Update if changed
after_validation :geocode, if: :address_changed?

Конечно, в вашем контроллере вы захотите убедиться, что тот, кто обновляет адрес,авторизоваться сначала, а затем запустить методы.Так что вместо того, чтобы повторять себя.Возможно, вы захотите создать что-то подобное в контроллере своего магазина.

В shops_controller.rb

class ShopsController < ApplicationController
  # If your shop owners are creating many shops you will want to add 
  #your methods here as well with index. Eg. :create, :new
  # In case you have a view shop page to show all people 

  before_action :set_shop, except: [:index]

  before_action :authenticate_user!, except: [:show]

  # I am assuming that you also want to update other fields in your 
  #shop and the address isn't the only one.

  before_action :is_user_authorised, only: [:name_x, :name_y, :name_z, :location, :update]

  def index
    @shops = current_user.shops
  end

  def show
    @photos = @shop.photos
    @product_reviews = @shop.product_reviews
  end

  def name_x
  end

  def name_y
  end

  def name_z
  end

  def location
  end

  def update
    new_params = shop_params
    # To ensure the shop is actually published
    new_params = shop_params.merge(active: true) if is_shop_ready

    if @shop.update(new_params)
      flash[:notice] = "Saved..."
    else
      flash[:alert] = "Oh oh hmm! something went wrong..."
    end
    redirect_back(fallback_location: request.referer)
  end

  private

    def set_shop
      @shop = Shop.find(params[:id])
    end

    def is_user_authorised
      redirect_to root_path, alert: "You don't have permission" unless 
      current_user.id == @shop.user_id
    end

    # You can play with this here, what defines a ready shop?
    def is_shop_ready
      !@shop.active && !@shop.name_x.blank? && 
      !@shop.name_y.blank? && !@shop.name_z.blank? && 
      !@shop.address.blank?
    end

    # Here you are allowing the authorized user to require her shop and it's properties, so that she can update them with update method above.
    # eg_summary, eg_shop_type, eg_shop_name are just additional #example properties that could have been added when you iniitially created your Shop model
    def shop_params
      params.require(:shop).permit(:address, :active, :eg_shop_name, :eg_shop_summary, :eg_shop_type)
    end

end
0 голосов
/ 20 июня 2018

Новый синтаксис для проверки перед определенным действием:

     before_validation :geocode_address, on: :update

или, если у вас более одного действия,

    before_validation :geocode_address, on: %i[create update]

Это будет гарантировать, что перед проверкой и сохранениемк базе данных сделано, ваш метод (geocode_address) запускается первым.

0 голосов
/ 27 октября 2010

Если пользователь меняет свой адрес, разве вы не можете обработать его так же, как новый адрес? В основном у вас есть 2 новых адреса, вам просто нужно связать вновь созданный адрес с учетной записью пользователя, и все должно работать.

...