我在模型中创建了一个to_param
,因此我可以按其令牌而不是URL中的用户ID查找订单。这是针对未登录的来宾用户的。我这样做是为了使其他用户将无法查看其他人的订单或仅查看一般的任何人。
我的模型中有这个
validates :order_token, presence: true
validates :order_token, uniqueness: true
before_validation :generate_token, on: :create
def generate_token
begin
self.order_token = SecureRandom.urlsafe_base64(28, false)
end while self.class.find_by(order_token: order_token)
end
def to_param
order_token
end
在我的控制器中,我将其与此配合使用:
def order_confirmation
@order = Order.find_by(order_token: params[:order_token])
end
不过,我希望将此find
或find_by
仅限于order_confirmation
方法
用户登录后,我确实希望其URL中具有实际的订单ID(登录用户的所有内容均受cancancan gem保护)。这样事情对他们来说更方便。
如何限制to_param
替代仅适用于一种方法?
我的路线:
resources :orders do
get 'order_confirmation', :on => :member
end
答案 0 :(得分:0)
Overriding Named Route Parameters
在定义资源以覆盖默认资源标识符时,可以使用param
选项。为了根据路由使用不同的标识符,可以使用only
和except
选项来分别指定要包括或排除的路由。
您将需要为每个标识符创建一个resources
块。然后,您可以定义哪些路由属于哪个标识符。
为了更新to_param
方法以生成URL,您将需要能够知道您正在进行的操作以及使用的标识符。有很多方法可以做到这一点。您可以向用户模型添加attr_writer :to_param_flag
,然后在控制器上的before_action
回调中进行设置。您可以将登录状态存储在用户上。您还可以尝试其他许多解决方案,以找到最适合您项目的套件。
更新:
您可以通过几种方式定义路线。由于只有一条路线,因此可以使用匹配来代替使用资源。在match documentation和ActionDispatch::Routing::Mapper::Base#match
的用法和注释中,我们可以看到可以在:param
中使用的选项(包括match
)。
因此我们可以做:
resources :orders do
match :order_confirmation, on: :member, param: :order_token, via: :get
end
并且自get
is an alias for match...via: :get
起,我们可以做到:
resources :orders do
get :order_confirmation, on: :member, param: :order_token
end
现在将通过/orders/order_confirmation/:order_token
进行路由,控制器将可以访问params[:order_token]
。
答案 1 :(得分:0)
这就是我解决to_param问题的方式。我只是简单地删除了它,并为特定的成员路线重新组织了路线.....
使用时:
resources :orders, param: :order_token do
get 'order_confirmation', :on => :member
end
在我的路线中,我可以转到所需的URL。尽管在创建订单后,它仍然使用:id将我定向到一条路线。
然后我将重定向更改为:
redirect_to order_confirmation_order_path(@order.order_token)
而且有效。
我还删除了to_param
替代项。