【问题标题】:Geokit location undefined method `lat' with :throughGeokit 位置未定义方法 `lat' 与 :through
【发布时间】:2020-09-18 21:00:25
【问题描述】:

如 GeoKit 指南 https://github.com/geokit/geokit-rails#using-through 中所述,我正在尝试查找订单“pickup_address”范围内的所有驱动程序

司机通过 UserLocations 获得位置,而订单通过 PickupAddresses 获得位置。

我收到以下错误:

NoMethodError in OrdersController#show
undefined method `lat' for "Order"

订单.rb

class Order < ApplicationRecord

 has_paper_trail

 # an order MUST contain the following 
 validates_presence_of :description 
 validates_presence_of :weight
 validates_presence_of :length
 validates_presence_of :width
 validates_presence_of :height 
 validates_presence_of :pickup_address
 validates_presence_of :dropoff_address
 validates_presence_of :pickup_contact
 validates_presence_of :dropoff_contact

 # each order should have one address for pickup and one address for dropoff 
 has_one :pickup_address, :as => :locatable  # also works for belongs_to associations
 acts_as_mappable :through => :pickup_address
 has_one :dropoff_address, inverse_of: :order

 # each order needs two contacts 
 has_one :pickup_contact, inverse_of: :order
 has_one :dropoff_contact, inverse_of: :order
end

PickupAddress.rb

class PickupAddress < Address
  belongs_to :locatable, :polymorphic => true
  acts_as_mappable
end

我还将acts_as_mappable 添加到Address.rb 以查看代码是否可以工作,但没有任何改变。

class Address < ApplicationRecord
  belongs_to :locatable, :polymorphic => true
  acts_as_mappable

  # Attributes to have a valid address for Driver/Geocoder
  validates_presence_of :street1
  validates_presence_of :city
  validates_presence_of :state
  validates_presence_of :country
  validates_presence_of :postal
  validates_presence_of :type

  # Geocoder conversion for easier calculations 
  geocoded_by :full_address
  after_validation :geocode

  # address used by Geocoder and condensed display 
  def full_address
    [street1, city, state, country].compact.join(', ')
  end 
end

这是我遇到错误的行:

@drivers = Driver.within(5, :origin => @order)

并且,作为参考,这是我的驱动程序映射:

驱动程序.rb

class Driver < User
  has_many :orders
end

用户.rb

class User < ApplicationRecord
  # each user has a location, drivers first, then can expand later 
  has_one :user_location, :as => :locatable
  acts_as_mappable :through => :user_location
end

用户位置.rb

class UserLocation < ApplicationRecord
  belongs_to :locatable, :polymorphic => true
  acts_as_mappable :default_units => :miles

  #reverse_geocoded_by :latitude, :longitude
end

最后是架构:

create_table "user_locations", force: :cascade do |t|
t.integer  "user_id"
t.float    "lat"
t.float    "lng"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["user_id"], name: "index_user_locations_on_user_id", using: :btree
end

create_table "addresses", force: :cascade do |t|
t.string   "type"
t.string   "street1"
t.string   "street2"
t.string   "city"
t.string   "state"
t.string   "postal"
t.string   "country"
t.integer  "order_id"
t.float    "lat"
t.float    "lng"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["order_id"], name: "index_addresses_on_order_id", using: :btree
end

OrdersController.rb

class OrdersController < ApplicationController
  layout 'dashboard'

  before_action :authenticate_user!

  before_action :set_order, only: [:show, :edit, :update, :destroy]

  before_action :load_resource

  # insert generic boring stuff

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_order
      @order = Order.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def order_params
      params.require(:order).permit(:invoice, :description, :weight, :length, :width, :height, :account_id, :driver_id, :status, 
      pickup_address_attributes: [:street1, :street2, :city, :state, :postal, :country],
      dropoff_address_attributes: [:street1, :street2, :city, :state, :postal, :country],
      pickup_contact_attributes: [:first_name, :last_name, :phone],
      dropoff_contact_attributes: [:first_name, :last_name, :phone])
    end

    def load_resource 
      case params[:action].to_sym
      when :show
        if current_user.is_admin? 
          @drivers = Driver.within(5, :origin => @order)
        end 
      end 
    end 
end

使用 'lat' 和 'lng' 更改我的纬度和经度列后出现新错误:

NEW error: PG::UndefinedTable: ERROR:  missing FROM-clause entry for table "user_locations"
LINE 1: ...M "users" WHERE "users"."type" IN ('Driver') AND (user_locat...
                                                         ^
: SELECT "users".* FROM "users" WHERE "users"."type" IN ('Driver') AND (user_locations.lat IS NOT NULL AND user_locations.lng IS NOT NULL) AND (user_locations.lat>29.61103991439227 AND user_locations.lat<38.28523108560773 AND user_locations.lng>-88.97349091777367 AND user_locations.lng<-78.5259326822263) AND (((ACOS(least(1,COS(0.5925067393881714)*COS(-1.4617082185063466)*COS(RADIANS(user_locations.lat))*COS(RADIANS(user_locations.lng))+ COS(0.5925067393881714)*SIN(-1.4617082185063466)*COS(RADIANS(user_locations.lat))*SIN(RADIANS(user_locations.lng))+ SIN(0.5925067393881714)*SIN(RADIANS(user_locations.lat))))*3963.1899999999996) <= 300))

【问题讨论】:

  • 我离开了指南,位于此处:github.com/geokit/geokit-rails
  • 您需要提供订单控制器。
  • 为你添加了控制器!
  • 但是pickup_address没有lat和lng属性,怎么知道提货地址点?
  • 取货地址确实有 lat 和 lng 属性。

标签: ruby-on-rails ruby geokit


【解决方案1】:

让我们在这里清楚您尝试运行的方法是如何工作的

@drivers = Driver.within(5, :origin => @order)

您发送到该方法的 origin 属性需要是具有 lat 和 lng 属性的模型的实例,并且似乎 order 没有它们,在示例中,您有两个具有这些属性的模型 @ 987654321@ 和 user_locations 只需将 @order 更改为具有您想要驱动程序的 lat 和 lng 的实例

【讨论】:

  • 新错误:#<0x007f8c29af2e88>
【解决方案2】:

gem 中的through 与this 一样存在很长时间的问题

解决方案是在 model 和 geokit 方法调用之间使用显式连接

driver 是user 的子类,user 具有geokit 的方法并可通过user_location 映射

所以要让Driver.within(5, :origin =&gt; @order) 工作,你需要这样写

Driver.joins(:user_location).within(5, :origin =&gt; @order)

【讨论】:

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