FriendlyID 控制器名称验证包含问题

FriendlyID Controller names validates inclusion issue

基本上我有一个应用程序(使用设计),用户只需要一个电子邮件和密码就可以注册 registrations#new;这将注册并创建用户。它会立即将他们带到 registrations#edit,在那里他们输入其余信息。

我将 :name 属性与 friendly_id 一起用于个性化网址。此属性有 3 个要求:

  1. 必须一次写入,写入后不可更改
  2. 它不能是任何控制器名称(否则会破坏应用程序)。
  3. 独一无二

#2 所以我在我的模型中添加了以下验证: `

  validates :name, :exclusion => { :in => %w(
  admin cars registrations users
 ), :message => "Sorry \"%{value}\" is taken!"}`

#3 我加了 validates_uniqueness_of :name

#1 我在 registrations#edit 下的视图中有以下内容:

<% if @user.name.blank?%>
                <br>
                <h2>Choose your username</h2>
            
                    <%= f.input :name,  :value => "Username" , required: true, autofocus: true, label:false, class: 'usernameinputc'  %>
           
<br>

如果它不存在,这会有效地向用户隐藏它。我遇到的问题是,如果他们输入一个控制器名称作为他们的 :name 或已经使用的东西,它将给出一个设计错误,并将它们发回但该字段将被隐藏。如果我删除条件,那么它允许他们更改他们的 :name 即使它是有效的?我怎样才能使它仅在名称属性尚未保存时显示?

注意:我试过 if @user.name.persisted? 它给了我 nilClass 的无方法错误(我想是因为 :name 不存在。

更新

所以我尝试将其添加为虚拟属性,我已将字段 :username 添加到我允许的参数中作为虚拟属性。 getter 和 setter 方法有点麻烦。我试过这个:

def username
  self.name if  self.name.persisted?
end

我仍然遇到无方法错误。

使用虚拟属性来保存表单中的值。

attr_accessor :desired_name

提交表单后,将填写 User.desired_name。然后对值​​执行验证。如果通过,则将虚拟属性复制到数据库字段属性中,保存并重定向。 (或复制值,验证,如果有错误,将 .name 设置回 null。)如果真实字段不为空,则隐藏表单。

您应该知道,仅隐藏表单几乎是一种安全风险。您应该在 #update 方法中验证 .name 不存在现有值,因为黑客可以创建他们自己的表单并提交该值以更改它。

虚拟属性教程如下:http://railscasts.com/episodes/16-virtual-attributes

如果你试试这个会怎么样?这将根据黑名单验证您的名字,但也会在发生这种情况时将 user.name 设置为空白。这样您的 erb 仍将正确呈现。

  validate do |user|
    if %w(admin cars registrations users).include?(user.name)

      user.errors[:name] << "Sorry \"" + user.name + "\" is taken!"
      user.name = ""
    end
  end