Frage

Ich habe in meinem 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

Und in meinem 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

Nun, wenn der Benutzer zuerst den Eintrag erstellt, wird die Adresse geocodiert, mit der geographischen Breite und Länge in der Datenbank gespeichert.

Aber wenn der Benutzer die Adresse aktualisiert, werden die Breite und Länge nicht mehr geocodiert werden und somit immer noch mit der alten geografischen Breite und Länge, die die ersten speichern.

Wie schreibe ich Rails haben wieder geocode jedes Mal ein Eintrag Update ist?

Ich kann nicht nur die Adresse hängt davon ab, weil es ein Fehler in Geokit ist, dass wenn ich versuche, mehrere Karten auf Adresse basierend zu zeigen, nur die letzten gezeigt.

Ich bin mit Geokit, Gmaps, Google Maps ...

Danke.

War es hilfreich?

Lösung

Ich habe dies in meinem Modell:

  before_validation_on_update :geocode_address

Andere Tipps

Wenn der Benutzer ändert ihre Adresse nicht Sie es auf die gleiche Weise wie eine neue Adresse im Wesentlichen umgehen? Sie haben grundsätzlich zwei neue Adressen, die Sie brauchen nur die neu erstellte Adresse mit dem Benutzerkonto zu verknüpfen und alles soll funktionieren.

Die neue Syntax-Validierung, bevor eine bestimmte Aktion auszuführen ist:

     before_validation :geocode_address, on: :update

oder wenn Sie mehr als eine Aktion,

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

Dies wird sicherstellen, dass vor der Validierung und die Datenbank gespeichert ist getan, Ihre Methode (geocode_address) läuft zuerst.

Besser Geocoder Gem benutzen https://github.com/alexreisner/geocoder

Eigentlich in Ihrem Modell shop.rb müssen Sie die folgenden, um sicherzustellen, hinzuzufügen, dass die Längen- und Breitenfelder in Ihrer Shop Tabelle ein Benutzer jedes Mal aktualisiert, aktualisiert die Adresse Ihrer Ansicht nach.

Gemfile

gem 'geocoder', '~> 1.4'

Sie sollten zwei Felder in die Shop-Tabelle hinzufügen, Längen- und Breitengrad, stellen Sie sicher sind sie beide Schwimmer, die Migration, wenn Sie dies nicht bereits getan haben.

, dass address Unter der Annahme ist ein Feld, und es existiert in Ihrer Shop-Tabelle, und dass location.html.erb unter der Annahme ist eine Ansicht, in Ihrem Geschäft und in dieser Ansicht haben Sie so etwas wie diese

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

ich, dass auch unter der Annahme, wenn Sie Ihr Shop-Modell erstellt, um Sie die Eigenschaft active:boolean und user:references zu wissen, hinzugefügt ist ein Geschäft aktiv ist oder nicht, und weiß, zu welchem ??Benutzer hat das Geschäft gehört. So ein Benutzer hat viele Geschäfte.

Die ID shopaddress, ich bin auch hier nur für den Fall Sie Geocomplete Juwel mit Google Maps API mit der Places-Bibliothek verwenden möchten. Aber Sie brauchen nicht es dort.

shop.rb

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

Natürlich in Ihrem Controller wollen Sie sicherstellen, dass wer auch immer die Adresse der Aktualisierung zuerst autorisiert ist und dann die Methoden ausgeführt werden. Anstatt also, um sich selbst wiederholen müssen. Sie wollen wahrscheinlich so etwas wie dies in Ihren Shop-Controller erstellen.

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top