每次更新地址时更新地理编码纬度和经度

时间:2010-10-27 13:58:04

标签: ruby-on-rails google-maps geokit geocode

我在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,Google地图......

感谢。

4 个答案:

答案 0 :(得分:2)

我把它放在我的模型中:

  before_validation_on_update :geocode_address

答案 1 :(得分:0)

如果用户更改了他们的地址,您基本上不能像新地址一样处理它吗?您基本上只需要2个新地址即可将新创建的地址与用户的帐户相关联,一切都应该有效。

答案 2 :(得分:0)

在执行特定操作之前执行验证的新语法为:

     before_validation :geocode_address, on: :update

或者如果您有多个动作,

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

这将确保在完成验证并保存到数据库之前,首先运行您的方法(geocode_address)。

答案 3 :(得分:0)

更好地使用Geocoder Gem https://github.com/alexreisner/geocoder

实际上,在模型shop.rb中,您将需要添加以下内容,以确保每次用户更新视图中的地址时,商店表中的经度和纬度字段都会更新。

宝石文件

gem 'geocoder', '~> 1.4'

您应该在Shop表中添加两个字段,经度和纬度,确保它们都是浮点数,如果尚未进行迁移,请进行迁移。

假设address是一个字段并且它存在于您的商店表中,并且假设location.html.erb是您商店中的一个视图,并且在该视图中您具有类似的内容

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

我还假设,当您创建商店模型时,您添加了属性active:booleanuser:references来了解商店是否处于活动状态,并知道该商店属于哪个用户。因此,一个用户有很多商店。

ID商店地址,如果您想将Geocomplete gem与Google Maps 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