FriendlyID controller names check for inclusion issue

Basically I have an application (using a program) where the user registrations#new

only signs with email and password; this registers and creates a user. He immediately transfers them to registrations#edit

where they enter the rest of the information.

I am using the attribute :name

with friendly_id for vanity purposes. This attribute has 3 requirements:

  • It should be written once, but unchanged after it is written.
  • It cannot be any of the controller names (or it will break the application).
  • It is unique

For # 2 So I added the following validation model: `

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

      

For # 3 I added validates_uniqueness_of :name

For # 1 I have the following, in my opinion, under # edit registration:

<% if @user.name.blank?%>
                <br>
                <h2>Choose your username</h2>

                    <%= f.input :name,  :value => "Username" , required: true, autofocus: true, label:false, class: 'usernameinputc'  %>

<br>

      

This effectively hides it from the user if it doesn't exist. The problem I am facing is that if they enter the controller name as their own, :name

or something already done, it will give an error on creation and send back, but the field will be hidden. If I remove the conditional then it allows them to change them :name

even if it really was? How can I make it so that it only shows if the name attribute was not saved?

Note: I tried it if @user.name.persisted?

, it gave me a method error for nilClass (I think because it :name

doesn't exist.

UPDATE

So I tried to add it as a virtual attribute, I added field: username to my allowed options as a virtual attribute. Having a bit of trouble with getter and setter methods. I've tried this:

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

      

I am still getting the method error.

+3


source to share


2 answers


What if you try this? This will validate your name against the blacklist, but will also cause user.name to be empty when it does. This way your erb will display correctly.



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

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

      

+1


source


Use a virtual attribute to store the value in the form.

attr_accessor :desired_name

      

When the form is submitted, it will be completed User.desired_name

. Then do your value checks. If it passes, copy the virtual attribute to the database field attribute and save and redirect. (Or copy the value, confirm, and if an error occurs, set it .name

back to null.) If the actual field is not empty, hide the form.



You have to know that it is almost a security risk to hide the form. You should check in your method #update

that there is no existing value for .name

, because a hacker can create his own form and submit the value to change it.

Here is a tutorial on virtual attributes: http://railscasts.com/episodes/16-virtual-attributes

-2


source







All Articles