Based on rails validation docs. I need to validate fullname field only on update
# encoding: utf-8
class User < ActiveRecord::Base
GENDER_MALE = true
GENDER_FEMALE = false
attr_accessor :password_confirm,
:term,
:year, :month, :day,
:captcha
validates :username, presence: {message: "Bạn phải nhập tài khoản"},
uniqueness: {message: 'Tài khoản đã tồn tại'}, :on => :update
# validates :password, presence: {message: "Bạn phải nhập mật khẩu"},
# confirmation: {message: 'Mật khẩu không chính xác'}
# validates :password_confirmation, presence: {message: "Bạn phải nhập xác nhận mật khẩu"}
# validates :fullname, presence: {message: "Bạn phải nhập họ tên"}
# validates :email, presence: {message: "Bạn phải nhập email"},
# uniqueness: {message: "Email đã tồn tại"}
# validates :email, format: {with: /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i, message: "Email không đúng định dạng"},
# unless: "email.blank?"
# validates :term, acceptance: {message: "Bạn phải đồng ý điều khoản"}
# # validates :gender, acceptance: {accept: [0,1], message: "Giới tính không hợp lệ"}
# validate :_birthday_validator
# validate :_captcha_validator
#
# before_save :_encrypt_password
def signup
self.birthday = "#{year.to_s}-#{month.to_s}-#{day.to_s}"
self.save
end
def self.human_attribute_name(attr, option = {})
"" || super
end
protected
def _encrypt_password
self.password = Digest::MD5::hexdigest(password)
end
private
def _birthday_validator
unless year.present? && month.present? && day.present?
errors.add(:birthday, 'Bạn phải nhập ngày sinh')
else
errors.add(:birthday, 'Ngày sinh không hợp lệ') unless Date.valid_date?(year.to_i, month.to_i, day.to_i)
end
end
def _captcha_validator
if !(captcha.nil?)
errors.add(:captcha, "Mã xác nhận không hợp lệ") if captcha == false
end
end
end
As understand, this validation rule only run when I call update method, but I have no idea why this rule run all the time
Can anyone tell me why or I missed somethings?
Ps: Can Rails validates only for user defined method, somethings like
validates :username, presence: true, only: [:my_func]
One way would be to set a virtual attribute which you'll only populate in the signup method:
#app/models/user.rb
class User < ActiveRecord::Base
attr_accessor :should_validate
validates :fullname, presence: true, on: :update, if: "should_validate.present?"
end
This way, you can then assign a value to should_validate only when you use signup:
def signup
self.birthday = "#{year.to_s}-#{month.to_s}-#{day.to_s}"
self.should_validate = true
self.save
end
you can use method like
validate :fullname , on: :update
def fullname
if self.fullname.present?
true
else
false
end
end
Related
I'm getting the following error
Error Message Image
When trying to save a message object in my MessageController. Here is my controller.
class MessagesController < ApplicationController
def new
#message = Message.new
#user = current_user
end
def create
#message = Message.new(message_params)
#message.user = current_user
#message.user_id = current_user.id
if #message.user_email.nil?
#message.user_email = current_user.email
end
if #message.save
# UserMailer.send_email_to_admin(current_user.email).deliver
else
# redirect_to new_message_path(#message)
end
end
private
def message_params
params.require(:message).permit(:subject, :body, :user_email)
end
end
And here is my model.
class Message < ActiveRecord::Base
belongs_to :user
validates :user_email, presence: true
validates :subject, presence: true, length: { minimum: 5 }
validates :message, presence: true, length: { minimum: 10 }
end
I have no idea why this error is appearing because there are no methods named "message" in my app. Any help would be much appreciated!
In your model you have a validation for the message field:
validates :message, presence: true, length: {minimum: 10}
Is that supposed to be a validation for your body field?:
validates :body, presence: true, length: {minimum: 10}
Before saving the record, the validator is calling the message method on the Message instance(#message) to check its presence and validate it. Since you don't have a column named message but have a validation for it, you will get the NoMethodError.
I have a model with validates:
attr_accessor :name, :username, :email, :password
validates :name, :presence => { allow_blank: false, message: "Имя не может быть пустым" }
validates :username, :presence => { allow_blank: false, message: "Имя пользователя не может быть пустым" }
validates :email, :presence => { allow_blank: false, message: "Эл. адрес не может быть пустым" }
CREATE def:
def create
#user= User.new(user_params)
if #user.save
redirect_to "http://bookworm.az:3000"
else
session[:name] =#user.name
session[:username] =#user.username
session[:email] =#user.email
error =#user.errors.to_a.to_sentence(two_words_connector:',')
delimeter = error.split
error = error.gsub(delimeter[0], '')
show_error = error.split(",")
flash[:notice] = show_error[0]
redirect_to :back
end
end
When I delete ALL validates checking all it saves the user in the database. But with the validates LOG prints:
INSERT INTO "users" DEFAULT VALUES RETURNING "id"
What is the problem?
UPDATE
def user_params
params.require(:user).permit(:name, :username, :email, :password)
end
attr_accessor is overriding the rails attributes. Try removing it and it should work.
Read the answer for similar issue.
I have a record in postgresql of user status it is boolean and its attributes are "true" and "false". I want to show "true" as "active and "false" as "inactive". How do I do it with query or any thing to add in model.
Controller:
def index
#users = User.reorder("id ASC").page(params[:page]).per_page(10)
#count = 0
end
Model:
class User < ActiveRecord::Base
has_many :orders
has_many :order_statuses
attr_accessible :first_name, :last_name, :email, :password,
:password_confirmation, :code
validates :first_name, presence: true
validates :last_name, presence: true
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false }
validates :password, length: { minimum: 6}
has_secure_password
before_save { self.email = email.downcase }
before_create :create_remember_token
def User.new_remember_token
SecureRandom.urlsafe_base64
end
def User.encrypt(token)
Digest::SHA1.hexdigest(token.to_s)
end
private
def create_remember_token
self.remember_token = User.encrypt(User.new_remember_token)
end
end
Add this method in your model, and when you call #user.status, it will show 'Active' or "Inactive".
def status
self.status? ? "Active" : "Inactive"
end
Hope, It will help. Thanks
If I understand you correctly you want to display to your users "active" instead of true and "inactive" instead of false.
You could do something like this in all your views:
#user.status? ? 'active' : 'inactive'
Or if you need this in a bunch of places you could write a helper:
module UserHelper
def status_text(user)
#user.status? ? 'active' : 'inactive'
end
end
# and call it from your views like this:
<%= status_text(#user) %>
Or you could put that into a model method if you need this function only in conjunction with the user and it's active method (as per Rails Guy's suggestion)
Lastly you could use I18n to translate the string for you if you have a mulitlingual page:
# en.yml
en:
status:
true: 'active'
false: 'inactive'
# user_helper.rb
def status_text(user)
I18n.t("statys.#{user.status.to_s}")
end
I am a noobie and I am trying to simply get all the records in the database and display them in alphabetical order. Whenever I display the index page the records are always sorted in descending by their id. I used the console to try calling EvalTest.order("name") and again I kept getting the records sorted by their id in descending order instead of by name. Do I need to add an index on the name column to sort by it? This seems like the answer should be so easy but I can't seem to figure it out...
Here is my code:
User Model:
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation
has_secure_password
has_many :eval_tests
before_save { |user| user.email = email.downcase }
before_save :create_remember_token
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true,
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates :password, presence: true, length: { minimum: 6 }
validates :password_confirmation, presence: true
after_validation { self.errors.messages.delete(:password_digest) }
private
def create_remember_token
self.remember_token = SecureRandom.urlsafe_base64
end
end
Eval_Test Model:
class EvalTest < ActiveRecord::Base
attr_accessible :description, :name
belongs_to :user
validates :user_id, presence: true
validates :name, presence: true
validates :description, presence: true, length: { maximum: 350 }
default_scope order: 'eval_tests.created_at DESC'
end
EvalTest Controller:
class EvalTestsController < ApplicationController
def show
#eval_test = EvalTest.find(params[:id])
end
def new
#eval_test = EvalTest.new
end
def index
#eval_tests = EvalTest.order("name")
end
def create
#eval_test = current_user.eval_tests.build(params[:eval_test])
if #eval_test.save
flash[:success] = "Nouveau test cree!"
redirect_to #eval_test
else
render 'new'
end
end
end
Evaluation Test index.html.erb:
<% provide(:title, 'Index des tests') %>
<h1>Index des tests</h1>
<ul class="eval_tests">
<% #eval_tests.each do |eval_test| %>
<li>
<%= link_to eval_test.name, eval_test %>
</li>
<% end %>
</ul>
This is happening because you have used default scope in your model. Try
#eval_tests = EvalTest.reorder("name")
This should solve your issue.
Hello I trying to create a reset password for my rails app; but when I try to save I get the following error:
Validation failed: Password can't be blank, Password is too short
(minimum is 6 characters), Password confirmation can't be blank
This is my user model.
class User < ActiveRecord::Base
attr_accessible :email, :password, :password_confirmation
has_secure_password
before_save { |user| user.email = email.downcase }
before_save :create_remember_token
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false }
validates :password, presence: true, length: { minimum: 6 }
validates :password_confirmation, presence: true
def send_password_reset
self.password_reset_token = SecureRandom.urlsafe_base64
self.password_reset_at = Time.zone.now
self.password = self.password
self.password_confirmation = self.password
save!
end
private
def create_remember_token
self.remember_token = SecureRandom.urlsafe_base64
end
end
the method "send_password_reset" doesn't update the user and I don't understand why is trying to save the user instead on updating just password_reset_token and the password_reset_at.
Does anybody can help me, please?
When you call save! on the model instance, it's going to run the validations on your User model; all of them.
There are a number of ways to skip the password validations conditionally. One is to use a Proc
validates :password, presence: true, length: { minimum: 6 }, unless: Proc.new { |a| !a.new_record? && a.password.blank? }
This will allow the User instance to be saved and will skip the validation of the :password field if it's blank and the User is not new (already persisted to the database).
Here is most of a password validation I use in my applications
validates :password, confirmation: true,
length: {:within => 6..40},
format: {:with => /^(?=.*\d)(?=.*([a-z]|[A-Z]))([\x20-\x7E]){6,40}$/},
Notice, you don't need the separate validation on :password_confirmation. Instead just pass confirmation: true to the :password validator.
Suggested Reading:
http://guides.rubyonrails.org/active_record_validations_callbacks.html#confirmation