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.
source to share
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
source to share
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
source to share