Ruby on Rails validation by pair of properties - ruby-on-rails

I need to do validation on my model on Ruby on Rails.
I have model with 2 fields:
user_id
some_item_id
And I have many rows in DB with the same user_id, but with different some_item_id. And I need avoid duplication of this some_item_id towards to specific user_id.
In Rails exist some 'magic' validation in one line for this?

validates : user_id, :presence => true, :uniqueness => { :scope => : some_item_id }

Related

How to do a simple regex validation in rails

How can perform a reguler expression to validate for either - or _ in the person username. i dont want to accept any other character like .#()$etc just - or _ so the person can either have a name like mike, mikel_mark or mike-mark. very simple. Thank you
example:
validate_format_of :username, with: "...."
The Rails 3 way to do validations is the following:
validates :username, :format => {:with => /\A[0-9a-z_]+\Z/i}
The form of validate_format_of is more Rails < 3 like and followed the "type of validation" concept, whereas the validates form is attribute based (you write all validations that apply to the attribute in one statement).
Check out the docs here: http://apidock.com/rails/v3.2.13/ActiveModel/Validations/ClassMethods/validates

Rails 3 validating multiple fields if unique field value exists

I have an Assignment model which has the following fields: :user_id, :company_id, :role_id
Each user can have multiple roles within a company but each company can only have one user with role_id == 5.
I would like to do something like below (obviously this does not work).
validates :company_id, :uniqueness => { :scope => :role_id => {:is => 5}, :message => "Only one owner is allowed." }
Is there a way to achieve this in a similar format to the above or will I need to create a custom validation macros?
If a custom validation is required how exactly would this be done and where is the 'correct' place to store this code if a new class needs to be created that inherits from ActiveModel::EachValidator? (Do I keep it in the same file or create a new file and possibly save it in /lib?)
Thanks in advance.
validates_uniqueness_of :user_id, :scope => :company_id, :if => Proc.new{|user| user.role_id == 5 }
Ok, I've come up with a solution but not quite sure if it's the 'rails way' of doing this or if it's just a hack-y workaround. Can someone please correct me on this?
I have done the following in my Association.rb file:
validate :owner_exists
.
..
...
protected
def owner_exists
errors.add(:role_id, " of owner already exists") if (role_id == 5 && Assignment.where('company_id = ? AND role_id = 5', company_id ).exists?)
end

Rails 3 Validation - Comparison with database values

I'm trying to use Rails validations for a form text box to see if the text entered matches any existing values in a specific column of a table in the database. Is this possible with Rails?
Basically, like this:
User enters 'Foobar'
Table column values: 'Foobar,test,house,random'
Validation does not pass because 'Foobar' is already in the database.
Thanks!
dwmcc
You can do this in your model with something like validates_uniqueness_of :name or new in Rails 3 you can do multiple validations inline with validates :name, :presence => true, :uniqueness => true
From the Rails API.

Rails: Validate unique combination of 3 columns

Hi I wan't to validate the unique combination of 3 columns in my table.
Let's say I have a table called cars with the values :brand, :model_name and :fuel_type.
What I then want is to validate if a record is unique based on the combination of those 3. An example:
brand model_name fuel_type
Audi A4 Gas
Audi A4 Diesel
Audi A6 Gas
Should all be valid. But another record with 'Audi, A6, Gas' should NOT be valid.
I know of this validation, but I doubt that it actually does what I want.
validates_uniqueness_of :brand, :scope => {:model_name, :fuel_type}
There is a syntax error in your code snippet. The correct validation is :
validates_uniqueness_of :car_model_name, :scope => [:brand_id, :fuel_type_id]
or even shorter in ruby 1.9.x:
validates_uniqueness_of :car_model_name, scope: [:brand_id, :fuel_type_id]
with rails 4 you can use:
validates :car_model_name, uniqueness: { scope: [:brand_id, :fuel_type_id] }
with rails 5 you can use
validates_uniqueness_of :car_model_name, scope: %i[brand_id fuel_type_id]
Depends on your needs you could also to add a constraint (as a part of table creation migration or as a separate one) instead of model validation:
add_index :the_table_name, [:brand, :model_name, :fuel_type], :unique => true
Adding the unique constraint on the database level makes sense, in case multiple database connections are performing write operations at the same time.
To Rails 4 the correct code with new hash pattern
validates :column_name, uniqueness: {scope: [:brand_id, :fuel_type_id]}
I would make it this way:
validates_uniqueness_of :model_name, :scope => {:brand_id, :fuel_type_id}
because it makes more sense for me:
there should not be duplicated "model names" for combination of "brand" and "fuel type", vs
there should not be duplicated "brands" for combination of "model name" and "fuel type"
but it's subjective opinion.
Of course if brand and fuel_type are relationships to other models (if not, then just drop "_id" part). With uniqueness validation you can't check non-db columns, so you have to validate foreign keys in model.
You need to define which attribute is validated - you don't validate all at once, if you want, you need to create separate validation for every attribute, so when user make mistake and tries to create duplicated record, then you show him errors in form near invalid field.
Using this validation method in conjunction with ActiveRecord::Validations#save does not guarantee the absence of duplicate record insertions, because uniqueness checks on the application level are inherently prone to race conditions.
This could even happen if you use transactions with the 'serializable' isolation level. The best way to work around this problem is to add a unique index to the database table using ActiveRecord::ConnectionAdapters::SchemaStatements#add_index. In the rare case that a race condition occurs, the database will guarantee the field's uniqueness.
Piecing together the other answers and trying it myself, this is the syntax you're looking for:
validates :brand, uniqueness: { scope: [:model_name, :fuel_type] }
I'm not sure why the other answers are adding _id to the fields in the scope. That would only be needed if these fields are representing other models, but I didn't see an indication of that in the question. Additionally, these fields can be in any order. This will accomplish the same thing, only the error will be on the :model_name attribute instead of :brand:
validates :model_name, uniqueness: { scope: [:fuel_type, :brand] }

RAILS 3 model validation inclusion in does not work

# ==Schema Information
# Schema version:
# Table name: terms
# id :integer not null, primary key
...
# user_id :integer
# term_type :string(255)`
term.rb:
class Term < ActiveRecord::Base
validates :term_type, :inclusion => { :in => %w(Term Segment Entity Abbreviation) }`
Rails 3.0.3, ruby 1.8.7, Windows via Cygwin
The validation does not seem to work, i.e. it accepts any value for term_type.
When using inclusion (or validates_inclusion_of which produces the same fail condition) do I need DB validations matching those in the model?
Any issues with Strings I should be wary of?
Term_type is just a string in the DB and not a separate table.
Any pointers much appreciated.
Vince
Have you tried using
validates :field, :inclusion => %{abc ade aeee}

Resources