deny specific number(0) on rails 3 numeric validation - ruby-on-rails-3

I can't figure out how to deny only 0 from my validation. jQuery is not an option and :other_than doesn't exist in rails 3.0
validates_numericality_of :quantity,:only_integer=>true, :message=>"message"
tryed
:greater_than=>0, :less_than=>0
denies both negative and positive values, instead of allowing both;
:if=> Proc.new{|sc| sc.quantity!=0}
behave if this line doesn't exist(maybe syntax error that i can't identify)
:other_than=>0
doesn't exist in Rails v3.0
:if=> :test
def test
!(:quantity==0)
end
same as the other :if statement
i'm trying to block the "save" of the form if the input=0

validates :quantity, numericality: { only_integer: true }, exclusion: [0]

Related

Extra validations on url before an object is created/saved to prevent SQL injection?

Hopefully this isn't an invalid question, but could someone please explain to me what happens when rails creates and saves an object to the database or updates one? I've put several validations in place, but I'm not sure if I've missed something as there doesn't seem to be too much information on how rails secures its models under the hood.
In this code the user is supplying some data(supposed to be a url), I check with a REGEX to see if it is a url. I'm wondering if I need to do any additional SQL protection techniques for something as complicated as a url?
class ListLink < ActiveRecord::Base
belongs_to :list
default_scope -> {order('created_at DESC')}
#the REGEX urls are matched against
VALID_URL_REGEX = /\A(http:\/\/|https:\/\/|www|)[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?\z/i
validates :link_url, presence: true,
format:{with: VALID_URL_REGEX, message: "Please enter a valid url."}
validates :list_id, presence: true
#if is a valid url, ping embedly for more information on it
before_save :embedly #:set_link_info
#not sure what checks rails does on attributes created after validation
#any suggestions on how I can make these safer would be appreciated!
before_create :title, presence: true, length:{minimum: 4, maximum: 200}
before_create :image_url, presence: true
private
def embedly
embedly_api = Embedly::API.new :key => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
:user_agent => 'Mozilla/5.0 (compatible; mytestapp/1.0; my#email.com)'
url = link_url.dup
obj = embedly_api.extract :url => url
#extract and save a title and image element to the database
#are these validated by Rails too?
self.title = obj[0].title
self.image_url = obj[0]["images"][0]["url"]
end
end
Thanks for any help!
No extra care required; validates is enough.
Using ActiveRecord you can be sure the input data is properly escaped.
User.last.update_attributes(first_name: 'DROP TABLE users;')
# => true
User.last.first_name
# => "DROP TABLE users;"
You seems to misunderstand the purpose of before_create. It is a callback that's executed right before the record is added into the database. Its purpose is not to validate the object, but to execute custom code, as in the case with :embedly. You want to change before_create to validates here. The latter is called every time before the object is saved on both create and update actions. If you have
validates :title, presence: true, length:{minimum: 4, maximum: 200}
and your object has a too short title, ActiveRecord won't allow you to save it.
As addition to #shock_one answer:
ActiveRecord will call ActiveRecord::Base.connection.connection.quoute on every property, which will properly escape the values against SQL Injections. Same happens if you use hash queries or question mark placeholders in you queries.
e.g
User.where(name: params[:name])
User.where("name=?", params[:name]).
However if you write your own concatenated sql queries you have to use qoute on user input
c = ActiveRecord::Base.connection
User.where("name=#{c.quote params[:name]}")

Where can I find the cause of this error message? (rails 3.2.8 nested form)

My New Contract Form use to work ... it still needs some refinement ... but the current version use to work, but now I am getting this message:
3 errors prohibited this codeline from being saved:
There were problems with the following fields:
Contract can't be blank
Client can't be blank
Code can't be blank
I do not have any fields named Contract, Client, or Code ... those are my models.
Here is the params which I raised in the codelines_controller:
{"contract_attributes"=>{"authnum"=>"900700", "st_date"=>"2012-09-03",
"end_date"=>"2012-12-31"}, "client_attributes"=>{"f_name"=>"Esme", "mi"=>"J",
"l_name"=>"Inneed", "birth_date"=>"1986-03-18", "address1"=>"62 Southy View",
"address2"=>"", "city"=>"Fromm", "zip_code"=>"55803", "state"=>"WI",
"medicare_num"=>"3008769788", "medicaid_num"=>"765894567", "member_num"=>"6709875-3",
"soc_sec_care_mgr"=>"Caring Manager", "sscm_ph"=>"1-444-444-4444",
"nurse_care_mgr"=>"Caring Nurse", "ncm_ph"=>"1-555-555-5555", "emer_contact"=>"Always
Here", "ec_ph"=>"1-666-666-6666", "pri_care_phy"=>"The One",
"pcp_ph"=>"1-777-777-7777"}, "code_attributes"=>{"code_name"=>"S-5463",
"status"=>"Active", "description"=>"Transition from schl to work"},
"units_alloc"=>"100.00"}
as you can see all of the fields that need data have data and are not 'blank'
I did contract out to see if I could get a professional to help me design a button to add extra attributes to the form, but I had to cancel the contract because they were not communicating. So part of this process required that I make them collaborators to github and heroku. Maybe they had to change something to work on the project?
Can someone give me some guidance on how to resolve this issue?
Thanks.
look in app/models/theModelThatIsUsed.rb and if you find something like:
validates :contract, :presence => true
validates :client, :presence => true
validates :code, :presence => true
delete that lines

Ruby on Rails: How to customize validation error message?

I have a following code:
validates :name, :presence => true
Error message produced is "Name can't be blank"
Instead of using the actual attribute name (in this case "name") I want to
display message as "Registration name can't be blank".
How do I overwrite the default message on the validations? I tried appending :message
but it didn't work...
Thanks!
In en.yml file define custom keys as:
activerecord:
attributes:
model_name:
attribute_name1: key1
attribute_name2: key2
......
This key will be used automatically when errors are generated.
Reference: http://edgeguides.rubyonrails.org/i18n.html#translations-for-active-record-models
(5.1 Translations for Active Record Models)
This will do the trick:
validates :name, presence: { message: "Registration name can't be blank" }
or the old hash rocket syntax version:
validates :name, :presence => { :message => "Registration name can't be blank" }
Its a little late now (after about 35 days) to answer this. So, sorry for this. But just wanted to share that I had used a gem, more than a few months back, for custom error messages.
This plugin allows you to omit the attribute name for specific messages. All you have to do is begin the message with a ‘^’ character.
I just checked it at
https://github.com/nwise/custom_error_message
& it has not been updated since march. So, i probably used it at the right time.
ps : Your answer for defining the custom keys in the yml file is more appropriate though.

Writing custom validator in Rails 3

I'm trying to write a custom validator that will check for the number of words entered into a text field.
I was trying to follow the example in railscasts episode 211 - http://railscasts.com/episodes/211-validations-in-rails-3
So I made a file /lib/word_limit_validator.rb and copied in the same code from the tutorial. I know that this code doesn't count the number of words, I am just trying to use it because I know how it is supposed to behave.
class WordLimitValidator < ActiveModel::EachValidator
def validate_each(object, attribute, value)
unless value =~ /^([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
object.errors[attribute] << (options[:message] || "is not formatted properly")
end
end
end
Here's the line I used in my validation:
validates :body, :presence => true,
:word_limit => true
When I tried to load the form I got the following error:
Unknown validator: 'word_limit'
How do I get rails to recognize my validator?
System spec:
Mac OS 10.6.7
Rails 3.0.4
ruby 1.9.2p136
You could also create an app/validators directory in your rails project and put your custom validators there. This way they will automatically be loaded.
Files in lib/ aren't autoloaded anymore in Rails. So, you have a few options.
You can add lib to your autoload paths in your application.rb:
config.autoload_paths += %W( #{config.root}/lib )
You can include by adding file with something like this to config/initializers:
require File.join( Rails.root, 'lib', 'word_limit_validator')
If you only need it one place, you can just put it in the same file as your model.

Rails 3. Validating email uniqueness and case sensitive fails

I am developing an app in Rails 3 and upon signup I need the user to enter their email address and I need it to be unique and case sensitive. I.e. no one should be able to sign up with myEmail#yahoo.com when MyEmail#yahoo.com already exists in the database.
This is my code and it crashes the app:
validates :email, :presence => true, :uniqueness => true, :case_sensitive => true,
:format => {:with => /^([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})$/i}
What is wrong with it?
Please dont use case sensitive there!!!. It will fetch all the users! So if you have 100.000 users. first it will fetch them all with LOWER(email). This can be VERY slow and it wont use your index on email.
Here an article that i found just now about this topic: http://techblog.floorplanner.com/post/20528527222/case-insensitive-validates-uniqueness-of-slowness
My suggesting is: Run a query to make all the emails downcased and make a before validation filter to downcase the email attribute so you dont have any uppercased characters in that column.
User.update_all('email = LOWER(email)')
before filter:
before_validation :downcase_email
private
def downcase_email
self.email = email.downcase if email.present?
end
For the Rails 3 type of validation you need to nest the casse insensitive block like so
validates :email, :uniqueness => { :case_sensitive => false }
I don't have the reputation to comment on the accepted answer, but #medBo asked about how this behaves in Rails 4. For reference, when using Rails 4.2 + MySQL, if I specify
validates :username, uniqueness: { case_sensitive: true }
ActiveRecord performs this query:
SELECT 1 AS one FROM `users` WHERE `users`.`username` = 'TEST_USER' LIMIT 1
In this case the search is not case sensitive. But when I set:
validates :username, uniqueness: { case_sensitive: false }
it performs:
SELECT 1 AS one FROM `users` WHERE `users`.`username` = BINARY 'TEST_USER'
The BINARY operator ensures the search is case sensitive without fetching all users, meaning for my setup at least, the case_sensitive flag doesn't suffer from the performance issue that #Michael Koper notes for earlier versions of Rails. I can't comment on how ActiveRecord performs for other database setups.
I'm not sure if it is possible to do case insensitive validations using that syntax (at least, I haven't found any documentation for it).
You should be able to validate case insensitive uniqueness like this though:
validates_uniqueness_of :email, :case_sensitive => false
Without more detail on the crash you get, I can't help more than that.
You can use a callback in your model like "before_validation" on email attribute to make it lowercased like this:
before_validation { self.email = email.downcase }
This will make the email input lowercased, after that try uniqueness validation without case sensitive:
validates :email, uniqueness: true
For more info about callbacks: here is ruby guide
https://guides.rubyonrails.org/active_record_callbacks.html