Rails has different types of finder methods that reduces your great amount of time. Suppose you want to create a record only if it doesn't exist already, your first approach would be first find the record and if is not already exist then you will create that using new command. like
# To check whether a user has already liked an article
# if present then get the object otherwise create the record
like = Like.where(user_id: user_id, article_id: article_id).first
if like.nil?
like = Like.create(user_id: user_id, article_id: article_id)
end
Now you can see it is a two step process, to reduce this kind of difficulty rails provides some special finders and methods that are used for such tasks:
1. find_or_initialize_by
find_or_initialize_by is a method that checks whether a record already exists by the attribute or not, if it already exists then it just returns their object, otherwise it initializes the object and returns that, but doesn't save that record in the DB.
user = User.find_or_initialize_by(email: "someemail@somedomain.com")
# if record already exists:
# Output will be like
# => <User id: 55, email: "someemail@somedomain.com", created_at: "2016-05-10 06:09:27", updated_at: "2016-05-10 06:09:27">
# if record doesn't exist:
# Output will be like
# => <User id: nil, email: "someemail@somedomain.com", created_at: "2016-05-10 06:09:27", updated_at: "2016-05-10 06:09:27">
2) find_or_create_by:
find_or_create_by is similar to the find_or_initialize_by, but it not only initializes the object but also executes the create query, it means it also saves the record to the database if it doesn't exist already.
user = User.find_or_create_by(email: "someemail@somedomain.com")
## SQL generated will be like
SELECT * FROM users WHERE (users.email = 'someemail@somedomain.com') LIMIT 1
BEGIN
INSERT INTO users (email, created_at, updated_at) VALUES ('someemail@somedomain.com', '2016-05-10 06:09:27', '2016-05-10 06:09:27')
COMMIT
# Output will be same whether the record already exists or not:
# => <User id: 55, email: "someemail@somedomain.com", created_at: "2016-05-10 06:09:27", updated_at: "2016-05-10 06:09:27">
3) find_or_create_by!:
find_or_create_by! is similar to the find_or_create_by, but it raises an exception if the created record is not valid. suppose the name field in the user was compulsury then it will raise an error.
user = User.find_or_create_by(email: "someemail@somedomain.com")
# Output will be same whether the record already exists or not:
# => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
4) Dynamic Finders:
Rails also has some dynamic finders. Suppose you have some column in your table then rails automatically creates dynamic finders with that column like:
## for email field
find_by_email
user = User.find_by_email(some_email)
## for name field
find_by_name
user = User.find_by_name(some_name)
## for id
find_by_id
user = User.find_by_id(some_id)
0 Comment(s)