Rails的validatation确保用户名不与现有路由发生冲突? [英] Rails validatation to ensure a username does not clash with an existing route?

查看:267
本文介绍了Rails的validatation确保用户名不与现有路由发生冲突?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要确保用户无法创建与我现有的路线冲突的用户名。我也想否认未来的路我可以定义的能力。我想实现这一点,像这样的:

I want to ensure users can't create usernames that clash with my existing routes. I would also like the ability to deny future routes I may define. I am thinking of accomplishing this like so:

在模型中:

class User < ActiveRecord::Base
  @@invalid_usernames = %w()

  cattr_accessor :invalid_usernames

  validates :username, :exclusion { :in => @@invalid_usernames }
end

在一些初始化:

User.invalid_usernames += Rails.application.routes.routes.map(&:path).join("\n").scan(/\s\/(\w+)/).flatten.compact.uniq

这是Rails的方式?有没有更好的办法?

Is this "Rails way"? Is there a better way?

推荐答案

下面是我自己的答案,测试和使用Rails 3.1.3和Ruby 1.9.3工作

Here's my own answer, tested and working with Rails 3.1.3 and Ruby 1.9.3

应用程序/模型/ user.rb

app/models/user.rb

class User < ActiveRecord::Base
  class_attribute :invalid_usernames
  self.invalid_usernames = Set.new %w()

  validates :username, presence:   true,
                       uniqueness: { case_sensitive: false },
                       exclusion:  { in: lambda { self.invalid_usernames }}
end

配置/ application.rb中

config/application.rb

[:after_initialize, :to_prepare].each do |hook|
  config.send(hook) do
    User.invalid_usernames += Rails.application.routes.routes.map(&:path).join("\n").scan(/\s\/(\w+)/).flatten.compact.uniq
  end
end


注意

我开始试着设置 User.invalid_usernames after_initialize 却发现它需要在<$ C $要设置C> to_ prepare (即之前的的发展模式下,每个的请求,并在第一的生产模式请求),因为模型重载发展的每个请求,原来的设定丢失之前。


Notes

I initially tried setting User.invalid_usernames during after_initialize but found it needs to be set during to_prepare (i.e. before each request in development mode, and before the first request in production mode) since the models are reloaded in development before each request and the original setting is lost.

不过,我的的设置 User.invalid_usernames after_initialize ,因为路由唐'T似乎在测试环境中运行的时候要在 to_ prepare 可用。另一个解决方法我试过了这一点,它不工作,是在为强制加载路线 to_ prepare

I am however also setting User.invalid_usernames during after_initialize because the routes don't seem to be available during to_prepare when running in the test environment. Another workaround I tried for this, which does work, is to force load the routes during to_prepare:

config.to_prepare do
  Rails.application.reload_routes!
  User.invalid_usernames += Rails.application.routes.routes.map(&:path).join("\n").scan(/\s\/(\w+)/).flatten.compact.uniq
end

我喜欢这个,因为它的干燥,易于阅读。但我小心重载线路上的每个请求,即使它只是在发展模式。我宁愿使用东西的的难读,如果这意味着我完全理解的影响。打开要批评!

I like this because it's DRY and easy to read. But I'm wary of reloading the routes on every request, even if it is only in development mode. I'd rather use something a little harder to read if it means I fully understand the impact. Open to criticisms!

我也抛弃了 cattr_accessor ​​ class_attribute 当我发现前者适用于整个类层次结构(即改变其子类值会影响超)

I also ditched cattr_accessor for class_attribute when I found out the former applies to the entire class hierarchy (i.e. changing its value on a subclass would affect the superclass)

我还选择使用了设置 User.invalid_usernames 不是数组,因为没有必要存储和比较反对易受骗的人,这是一个透明的变化。

I also chose to use a Set for User.invalid_usernames instead of an array as there's no need to store and compare against dupes and it was a transparent change.

我也改变了Ruby 1.9哈希语法(:

I also changed to Ruby 1.9 hash syntax (:

这篇关于Rails的validatation确保用户名不与现有路由发生冲突?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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