住所が更新されるたびにジオコードの緯度と経度を更新します
-
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、Gmap、Google マップを使用しています...
ありがとう。
解決
私は私のモデルでこれを入れます:
before_validation_on_update :geocode_address
他のヒント
ユーザーが自分のアドレスを使用して、基本的に新しいアドレスとしてそれを同じように扱うことができない変更した場合は?あなたは、基本的にはあなただけのユーザーのアカウントを新たに作成されたアドレスをリンクする必要があり、すべてが動作するはず2つの新しいアドレスを持っています。
特定のアクションの前に検証を実行するための新しい構文は次のとおりです。
before_validation :geocode_address, on: :update
または複数のアクションを持っている場合は、
before_validation :geocode_address, on: %i[create update]
これは、検証し、データベースへの保存が行われる前に、あなたの方法(geocode_address
)が最初に実行されること。
Geocoder Gem を使用することをお勧めします https://github.com/alexreisner/geocoder
実際には、モデル shop.rb に次のコードを追加して、ユーザーがビュー内の住所を更新するたびにショップ テーブルの経度と緯度のフィールドが更新されるようにする必要があります。
Gemfile
gem 'geocoder', '~> 1.4'
Shop テーブルに経度と緯度の 2 つのフィールドを追加し、両方とも浮動小数点であることを確認し、まだ移行していない場合は移行を行う必要があります。
仮定して address
はフィールドであり、ショップテーブルに存在し、次のように仮定します location.html.erb
これはあなたのショップのビューであり、そのビューには次のようなものがあります
<%= f.text_field :address, placeholder: "Your Shop's Address", class: "form-control", required: true, id: "shopaddress" %>
また、Shop モデルを作成したときにプロパティを追加したと仮定します。 active:boolean
そして user:references
ショップがアクティブかどうか、またショップがどのユーザーに属しているかを知ることができます。つまり、1人のユーザーがたくさんのショップを持っています。
ID ショップアドレス。Places Library を使用して Google Maps API で Geocomplete gem を使用する場合に備えて、ここに含めておきます。しかし、そこには必要ありません。
で ショップ.rb
geocoded_by :address
# Will Update if changed
after_validation :geocode, if: :address_changed?
もちろん、コントローラーでは、アドレスを更新する人が最初に承認されていることを確認してから、メソッドを実行する必要があります。ですから、自分自身を繰り返す必要はありません。おそらく、ショップ コントローラーでこのようなものを作成するとよいでしょう。
で ショップ_コントローラー.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