Domanda

Ho questo nel mio 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

E nella mia 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

Ora, quando l'utente crea prima l'entrata, è geocoding l'indirizzo, con latitudine e longitudine salvati nel database.

Ma quando l'utente aggiorna l'indirizzo, la latitudine e la longitudine non sarà geocodificato più, e quindi ancora utilizzando il vecchio latitudine e longitudine, che è il primo salvataggio.

Come faccio a scrivere di avere Rails ri-geocode ogni volta una voce è aggiornamento?

I non può dipendere solo l'indirizzo perché c'è un bug in Geokit che quando cerco di mostrare più mappe in base all'indirizzo, solo l'ultimo è mostrato.

sto usando Geokit, Gmaps, Google Maps ...

Grazie.

È stato utile?

Soluzione

Ho messo questo nel mio modello:

  before_validation_on_update :geocode_address

Altri suggerimenti

Se l'utente cambia il loro indirizzo non si può essenzialmente gestire allo stesso modo di un nuovo indirizzo? Hai sostanzialmente 2 nuovi indirizzi Hai solo bisogno di collegare l'indirizzo appena creato con l'account dell'utente e tutto dovrebbe funzionare.

La nuova sintassi per eseguire la convalida prima di una determinata azione è:

     before_validation :geocode_address, on: :update

o se si dispone di più di un'azione,

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

Questo farà sì che prima convalida e salvare nel database è fatto, il metodo (geocode_address) viene eseguito prima.

meglio usare Geocoder Gem https://github.com/alexreisner/geocoder

In realtà nel modello shop.rb sarà necessario aggiungere quanto segue al fine di garantire che la longitudine e la latitudine campi vengono aggiornati nella tabella negozio ogni volta che un utente aggiorna l'indirizzo nel vostro punto di vista.

Gemfile

gem 'geocoder', '~> 1.4'

Si dovrebbe aggiungere due campi alla tavola negozio, longitudine e latitudine, assicurarsi che siano entrambi i carri, rendono la migrazione, se non avete fatto questo già.

Supponendo che address è un campo ed esiste nella tabella negozio, e assumendo che location.html.erb è una vista nel vostro negozio e in quella vista si ha qualcosa di simile

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

Ho anche supponendo che, quando hai creato il tuo modello di negozio è stato aggiunto l'active:boolean proprietà e user:references sapere è un negozio è attivo o meno, e sapere a quale utente fa il negozio di appartenenza. Così un utente ha molti negozi.

L'ID shopaddress, io includo qui solo nel caso in cui si desidera utilizzare Geocomplete gioiello con API di Google Maps con la Biblioteca Places. Ma non avete bisogno di lì.

Nel shop.rb

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

Naturalmente nel controller si vuole garantire che chi sta aggiornando l'indirizzo è autorizzato prima e quindi eseguire i metodi. Così, invece di dover ripetere la vostra auto. Probabilmente si vorrà creare qualcosa di simile nel vostro controller negozio.

Nel 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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top