【问题标题】:Update geocode latitude and longitude everytime address is updated每次更新地址时更新地理编码纬度和经度
【发布时间】:2010-10-27 13:58:04
【问题描述】:

我的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、谷歌地图...

谢谢。

【问题讨论】:

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


    【解决方案1】:

    我把它放在我的模型中:

      before_validation_on_update :geocode_address
    

    【讨论】:

      【解决方案2】:

      如果用户更改了他们的地址,您就不能以与新地址相同的方式处理它吗?您基本上有 2 个新地址,您只需要将新创建的地址与用户帐户相关联,一切都应该正常。

      【讨论】:

      • 不,这不是用户的地址。是店铺地址。假设最初商店的地址与城市和国家信息一起保存,地理编码将基于该城市和国家。但是当它更新为带有街道名称的更精确地址时,地理编码应该更新经度和纬度。
      【解决方案3】:

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

           before_validation :geocode_address, on: :update
      

      或者如果您有多个操作,

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

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

      【讨论】:

        【解决方案4】:

        最好使用 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" %>

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

        ID shopaddress,我在这里包括以防您想将 Geocomplete gem 与 Google Maps API 与 Places Library 一起使用。但你不需要它。

        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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-01-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多