我正在使用地理编码。这个想法是我们的合作伙伴可以发布带有地址的产品。当他们这样做时,它将获取经度和纬度。现在,当我们的客户去购买该产品时,他们必须输入送货地址以告诉我们该产品在哪里送货。但是,如果他们的送货地址不在产品的20英里之内,则不允许他们送货。
我收到一条错误消息,提示此“ nil:NilClass的未定义方法'latitude'”
就像我说的那样,当用户尝试订购产品时,product.longitude,product.latitude已经设置。
不确定是否是因为order.delivery_address(lat,long)尚未提交到数据库中,并且它正在尝试检查距离。这是我的下面的代码
所以我的问题是如何找到产品地址和订单地址之间的距离,并且如果两者之间的距离超过20英里,我想向用户显示警报消息。
def create
product = Product.find(params[:product_id])
if current_user == product.user
flash[:alert] = "You cannot purchase your own property"
elsif current_user.stripe_id.blank? || current_user.phone_number.blank?
flash[:alert] = " Please update your payment method and verify phone number please"
return redirect_to payment_method_path
elsif Geocoder::Calculations.distance_between([product.latitude, product.longitude], [@order.latitude, @order.longitude]) < 20
flash[:alert] = "The delivery address you provided is outside the delivery zone. Please choose a different product."
else
quantity = order_params[:quantity].to_i
@order = current_user.orders.build(order_params)
@order.product = product
@order.price = product.price
@order.total = product.price * quantity + product.delivery_price
# @order.save
if @order.Waiting!
if product.Request?
flash[:notice] = "Request sent successfully... Sit back and relax while our licensed dispensary fulfil your order :)"
else
@order.Approved!
flash[:notice] = "Your order is being filled and it will delivered shortly:)"
end
else
flash[:alert] = "Our licensed dispensary cannot fulfil your order at this time :( "
end
end
redirect_to product
end
答案 0 :(得分:2)
您在以下行中设置了@order
:
@order = current_user.orders.build(order_params)
但是您甚至在设置longitude
变量之前,尝试在其之上调用其latitude
和@order
方法。为了简单地解决此问题,您可以将该行上移,甚至可以将其放在create
方法的开头,因为它不依赖于product
或类似的东西:
def create
@order = current_user.orders.build(order_params)
# ...
end
尽管您的代码中存在许多问题,例如以大写字母开头的方法名称(您可以做到这一点,但是您不应该这样做,这违反了惯例)或代码的整体复杂性方法。
答案 1 :(得分:1)
您应该将业务逻辑移动到它所属的模型中。
因此,让我们首先为产品距离创建一个验证:
go build
然后将总计的计算移入模型:
class Order < ApplicationRecord
validates :product_is_within_range,
if: -> { product.present? } # prevents nil errors
# our custom validation method
def product_is_within_range
errors.add(:base, "The delivery address you provided is outside the delivery zone. Please choose a different product.") if product_distance < 20
end
def product_distance
Geocoder::Calculations.distance_between(product.coordinates, self.coordinates)
end
end
但是您仍然必须处理控制器非常坏的事实。例如:
class Order < ApplicationRecord
before_validation :calculate_total!, if: ->{ product && total.nil? }
def calculate_total!
self.total = product.price * self.quantity + product.delivery_price
end
end
应使该方法保释。您实际上也没有保存记录。我会重新开始。针对不同的可能情况(无效参数,有效参数,用户是所有者等)编写失败的测试,然后编写控制器代码。确保测试每个代码分支。