更新地理编码经纬度每次地址更新
-
26-09-2019 - |
题
我有这在我的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的重新地理编码每次一个条目更新?
我不能因为在geokit,当我试图说明基于地址的多个地图中的错误,只有最后一个显示仅仅依靠地址。
我使用geokit,Gmaps,谷歌地图...
感谢。
解决方案
我把这个在我的模型:
before_validation_on_update :geocode_address
其他提示
如果用户更改他们的地址,你就不能本质上处理它以同样的方式作为一个新的地址?你基本上你只需要到新创建的地址与用户的帐户链接2个新地址,一切都应该工作。
的特定动作之前执行验证的新的语法是:
before_validation :geocode_address, on: :update
或者如果有一个以上的动作,
before_validation :geocode_address, on: %i[create update]
这将确保验证之前,并保存到数据库完成后,你的方法(geocode_address
)先运行。
最好使用地理编码宝石 https://github.com/alexreisner/geocoder
其实在你的模型shop.rb你将需要添加以下,以确保经度和纬度字段将会在你的店铺表中的每个用户在视图更新地址时更新。
<强>的Gemfile 强>
gem 'geocoder', '~> 1.4'
您应该添加两个字段的表店,经度和纬度,确保他们都是浮动,使迁移,如果你还没有这样做了。
假设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 shopaddress,我包括在这里,以防万一你想使用Geocomplete宝石与商家信息库谷歌地图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