Rails: truncate text input instead of whining it's too big - ruby-on-rails

I have a Rails 6.0.21 application which, like any normal application, accepts input from users.
Sometimes users type in by mistake or intentionally very long strings where not really supposed to, eg a random 9348913 character string in an input meant for email addresses which saves in a varchar(255) column.
When this happens Rails errors out:
Mysql2::Error: Data too long for column 'email'
I'm looking for a way for the framework to just truncate the data rather than whining it's too big and doesn't fit in.
I can't just truncate before_commit because some models have a lot of fields, I'd end up writing a few thousand lines of code to do this very simple thing.
Anyone know how to do it "automagically"?

You can validate the length of the attribute in your model
class User
validates :email, length: { maximum: 255 }
#validates_lenght_of :email, :maximum => 255 #rails3
end
In your view, limits the amount they can enter with the maximum length attribute:
<input maxlength="255".... >....
And if you have many fields build an array with all the attributes of type string, and if you want to customize the message you can also:
class User
ATTR_TO_VALIDATE = Todo.attribute_names.reject{|attr| Todo.columns_hash[attr].type != :string}
validates ATTR_TO_VALIDATE, length: { maximum: 255,
too_long: "%{count} characters is the maximum allowed" }
end

Related

Cannot iterate over unique elements

I have an array of errors as below:
n.errors.full_messages
# => ["Password can't be blank", "Password can't be blank", "Password is too short (minimum is 3 characters)"]
I would like to iterate over the unique elements of this array and display them on the screen.
Validation model
class Member < ActiveRecord::Base
has_one :profile
before_save { self.username = username.downcase }
has_secure_password
validates :password, presence: true, length: { minimum: 3 }
end
n.errors.full_messages.uniq do |a|
puts a
end
uniq is not working, and "Password can't be blank" appears twice in my array. Any ideas?
Password can't be blank
Password can't be blank
Password is too short (minimum is 3 characters)
# => ["Password can't be blank"]
Edit: This doesn't actually answer the question, use the answer from #BroiSatse if google brought you here.
The reason you are getting that message twice is because of has_secure_password:
http://api.rubyonrails.org/classes/ActiveModel/SecurePassword/ClassMethods.html#method-i-has_secure_password
The first bullet point appears to add validation that makes the password required.
In your model you also add
validates :password, presence: true, length: { minimum: 3 }
The presence: true part of this adds the same validation. Remove this so its:
validates :password, length: { minimum: 3 }
This should fix the problem.
uniqe with a block uses value of the block to compare the elements. What you want is:
n.errors.full_messages.uniq.each do |m|
Anyhow, I think you're approaching the problem from the wrong angle - your problem is not how to avoid displaying duplicate messages, but how this duplication happened.
You could just do a string comparison.
Have the array that is problematic to you. Go over it and save the elements one by one to a new array.
Now when the first one is added to the new array, check that the elements allready in the array don't match the new element to be added. E.g: "My string".eql? "My sting"
There might be of course a more clever way to do this in Ruby. But that would be the idea when doing it in other languages manually.

Rails model validation fails on integer big number input ("out of range ")

I have Integer attribute in my model and I need back-end validation for that (it should be up to 7 digts only).
In my model I do some validations like:
validates :duration, format: { with: /([0-9]{1,7})/ }
validates :duration, numericality: { less_than_or_equal_to: 9999999 }
This works when I try to put letters into the form (it returns 'is not a number' error), works well when I put valid integer (11045555 - returns 'must be less than or equal to 9999999') BUT it crashes when I put really big number - let's say 11045555766666666666. Error is "11045555766666666666 is out of range for ActiveRecord::Type::Integer with limit 4"
How can I skip this crash when user puts that big number?
I use mysql2 DB.
You have to declare the limit on your migration file. By default, an integer is coded in 4 bytes, so the limit is 2147483647.
If you want to set a bigger limit, declare it like this
add_column :yourtable, :duration, :integer, :limit => 8
8 bytes have a 9223372036854775807 limit.
Just check How to specify the size of an integer in the migration script

Multilingual support for custom validation messages in Rails

Hi let's say I have the following in my accounts model:
validates :name, length: {in: 1..70, message:%Q|Please enter a decent name Sr.|}
How can I add multilingual support to those custom validation messages? I checked this tutorial
But I could not find out how to translate custom validation messages in the model.
I needed once to use translations in model so I went this way:
TITLE = { 0 => :"employee.title.mrs",
1 => :"employee.title.mr",
2 => :"employee.title.miss" }
these are options for select, and in select I used t(value_of_key_here), value was a string that was seen as a key to locale.
So in your case this might work (not really sure):
validates :name, length: {in: 1..70, message: :"enter_decent_name"}
that would return a key in your validation messages and rails will just complain about missing key in translations that you have to add into your yml file:
enter_decent_name: 'Please enter a decent name Sr.'

Use Ruby ActiveRecord Validates_Numericality to accept 20.00 as integer

We are working with web development firm to build a site. We have a field where we request that the user input the amount that they would like to invest. We asked for this field to be limited to whole numbers. For example, the user should be able to invest "20" or "20.00" but not "20.50".
The developer is using Ruby ActiveRecord Validate_numericality :only_integer which is restricting the input to "20". If a user inputs and submits the value "20.00" they receive an error telling them that they need to input an integer.
Is there a way to use ActiveRecrod validate_numericality to accept only numbers that are whole numbers, not necessarily only integers? The code is currently:
validates :principal, numericality: {greater_than_or_equal_to:MINIMUM_INVESTMENT_AMOUNT,
less_than_or_equal_to:MAXIMUM_INVESTMENT_AMOUNT,
:only_integer => true}
I am hoping that there is a numericality constraint that will allow 20.00 as a whole number.
you could do this
before_validation {|a| a.principal = principal.to_i}
This will convert it to an integer without modifying the validations but if you want to notify the user that they entered something that is not a whole number then I would remove the :only_integer and create a more flexible validation like
validates :principal, numericality:{greater_than_or_equal_to:MINIMUM_INVESTMENT_AMOUNT, less_than_or_equal_to:MAXIMUM_INVESTMENT_AMOUNT}
validate :principal_is_whole_number
def principal_is_whole_number
errors.add(:principal, "must be a whole number.") unless principal.to_i == principal
end

Rails - validate 25 lines in a text box

I want to use the validates method on one of my text fields in a model so that the end user must enter at least 25 lines (separated with an enter key). So for now i validate the presence of the input so it won't be blank:
validates :lines, :presence => true
This must use some regex to check for maybe the presence of at least 24 '\n' ?
How can i accomplish that in my model?
EDIT: values need to be utf8
Maybe you have to do it with validate method:
validate do
errors.add(:lines, "must be at least 25 lines") if lines.lines.to_a.size < 25
end
If you really need to do it with regexp, try something like
/([^\n]*\n[^\n]*){24,}/
but it counts empty lines as well.

Resources