Ruby on Rails Modelling users [closed] - ruby-on-rails

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
class User < ActiveRecord::Base
before_save { self.email = email.downcase }
(validates :name, presence: true, length: { maximum: 50 })
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 };
format: { with: VALID_EMAIL_REGEX };
uniqueness: { case_sensitive: false },
has_secure_password:
(validates :password, presence: true, length:{ minimum: 6 } )
end
Someone help me to figure out where this syntax has an error

In your User model try this:
class User < ActiveRecord::Base
before_validation { self.email = email.downcase! }
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, presence: true, length: { minimum: 6 }
end

Your model should looks like below.
class User < ActiveRecord::Base
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
before_save { self.email = email.downcase }
validates :name, presence: true, length: { maximum: 50 }
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates :password, presence: true, length:{ minimum: 6 }
has_secure_password
end

You probably also want to change this line:
before_save { self.email = email.downcase }
Into this:
before_validation { self.email = email.downcase }
The way this is going to go down is:
Validation
Before save callbacks
Actual save
So a user will use uppercase letters in his email, then save and the validations will fail because of the use of uppercase letters.
So you want to set his email to lower case letters BEFORE the validations and not after :-)

Related

Wrap multiple validations in a context

With validation context we can do:
validates :title, presence: true, on: :published
validates :content, length: { maximum: 50 }, on: :published
Is it possible to wrap multiple validations that share a context something like the following?
on: :published do
validates :title, presence: true
validates :content, length: { maximum: 50 }
end
Yes, you can group validations using the with_options method:
with_options(on: :published) do |record|
record.validates :title, presence: true
record.validates :content, length: { maximum: 50 }
end
See the Rails Guides, this article and the sources for more info.

How to structure a Ruby on Rails model?

In our app's User model, we already have:
attr_accessor :remember_token, :activation_token, :reset_token
before_save :downcase_email
before_create :create_activation_digest
before_save { self.email = email.downcase }
validates :first_name, presence: true, length: { maximum: 50 }
validates :last_name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, presence: true, length: { minimum: 6 }, allow_nil: true
Now, we need to add relationship associations to the model, namely:
has_many :roles, dependent: :destroy
has_many :agendas, through: :roles
Does it matter whether we include the latter go BEFORE or AFTER the former, in the model?
If so, what is the recommended / preferred / best way?
It doesn't matter, but the important thing is to be consistent. A usual best practice is to first do all you can to declare the class' structure, before you get in to any operational details. For example:
class User < ActiveRecord::Base
attr_accessor :remember_token, :activation_token, :reset_token
has_many :roles, dependent: :destroy
has_many :agendas, through: :roles
before_save :downcase_email
before_create :create_activation_digest
before_save { self.email = email.downcase }
validates :first_name, presence: true, length: { maximum: 50 }
validates :last_name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, presence: true, length: { minimum: 6 }, allow_nil: true
end
Again, this is just one way to do things, but it's very common amongst Rails applications.

Rails 4 active record validation - Conditionally validate interdependent presence of 4 attributes

I have a form with 10 attributes.
Among them I have 4 attributes which I need to apply what I'd call a"mutually conditional presence" Active Record validation.
these attributes are
address_line_1
zipcode
state
country
It means that if the user fills ONE of them then ALL the others have to be present
So far I have only be able to say that if the user fills the first attribute "address line 1" then all the others must be present.
But it does not validate that all the MUTUAL presences in all possible combinations. For example if the user lets 'address line 1' empty but fills zipcode and leaves the other three empty, I want active recoird not to validate the form as he then should have been asked to fill the other three attributes. And so on with each of the attibutes.
How to do this?
Here is my current code
spec/models/users
validates :address_line_1,
presence: true,
length: { maximum: 100,
minimum: 3 }
validates :zipcode,
presence: true, if: :address_line_1?,
length: { maximum: 20,
minimum: 4}
validates :state,
presence: true, if: :address_line_1?,
validates :country,
presence: true, :address_line_1?,
length: { maximum: 50}
Just replace :address_line?condition with a check for one of the filled out fields:
validates :address_line_1,
presence: true, if: :address_entered?,
length: { maximum: 100,
minimum: 3 }
validates :zipcode,
presence: true, if: :address_entered?,
length: { maximum: 20,
minimum: 4
validates :state,
presence: true, if: :address_entered?,
validates :country,
presence: true, if: :address_entered?,
length: { maximum: 50}
def address_entered?
address_line_1.present? || zipcode.present? || state.present? || country.present?
end

Issues with validation in rails

I have a working validation on my user model. But since we're discovered that users tend to give up during their long registration form, we've split up registration form into steps so that user can give up any time and still use the site.
I'm having issues with the first step of user registration with validations. Here is the relevant bit of my User model :
with_options :if => lambda { |u| u.current_step == "get_started" } do |user|
user.validates :firstname, presence: true, length: { maximum: 50 }
user.validates :surname, presence: true, length: { maximum: 50 }
user.validates :email, presence: true,
format: { with: VALID_EMAIL_REGEX }
user.validates :password_digest, presence: true
user.validates :password, length: { minimum: 6 }
end
This validation works perfectly. However we now added facebook so its possible to login with facebook and we have hidden fields in our form facebook_uid. So I want to validate password only if these fields are nil.
Here is how I tried to modify my current validation :
with_options :if => lambda { |u| u.current_step == "get_started" } do |user|
user.validates :firstname, presence: true, length: { maximum: 50 }
user.validates :surname, presence: true, length: { maximum: 50 }
user.validates :email, presence: true,
format: { with: VALID_EMAIL_REGEX }
with_options :if => lambda { |u| u.facebook_uid.nil? } do |user|
user.validates :password_digest, presence: true
end
with_options :if => lambda { |u| u.user.password_digest_changed? && !u.password.nil? } do |user|
user.validates :password, length: { minimum: 6 }
end
end
Or inline (the relevant password part only) :
user.validates :password_digest, presence: true, if: lambda { |u| u.facebook_uid.nil? }
user.validates :password, length: { minimum: 6 }, if: lambda { |u| u.user.password_digest_changed? && !u.password.nil? }
None of these worked for me, whatever I tried I get this error :
undefined method `user' for #<User:0x00000008e924a8>
Again if I remove ifs and lambdas works as charm. Is there another way of accomplishing this or something I'm currently doing wrong with my code?
In your password validation lambda, you're calling
u.user.password_digest_changed? && !u.password.nil?
ie, you're sending a user method to the u object, which is your User instance. That object doesn't respond to user. You probably just want
u.password_digest_changed? && !u.password.nil?

How do i forbid a character in rails

i would like to forbid "/" from a field.
I read in the doc that it should be something like that:
valid_name_regex = /
validates :name, presence: true,
uniqueness: { case_sensitive: true }, format: { with: valid_name_regex }
But i'd like the opposite.
thanks
Try something like
validates :name, presence: true, uniqueness: { case_sensitive: true }, format: { with: /^[^\/]+$/ }

Resources