如何仅在一种方法上使用to_param-或对其他方法禁用?

时间:2019-01-08 04:31:11

标签: ruby-on-rails ruby

我在模型中创建了一个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

不过,我希望将此findfind_by仅限于order_confirmation方法

用户登录后,我确实希望其URL中具有实际的订单ID(登录用户的所有内容均受cancancan gem保护)。这样事情对他们来说更方便。

如何限制to_param替代仅适用于一种方法?

我的路线:

resources :orders do
      get 'order_confirmation', :on => :member
  end

2 个答案:

答案 0 :(得分:0)

Overriding Named Route Parameters

在定义资源以覆盖默认资源标识符时,可以使用param选项。为了根据路由使用不同的标识符,可以使用onlyexcept选项来分别指定要包括或排除的路由。

您将需要为每个标识符创建一个resources块。然后,您可以定义哪些路由属于哪个标识符。

为了更新to_param方法以生成URL,您将需要能够知道您正在进行的操作以及使用的标识符。有很多方法可以做到这一点。您可以向用户模型添加attr_writer :to_param_flag,然后在控制器上的before_action回调中进行设置。您可以将登录状态存储在用户上。您还可以尝试其他许多解决方案,以找到最适合您项目的套件。

更新

您可以通过几种方式定义路线。由于只有一条路线,因此可以使用匹配来代替使用资源。在match documentationActionDispatch::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替代项。