Geokit位置未定义方法`lat'用:通过

时间:2017-04-24 19:34:10

标签: ruby-on-rails ruby geokit

我正在尝试找到Order' pickup_address'距离内的所有驱动程序,如GeoKit指南中所述https://github.com/geokit/geokit-rails#using-through

驱动程序通过UserLocations拥有位置,订单通过PickupAddresses具有位置。

我收到以下错误:

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

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)

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

Driver.rb

class Driver < User
  has_many :orders
end

User.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

UserLocation.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
使用&#39; lat&#39;更改我的纬度和经度列后,

NEW ERROR和&#39; lng&#39;建议更改:

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))

2 个答案:

答案 0 :(得分:0)

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

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

您要发送给方法的origin属性需要是具有lat和lng属性的模型的实例,并且看起来顺序没有它们,例如,您有两个具有这些属性的模型属性addressesuser_locations只更改了具有你的lat和lng的实例的@order

答案 1 :(得分:0)

this一样,gem中的through已有很长时间了

解决方案是在modelgeokit方法调用之间使用显式联接

driveruser的子类,并且user具有geokit的方法并且可以通过user_location进行映射

要使Driver.within(5, :origin => @order)正常工作,您需要这样写

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