在Rails中创建帐户时创建随机,唯一的令牌 [英] Create random, unique tokens upon account creation in Rails

查看:70
本文介绍了在Rails中创建帐户时创建随机,唯一的令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用Devise的Rails 4应用程序(最新),并且正在尝试使用答案我能够提出以下代码:

I have a Rails 4 app using Devise (the most recent) and am trying to create a random token for each user (like the ID, but longer, etc.) Using this answer I was able to come up with the follow code:

# app/models/model_name.rb
class ModelName < ActiveRecord::Base
  include Tokenable
end

# app/models/concerns/tokenable.rb
module Tokenable
  extend ActiveSupport::Concern

  included do
    before_create :generate_token
  end

  protected

  def generate_token
    self.token = loop do
      random_token = SecureRandom.urlsafe_base64(nil, false)
      break random_token unless self.class.exists?(token: random_token)
    end
  end
end

此代码对于任何给定模型都是唯一的令牌非常有效。即所有用户将具有唯一的令牌,所有管理员将具有唯一的令牌。但是管理员可能与用户具有相同的令牌-这种行为是不必要的。

This code works fantastically for tokens that are unique for any given model. I.e. All Users will have unique tokens, and all Admins will have unique tokens. But an Admin may have the same token as a User – this behavior is unwanted.

有没有一种优雅的方法,可以将令牌抽象到自己的模型中并使用 has_one关系,以确保令牌在所有模型中都不存在是一部分?

Is there an elegant way, short of abstracting the token into its own model and using "has_one" relationships, to ensure that the token does not exist in all the models it is a part of?

(我想除非(User.exists?...或Admin.exists?... )插入到except子句中,尽管这看起来很笨重。)

(I guess I could hard code unless (User.exists? ... or Admin.exists? ... ) into the unless clause, though this seems bulky.)

任何想法或建议都值得赞赏!谢谢!

Any thoughts or suggestions are appreciated! Thanks!

推荐答案

我将创建一个方法,该方法列出包含我所关注的每个类,然后针对该令牌测试每。像这样的东西:

I would create a method that lists each of the Classes that are including my concern and then test against the token for each. Something like this:

# app/models/concerns/tokenable.rb
module Tokenable
  extend ActiveSupport::Concern

  included do
    before_create :generate_token
  end

  protected

  def included_classes
     ActiveRecord::Base.descendants.select do |c|
       c.included_modules.include(Concerns::Tokenable)}.map(&:name)
     end
  end

  def generate_token
    self.token = loop do
      random_token = SecureRandom.urlsafe_base64(nil, false)
      break random_token unless included_classes.map {|c| c.constantize.exists?(token: random_token) }.include?(true)
    end
  end
end

所以include_classes将返回一个名称数组,作为包含可标记关注点的每个类的字符串。然后在generate_token内的循环中,将对每个类进行检查,以生成一个true或false数组,然后我们使用 include?(true)。

So include_classes is going to return an array of names as strings of each of the classes that include the Tokenable concern. And then in the loop within generate_token is going to check against each of these classes generating an array of true or false which then we just check if any are true with include?(true).

在这里,我找到了如何获取包含的课程(第一个答案)。

编辑

在Rails 5中,included_classes看起来像这样(注意ApplicationRecord而不需要Concerns :: Tokenable):

In Rails 5 the included_classes looks like this (note the ApplicationRecord and not needing the Concerns::Tokenable):

  def included_classes
    ApplicationRecord.descendants.select do |c|
      c.included_modules.include?(Tokenable)
    end
  end

这篇关于在Rails中创建帐户时创建随机,唯一的令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆