Rails - find by with two fields using OR instead of AND? - ruby-on-rails

I am familiar with doing a find on two fields:
user = User.find_by_username_and_email(params[:username], params[:email])
However, I would like to retrieve one record where the username OR email equals the same field. Something like:
user = User.find_by_username_or_email(params[:text])
Which I know doesn't work. Is this possible? Any help is a appreciated.

Just to expand on the answer by #xdazz, you can use the following syntax to allow searching any number of fields by the same value without having to repeat the value:
user = User.where('username = :text or email = :text', :text => params[:text]).first
Very useful when you come to search postal address fields, for example.
2.2.1 Placeholder Conditions

You could use .where :
user = User.where('username = ? or email = ?', params[:text], params[:text]).first

Related

Rails show record start from db with specific letters

I want to show only those inquiry processes where company name starts from specific letters. I thought I should use start_with? but in the code below I've an error
NoMethodError (undefined method `start_with?'
def call
InquiryProcess.all.includes(inquiry_field_responses: :inquiry_field).select do |process|
process.inquiry_field_responses.select do |inquiry_field_responses|
inquiry_field_responses.inquiry_field.name == 'company_name'
end&.last&.value == start_with?('aaa')
end
end
I would do something like this:
field = InquiryField.find_by!(name: 'company_name')
response_table = InquiryFieldResponse.arel_table
responses = field.inquiry_field_responses.where(response_table[:value].matches('aaa%'))
processes = InquiryProcess.where(id: responses.select(:inquiry_process_id))
First select the field that you want to check the values of. From there select all responses that belong to that specific field and start with 'aaa'. Then select the processes using the responses.
The issue with your current code is that you'll do:
'some string' == start_with?('aaa')
Which should be:
'some string'.start_with?('aaa')
Or more specific to your case:
end.last&.value&.start_with?('aaa')
It's much more easier.
Just use SQL for this:
InquiryProcess.where("company_name LIKE ?", "aaa%")
This shows you all inquiry_processes that company_name starts with aaa

Multiple word search in one field

I have search functionality with this code in the 'search.rb' file:
votsphonebooks = votsphonebooks.where("address like ?", "%#{address}%") if address.present?
There are multiple fields, this is just one of them.
How can I successfully change this line into something like a map to include multiple words.
Eg. If they type in '123 Fake St' - it will look for exactly that, but I want it to search for '123', 'Fake', 'St'.
First thing you should do is split the address by spaces:
addresses = params[:address].split(" ")
Then what you need is a OR query, you could do it by using ARel.
t = VotsPhoneBook.arel_table # The class name is my guess
arel_query = addresses.reduce(nil) do |q, address|
q.nil? ? t[:address].matches("%#{address}%") : q.or(t[:address].matches("%#{address}%"))
end
results = Post.where(arel_query)
Try using REGEXP instead of LIKE:
address_arr = address.split(" ")
votsphonebooks = votsphonebooks.where('address REGEXP ?',address_arr.join('|')) unless address_arr.blank?

How to check if text contains an #username? - Rails

In my create action in the comments controller I want to check if the comment text contains a "# + username" so I can add it to my public activities.
if #comment.body.include?(' [HERE] ')
maybe User.all.username.any? ?
You better use ruby regex to first find the user name from comment body matching pattern #abc and then user that username query database to find user
#comment.body.scan(/#(\w+)/).flatten.to_a.each do|username|
if User.where(:username => username).any?
# your code here
end
end
or search the users with single database query by passing the array
usernames = #comment.body.scan(/#(\w+)/).flatten.to_a
if User.where(:username => usernames).any?
# your code here
end
This will optimize the db query and will not load all users to memory.
A quick answer:
if User.pluck(:username).any? {|u| #comment.body.include?("##{u}")}
# ...
end
A better answer:
Why not use a javascript library to auto-complete the username? This is more user friendly, and scales better as the User table grows.

RoR Take atrributes from ActiveRecord::Relation

I'm a novice at RoR. Tell me please how to take attributes from ActiveRecord::Relation? For Example I write:
#user = User.where(code: 123)
next I want to take attribute id
id = #user.id
but this method is not working. Thanks in advance
When use .where it gives you an active record relation so you can't find id directly on it because it's a relation not a single model object.
Fix:
You can do
#user = User.where(code: 123).first
OR
You can use dynamic finders
#user = User.find_by_code(123)
If you want to find single user with code == 123, you can use find_by method, like this:
#user = User.find_by(code: 123)
It returns User instance, so you can call id method on it.
EDIT: If you use Rails prior to 4.x version, you can use dynamic find_by_code finder:
#user = User.find_by_code(123)
You are using where clause it returns array. Use it like :
#user = User.where(code: 123).first
Above is not right way for query. So you can also write your code to find user like :
#user = User.find_by_code(123)
With above two ways you get single object and you can find any attribute from it. #user.id etc
I guess you are missing first, where returns an array of objects, so you need to use first to get the object out of array
Do this
#user = User.where(code: 123).first
id = #user.id

Rails/Ruby. Searching for double emails

I am developing an API in Rails 3.
Lately I have seen some user accounts being double. I am not sure how many so I need a way to find out which accounts that are double.
Is there a way, in ruby, to search the entire database and fetch those user accounts that got the same email address (hence double)?
Thankful for all input!
Just open the Rails console (rails c) and type something like this:
Account.group(:email).having('count_all > 1').count
This will return a Hash with email addresses being the key and the number of times it occured as the value. The result will look something like this:
=> #<OrderedHash {"billyjoe#example.com"=>2, "johndoe#example.com"=>2}>
Then, I guess you could take those email addresses and actually get the accounts:
Account.where(:email => "billyjoe#example.com")
To output them all in the console, you could combine both of those like this:
email_hash = Account.group(:email).having('count_all > 1').count
email_hash.each do |email, count|
Account.where(:email => email).each do |account|
p account
end
end
I think if you try to use(for example):
UserAccount.all.group_by(&:email_address).each do |email, record|
#you will get a set of records grouped by email address
end
this will help you (You did not write detailed description of your models but if think you will get the clue)

Resources