skipping a specific validation when using valid? in ActiveRecord - ruby-on-rails

In my Post model, I have a couple of validations for attribute link
validates :link, url: true, uniqueness: true
Now, in my controller, I would like to call:
#post = Post.new(link: "google.com")
#post.valid?
I want to check if the link is in correct format, but to skip uniqueness test. How should I do that?

You can set an :if => :method_name argument on validations which will cause that validation to only run if the condition in the method is true. Put whatever your condition is in that method.
Example:
validates :link, :uniqueness => true, :if => :validate_link_uniqueness? #Will only run if validate_link_uniqueness? returns true
validates :link, :url => true # Will always run
def validate_link_uniqueness?
!new_record? # Insert the conditions that return true if uniqueness should be validated
end

You can check if there is an error for that field:
#post.errors[:link].blank?

Related

How can I use Rails newer `validates :column, presence: value` syntax inside of a `validate` block?

I have the following code in my Applicant model.
validate do |applicant|
validates_presence_of :name
end
This works, but Rubocop complains:
Rails/Validation: Prefer the new style validations validates :column, presence: value over validates_presence_of.
However, when I change things to:
validate do |applicant|
validates :name, presence: true
end
Rails falls over and throws the following error:
undefined method validates for #<Applicant:0x00007ff17f7d7a58> Did you mean? validate validate! valid_date? _validators
How can I use the newer validates :column, presence: value syntax inside of my validate block?
Edit:
I'm using a validate block, as I want to pass params to a custom validation method, like so:
validate do |applicant|
validates :name, presence: true
applicant.validate_stuff(param1, param2)
end
def validate_stuff(param1, param2)
# return something
end
Am I missing a better way to do that?

allow validations only when resource added from activeadmin rails

I have a form in active admin for user. I have added a validation 'presence' for the below attribute,
validates :needy_id, presence: true
I want it to work only when the request comes from activeadmin.
Any suggestions?
Please check this,
validates :needy_id, :presence => true, :if => Proc.new { user.admin? }

validate email in rails after updating

In my user model, I have
validates :email, :presence=>true,
:format => { :with => email_regex },
:uniqueness => true
In my controller, I update the email if a user chooses to change it like this:
#user.update_attribute("email","#{#new_email}")
However, it doesn't throw an error if the format is not honored.
update_attribute does no validations. use
#user.update_attributes({ :email => #new_email })
instead.
I found out that update_attribute skips checking for validation but update_attributes doesn't! Interesting.
http://apidock.com/rails/ActiveRecord/Base/update_attributes

How to validate a single attribute for a submitting ActiveRecord instead of all its attributes?

I am using Ruby on Rails 3 and I would like to validate a single attribute for a submitting ActiveRecord instead of all its attributes.
For example, in my model I have:
validates :firstname, :presence => true, ...
validates :lastname, :presence => true, ...
I would like to run validation on the :firstname and on the :lastname separately. Is it possible? If so, how can I make that?
P.S.: I know that for validation purposes there are methods like "validates_presence_of", "validates_confirmation_of", ..., but I would like to use only the above code.
You can setup a virtual attribute on your model, and then do conditional validation depending on that attribute.
You can find a screencast about this at http://railscasts.com/episodes/41-conditional-validations
class Model < ActiveRecord::Base
def save(*attrs)
Model.validates :firstname, :presence => true if attrs.empty? || attrs.include?( :firstname )
Model.validates :lastname, :presence => true if attrs.empty? || attrs.include?( :lastname )
...
super
end
end
m = Model.new
m.save
#=> false
m.save(nil) # same as save(false), you can use both of them
#=> true
m = Model.new :firstname => "Putty"
m.save
#=> false
m.save(:firstname, :lastname)
#=> false
m.save(:firstname)
#=> true
You can just delete the second line of your code above so it reads:
validates :firstname, :presence => true
No validation will then be performed on the :lastname.
Regards
Robin

Validates acceptance always failing

I can't see what I'm missing, but something is obviously not right.
In model:
validates :terms, :acceptance => true, :on => :update
Trying a few options:
>> a = Factory(:blog_agreement)
=> #<BlogAgreement id: 54, terms: false, created_at: "2011-01-20 11:33:03", updated_at: "2011-01-20 11:33:03", accept_code: "fa27698206bb15a6fba41857f12841c363c0e291", user_id: 874>
>> a.terms
=> false
>> a.terms = true
=> true
>> a.save
=> false
>> a.terms = "1"
=> "1"
>> a.save
=> false
>> a.terms = 1
=> 1
>> a.save
=> false
>> a.errors.full_messages
=> ["Terms must be accepted"]
Updated answer..
So it turns out that the problem was having terms as an actual column in the table. In general validates_acceptance_of is used without such a column, in which case it defines an attribute accessor and uses that for its validation.
In order for validates_acceptance_of to work when it maps to a real table column it is necessary to pass the :accept option, like:
validates :terms, :acceptance => {:accept => true}
The reason for this has to do with typecasting in Active Record. When the named attribute actually exists, AR performs typecasting based on the database column type. In most cases the acceptance column will be defined as a boolean and so model_object.terms will return true or false.
When there's no such column attr_accessor :terms simply returns the value passed in to the model object from the params hash which will normally be "1" from a checkbox field.
In the case of someone has the same problem like me with devise, i add this answer:
i added to the devise's registration form:
sign_up.html.erb
<%= f.check_box :terms_of_service %>
user.rb
validates, :terms_of_service, acceptance: true
i forgot to add :terms_of_service inside my configured_permitted_parameters and devise ignored the checkbox state.
application_controller.rb
before_filter :configure_permitted_parameters, if: :devise_controller?
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:email, :password, :password_confirmation, :terms_of_service)}
end
The configure_permitted_parameters method is used by devise for know what params he should be save in addition of email and password.
I had to use this format:
validates :accpeted_terms, :acceptance => {:accept => true}
validates_acceptance_of :terms, :accept => true
I found Candland's answer above for validates acceptance to be correct in Rails 3.1. This is how I set up my Rails 3.1.3 app to record the acceptance to the database.
In the migration,
class AddTermsToAccount < ActiveRecord::Migration
def change
add_column :accounts, :terms_of_service, :boolean, :default => false
end
end
In the model,
attr_accessible :terms_of_service
validates :terms_of_service, :acceptance => {:accept => true}
In the form,
<%= f.check_box :terms_of_service %>
<%= f.label :terms_of_service %>
I have tried this from Angular JS and Rails 4. Angular send parameter with true value but rails did not recognize true.
It can receive an :accept option, which determines the value that will
be considered acceptance. It defaults to "1" and can be easily
changed.
So, I change into this:
class Person < ActiveRecord::Base
validates :terms_of_service, acceptance: { accept: true }
end
If you have default parameter is 1 or 0. Try to do this:
class Person < ActiveRecord::Base
validates :terms_of_service, acceptance: true
end
This is for more documentation. acceptance validation.
I hope this help you.
A call to a factory creates the record, so your subsequent calls to save are in fact updates, so your validation fails as intended. Try it without the factory and it should work.
if you have a basic checkbox in your view, such as
<%= builder.check_box :agreement %>
just put this line in your model
validates :agreement, :acceptance => true
which uses the default "1" generated by the check_box view helper

Resources