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

发布于 2024-09-29 07:31:37 字数 971 浏览 4 评论 0原文

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

谢谢。

I have this in my 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

And in my 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

Now when the user first creates the entry, the address is geocoded, with latitude and longitude saved to the database.

But when the user updates the address, the latitude and longitude will not be geocoded anymore, and thus still using the old latitude and longitude which is the first save.

How do I write to have Rails re-geocode everytime an entry is update?

I can't depend on just the address because there is a bug in geokit that when I try to show multiple maps based on address, only the last one is shown.

I'm using geokit, Gmaps, Google Maps...

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

别理我 2024-10-06 07:31:37

我将其放入我的模型中:

  before_validation_on_update :geocode_address

I put this in my model:

  before_validation_on_update :geocode_address
孤单情人 2024-10-06 07:31:37

如果用户更改了他们的地址,您不能像处理新地址一样以同样的方式处理它吗?您基本上有 2 个新地址,您只需将新创建的地址与用户的帐户链接起来,一切就应该可以正常工作。

If the user changes their address can't you essentially handle it the same way as a new address? You basically have 2 new addresses you just need to link the newly created address with the user's account and everything should work.

×纯※雪 2024-10-06 07:31:37

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

     before_validation :geocode_address, on: :update

或者如果您有多个操作,

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

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

The new syntax to perform validation before a specific action is:

     before_validation :geocode_address, on: :update

or if you have more than one action,

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

This will ensure that before validation and saving to the database is done, your method (geocode_address) runs first.

梦纸 2024-10-06 07:31:37

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

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

Gemfile

gem 'geocoder', '~> 1.4'

您应该向 Shop 表添加两个字段,经度和纬度,确保它们都是浮点型,如果您还没有这样做,请进行迁移。

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

<%= 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 和 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
      [email protected] && [email protected]_x.blank? && 
      [email protected]_y.blank? && [email protected]_z.blank? && 
      [email protected]?
    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

Better to use Geocoder Gem https://github.com/alexreisner/geocoder

Actually in your model shop.rb you will need to to add the following to ensure that the longitude and latitude fields get updated in your shop table every time a user updates the address in your view.

Gemfile

gem 'geocoder', '~> 1.4'

You should add two fields to the Shop table, longitude and latitude, make sure they are both floats, make the migration if you have not done this already.

Assuming that address is a field and it exists in your shop table, and assuming that location.html.erb is a view in your shop and in that view you have something like this

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

I also assuming that, when you created your Shop model you added the property active:boolean and user:references to know is a shop is active or not, and know to which user does the shop belong to. So one user has many shops.

The ID shopaddress, i am including here just in case you want to use Geocomplete gem with Google Maps API with the Places Library. But you do not need it there.

In shop.rb

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

Of course in your controller you will want to ensure that whoever is updating the address is authorized first and then run the methods. So instead of having to repeat your self. You'll probably want to create something like this in your shop controller.

In 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
      [email protected] && [email protected]_x.blank? && 
      [email protected]_y.blank? && [email protected]_z.blank? && 
      [email protected]?
    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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文