Mise à jour géocodage latitude et la longitude adresse chaque fois est mis à jour
-
26-09-2019 - |
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.
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