Question

J'ai dans mon 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

Et dans mon 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

lorsque l'utilisateur crée d'abord l'entrée, l'adresse est géocodée, avec la latitude et la longitude enregistrées dans la base de données.

Mais lorsque l'utilisateur met à jour l'adresse, la latitude et la longitude ne sera pas géocodées plus, et donc en utilisant encore l'ancienne latitude et la longitude qui est le premier enregistrement.

Comment puis-je écrire avoir Rails re-géocodage à chaque fois une entrée est mise à jour?

Je ne peux pas dépendre uniquement l'adresse parce qu'il ya un bogue dans Geokit que lorsque je tente de montrer plusieurs cartes basées sur l'adresse, seul le dernier est affiché.

J'utilise Geokit, Gmaps, Google Maps ...

Merci.

Était-ce utile?

La solution

Je mets cela dans mon modèle:

  before_validation_on_update :geocode_address

Autres conseils

Si l'utilisateur change leur adresse ne peut pas vous traiter essentiellement de la même façon que d'une nouvelle adresse? Vous avez essentiellement 2 nouvelles adresses il vous suffit de relier l'adresse nouvellement créée avec le compte de l'utilisateur et tout devrait fonctionner.

La nouvelle syntaxe pour effectuer la validation avant une action spécifique est:

     before_validation :geocode_address, on: :update

ou si vous avez plus d'une action,

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

Cela garantira que avant la validation et l'enregistrement dans la base de données est fait, votre méthode (geocode_address) se dirige d'abord.

Il vaut mieux utiliser géocodage Gem https://github.com/alexreisner/geocoder

En fait, dans votre shop.rb modèle vous devez ajouter ce qui suit pour faire en sorte que la longitude et la latitude champs sont mis à jour dans votre table de magasin chaque fois qu'un utilisateur met à jour l'adresse de votre point de vue.

Gemfile

gem 'geocoder', '~> 1.4'

Vous devriez ajouter deux champs à la table de magasin, la longitude et la latitude, assurez-vous qu'ils sont tous les deux flotteurs, faire la migration si vous ne l'avez pas déjà fait cela.

En supposant que address est un champ et il existe dans votre table de magasin, et en supposant que location.html.erb est une vue dans votre magasin et ce point de vue que vous avez quelque chose comme ceci

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

Je supposant aussi que, lorsque vous avez créé votre modèle boutique vous avez ajouté le active:boolean de la propriété et user:references savoir est un magasin est actif ou non, et de savoir à quel utilisateur fait la boutique appartient. Ainsi, un utilisateur a de nombreux magasins.

Le shopaddress ID, je suis ici, y compris au cas où vous voulez utiliser avec l'API gem Geocomplete Google Maps avec la Bibliothèque Lieux. Mais vous n'avez pas besoin là.

shop.rb

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

Bien sûr, dans votre contrôleur, vous devrez vous assurer que quiconque est mise à jour l'adresse est autorisée, puis exécutez les méthodes. Ainsi, au lieu d'avoir à répéter votre auto. Vous aurez probablement envie de créer quelque chose comme ça dans votre contrôleur boutique.

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top