I have a model Competitor like this
class Competitor < ActiveRecord::Base
belongs_to :admin_user
has_many :companies
attr_accessible :admin_user_id, :c1, :c2, :c3, :c4, :c5
validates :admin_user_id, :presence => true
validates_uniqueness_of :admin_user_id, :message => "This user has yet a competitors list"
end
C1, c2,.. are the id of companies. Selected from a drop down list. How can I validate the uniqueness of a row?
(i.e. is not possible to have two or more equals companies for an admin user BUT they can be empties).
You could write your own validation method that would enforce this.
class Competitor < ActiveRecord::Base
belongs_to :admin_user
has_many :companies
attr_accessible :admin_user_id, :c1, :c2, :c3, :c4, :c5
validates :admin_user_id, :presence => true
validates_uniqueness_of :admin_user_id, :message => "This user has yet a competitors list"
validate :check_companies
def check_companies
#[do your checks]
end
end
Related
In my Rails 5 app I have the following setup:
class Client < ApplicationRecord
has_one :address, :as => :addressable, :dependent => :destroy
accepts_nested_attributes_for :address, :allow_destroy => true
end
class Company < Client
has_many :people
end
class Person < Client
belongs_to :company
end
class Address < ApplicationRecord
belongs_to :addressable, :polymorphic => true
validates :city, :presence => true
validates :postal_code, :presence => true
end
A person can belong to a company but doesn't necessarily have to.
Now I want to validate a person's address only if that person doesn't belong to a company. How can this be done?
There might be other approaches as well, but based on my experience, something like this should work.
validates :address, :presence => true, if: -> {!company}
Hope this helps.
Validations can take either an if or unless argument, which accept a method, proc or string to determine whether or not to run the validation.
In your case:
validates :address, presence: true, unless: :company
Update according to comments
The above only takes care of skipping the validation itself, but due to accepts_nested_attributes_for OP still saw errors when trying to persist a missing address. This solved it:
accepts_nested_attributes_for :address, reject_if: :company_id
Nabin's answer is good but wanted to show another way.
validate :address_is_present_if_no_company
def address_is_present_if_no_company
return if !company_id || address
errors.add(:address, "is blank")
end
I have a user model which has a polymorphic relationship to teachers, students, and admin. These three types of users each belong to a school. I would like to have it so the username of the user is unique within a school. How would I write the validations to accomplish this?
Here is what my models look like:
class User < ActiveRecord::Base
belongs_to :profileable, :polymorphic => true
delegate :school, :to => :profileable
end
class Student < ActiveRecord::Base
belongs_to :school
has_one :user, :as => :profileable
delegate :name, :username, :to => :user
end
class Teacher < ActiveRecord::Base
belongs_to :school
has_one :user, :as => :profileable
delegate :name, :username, :to => :user
end
class Admin < ActiveRecord::Base
belongs_to :school
has_one :user, :as => :profileable
delegate :name, :username, :to => :user
end
I'm quite sure you will need to use a custom validator for this. The delegated attribute will not be usable in the User model. What you could do is also include the school_id in the User method and set it using before_validate every time. Then you'd be able to use the "simple" uniqueness validator:
validates :username, :uniqueness => {:scope => :school_id}
However, a custom validator joining the school_id of the profileable parent would probably be a cleaner way to go.
I have got three models
class RateCard < ActiveRecord::Base
validate :name, :presence => true, :uniqueness => true
has_many :rate_card_countries, :dependent => :destroy
has_many :rate_card_details, :dependent => :destroy
has_many :countries, :through => :rate_card_countries
end
class RateCardCountry < ActiveRecord::Base
validates :country_id, :presence => true, :uniqueness => true
validates :rate_card_id, :presence => true
belongs_to :rate_card
belongs_to :country
end
class Country < Geography
has_one :rate_card
has_one :rate_card_country
end
In rate_cards_controller i want to create/update rate_cards such that one country should have one rate_card..
For that i have added uniqueness validation in RateCardCountry Model.
And NOw i want to display the error in rate_card_controller while creating/updating rate_cards..
Needed help?
If I understand your intention correctly, you are trying to build a one-to-many relationship between RateCard and Country. In other words- a country will have only one RateCard, and a RateCard can belong to many countries.
Assuming that's the case, you really don't need the RateCardCountry model (which will be useful if you wanted it to be a many-to-many relationship).
You will need to have:
class RateCard < ActiveRecord::Base
validate :name, :presence => true, :uniqueness => true
belongs_to :rate_card
end
And make sure you have county_id foreign key in the RateCard table.
and then:
class Country < ActiveRecord::Base
has_one :rate_card
end
Also, it seems that right now you have:
class Country < Geography
I am not sure if you are subclassing from a Geography class, as you have not provided the rest of the code.
Hope that helps.
I have products and brands
products model:
class Product < ActiveRecord::Base
attr_accessible :brand_id, :title
belongs_to :brand
validates :title, :presence => true
validates :brand, :presence => {:message => 'The brand no exists'}
end
and the brands model
class Brand < ActiveRecord::Base
attr_accessible :name
validates :name, :presence => true
has_many :products, :dependent => :destroy
end
I want to validate if exist a product with a name in this brand.
I mean I could have 2 products with the same name in different brands but not in the same brand.
You could use the uniqueness validation with a scope:
validates :name, :uniqueness => { :scope => :brand_id }
Note that you have to specify :brand_id instead of :brand, because the validation can't be made on the relation.
If you don't know it, I suggest you to read the Active Record Validations and Callbacks guide.
NB: the syntax {:foo => 'bar'} is replaced (since Ruby 1.9.2) with {foo: 'bar'}.
I have users and issues joined by a votership model. Users can vote on issues. They can either vote up or down (which is recorded in the votership model). First, I want to be able to prevent users from casting multiple votes in one direction. Second, I want to allow users to cast the opposite vote. So, if they voted up, they should still be able to vote down which will replace the up vote. Users should never be able to vote on an issue twice. Here are my files:
class Issue < ActiveRecord::Base
has_many :associations, :dependent => :destroy
has_many :users, :through => :associations
has_many :voterships, :dependent => :destroy
has_many :users, :through => :voterships
belongs_to :app
STATUS = ['Open', 'Closed']
validates :subject, :presence => true,
:length => { :maximum => 50 }
validates :description, :presence => true,
:length => { :maximum => 200 }
validates :type, :presence => true
validates :status, :presence => true
def cast_vote_up!(user_id, direction)
voterships.create!(:issue_id => self.id, :user_id => user_id,
:direction => direction)
end
end
class Votership < ActiveRecord::Base
belongs_to :user
belongs_to :issue
end
class VotershipsController < ApplicationController
def create
session[:return_to] = request.referrer
#issue = Issue.find(params[:votership][:issue_id])
#issue.cast_vote_up!(current_user.id, "up")
redirect_to session[:return_to]
end
end
class User < ActiveRecord::Base
authenticates_with_sorcery!
attr_accessible :email, :password, :password_confirmation
validates_confirmation_of :password
validates_presence_of :password, :on => :create
validates_presence_of :email
validates_uniqueness_of :email
has_many :associations, :dependent => :destroy
has_many :issues, :through => :associations
has_many :voterships, :dependent => :destroy
has_many :issues, :through => :voterships
end
You would put the uniqueness constraint on the Votership model. You don't need to put validations on the association itself.
class Votership < ActiveRecord::Base
belongs_to :user
belongs_to :issue
validates :issue_id, :uniqueness => {:scope=>:user_id}
end
This means a user can only have a single vote on a given issue (up or down).
Relationship models:
class Person
has_many :accounts
has_many :computers, through: :accounts
end
class Account
belongs_to :person
belongs_to :computer
scope :administrators, -> { where(role: 'administrator') }
end
class Computer
has_many :accounts
has_many :people, through: :accounts
end
This is how it is called
person.accounts.administrators.map(&:computer)
We can do this better using ActiveRecord::SpawnMethods#merge!
person.computers.merge(Account.administrators)
Ref: https://coderwall.com/p/9xk6ra/rails-filter-using-join-model-on-has_many-through