Customize Ruby on rails validation errors - ruby

Hi I'm trying to customize some rails form errors. All of which work fine except for the middle one regarding lead_reason_id etc i;m guessing this is because there are no custom validators?
validates :email, presence: true, format: { with: Validators::Base::EMAIL, message: 'Este campo tiene que ser positivo' }
validates :lead_reason_id, :lead_source_id, presence: true, format: { message: 'Este campo tiene que ser positivo' }
validates :amount, presence: true, numericality: { only_integer: true, greater_than: 0, message: 'Este campo tiene que ser positivo' }
The error I'm getting is

Not sure if validating several fields with a single validates call is allowed. Also, for your format hash you need to specify :with option, which is missing. If you just want to validate presence, then format hash is not necessary:
validates :lead_reason_id, presence: { message: 'Este campo tiene que ser positivo' }
validates :lead_source_id, presence: { message: 'Este campo tiene que ser positivo' }
See more at: https://guides.rubyonrails.org/active_record_validations.html#format

Related

Can't Use Validates Presence On Picture Rails 5.x

micropost.rb
class Micropost < ActiveRecord::Base
belongs_to :user
default_scope -> { order(created_at: :desc) }
mount_uploader :picture, PictureUploader
validates :user_id, presence: true
validates :tag1, presence: true, length: { maximum: 20 }
validates :tag2, presence: true, length: { maximum: 20 }
validates :tag3, presence: true, length: { maximum: 20 }
validates :picture, presence: true
validate :picture_size
validates :ispublic, inclusion: { in: [ true, false ] }
private
# Validates the size of an uploaded picture.
def picture_size
if picture.size > 5.megabytes
errors.add(:picture, "should be less than 5MB in size.")
end
end
end
microposts_controller.rb snippet:
def create
#micropost = current_user.microposts.build(micropost_params)
if #micropost.save!
flash[:success] = "Post created!"
redirect_to root_url
else
#feed_items = []
render 'static_pages/home'
end
end
def micropost_params
params.require(:micropost).permit(:tag1, :tag2, :tag3, :picture, :ispublic)
end
Test that is failing snippet:
tag1 = "This"
tag2 = "Is"
tag3 = "Sparta"
image = File.open("test/fixtures/p_avatar.png")
assert_difference 'Micropost.count', 1 do
post microposts_path, params: {micropost: { tag1: tag1, tag2: tag2, tag3: tag3, picture: "image",
ispublic: false }}
end
Test error:
Validation failed. Picture can't be blank.
I am using CarrierWave...based on other answers I was wondering if I can't use the presence: true validation with a picture, but I thought the #micropost.save would just store whatever as a string (varchar). For testing purposes, I just want to make sure a valid string is passed, but maybe that isn't even necessary if CarrierWave and picture_size validation is enough.
Found it. In the Rails spec, there is a function called fixture_file_upload() which does all the heavy lifting of creating the image object for me (some sort of upload to a cache it seems) and making the Model.save() method validate it and store the string in the db.
Thanks to this site it informed me a bit on image upload testing without going through FactoryBot: https://jeffkreeftmeijer.com/carrierwave-rails-test-fixtures/
Ultimately I decided I micropost doesn't require a picture (A la Twitter).

Rails: Uninitialized constant User::VALID_EMAIL_REGEX

Background - I am working with rails version 5.1.2. I am using Cloud 9 IDE. My problem relates to Ch 11 Rails Tutorial by Michael Hartl.
Problem details - typing $ rails test:mailers:
Error:
UserMailerTest#test_account_activation:
NameError: uninitialized constant User::VALID_EMAIL_REGEX
app/models/user.rb:6:in <class:User>'
app/models/user.rb:1:in'
bin/rails test test/mailers/user_mailer_test.rb:5
app/models/user.rb:1 - app/models/user.rb:6:
class User < ApplicationRecord
attr_accessor :remember_token, :activation_token
before_save :downcase_email
before_create :create_activation_digest
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
Looks like you are missing the regex in your User model
class User < ApplicationsRecord
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
...
end
Just to add to Antarr Byrd's answer.
I had a similar experience when working on a Rails Application.
The issue was that I was defining the REGEX constant below the point of validation call.
That is, instead of this:
class User < ApplicationRecord
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
end
Do this rather:
class User < ApplicationRecord
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX }
end
That's all.
I hope this helps

Uniqueness validation for polymorphic model fails

So I have this really weird problem. Here is my model:
class Clip < ApplicationRecord
belongs_to :owner, polymorphic: true
default_scope -> { order(created_at: :desc) }
validates :address, presence: true, uniqueness: { scope: [:owner_type, :owner_id] }
before_save { self.adress=adress.split("=").last }
validates :owner, presence: true
end
and the test
test "invalid creations" do
get new_clip_path
assert_no_difference "Clip.count" do
post clips_path, params: { clip: { address: "",
description: "bum bum bum" } }
end
assert_template "clips/new"
assert_match "blank", response.body
assert_no_difference "Clip.count" do
#clip allready in db, should refure
post clips_path, params: { clip: { address: "fWNaR-rxAic",
description: "bum bum bum" } }
end
assert_template "clips/new"
assert_no_match "blank", response.body
assert_match "Address has already been taken", response.body
end
The test is passing without a problem but I just realized by accident, that I can still create clips with the same address and owner, as often as I want to. This confuses me for two reasons: a) what is wrong with this line validates :address, presence: true, uniqueness: { scope: [:owner_type, :owner_id] } and b) why does the test not fail?

Rails 4+: where to store custom validation msgs used across models

I have custom validation messages that I use in several different models:
# models/user.rb
class Person < ActiveRecord::Base
validates :name, presence: { message: "This is a required question" }
end
# models/pet.rb
class Pet < ActiveRecord::Base
validates :name, presence: { message: "This is a required question" }
end
I'm a little familiar with the en.yml config, but that specifies messages per model:
en:
activerecord:
errors:
models:
person:
attributes:
name:
blank: "This is a required question"
pet:
attributes:
name:
blank: "This is a required question"
And that just seems very verbose and not developer-friendly.
My solution was to create an initializer file and store my custom validation messages in a hash there:
# config/initializers/custom_validation_messages.rb
CUSTOM_VALIDATION_MESSAGES = {
required: "This is a required question"
}
And then to use them as:
validates :name, presence: { message: CUSTOM_VALIDATION_MESSAGES[:required] }
My solution works, but I'm not sure if this is a correct usage of an initializer. Is there a more appropriate Rails convention for cleaning up those duplicate validation messages?
I prefer the following approach, so I could also use the translations on other places within my app (like a hint message for instance):
class Pet < ActiveRecord::Base
validates :name, presence: { message: I18n.t('common_errors.required_question' }
end
and
en:
common_errors:
required_question: "This is a required question"

Validation doesn't work in "sexy" style

It seems that Rails doens't let me pass in more than one parameter when using this validation syntax. It always has a syntax method for an unexpected comma after the first argument.
class Apartment < ActiveRecord::Base
geocoded_by :location
after_validation :geocode
has_many :image_attachments
validates_associated :image_attachments
accepts_nested_attributes_for :image_attachments
validates :location, presence: true
validates :description, presence: true
validates :price, :presence => true
,:format => { with: /^[0-9]+$/, message: 'must be a number' }
validates :longitude, presence: true
end
It's bad formatting (and very "unsexy") to have the comma at the beginning of the next line.
Better to do...
validates :price, :presence => true,
:format => { with: /^[0-9]+$/, message: 'must be a number' }
...which should work fine.
A more consistent style is to use the Ruby 1.9 convention for key/value when key is a symbol.
validates :price, presence: true,
format: { with: /^[0-9]+$/, message: 'must be a number' }

Resources