ror find many records in db by parameter - ruby-on-rails

I know how to find single item with given parameter.
#record = Record.find_by(phone: params[:phone])
How do I find all records in db with given parameter?
#records = ?

#records = Record.where(phone: params[:phone])

#records = Record.where(phone: params[:phone]).all

Related

Ruby, query active model dynamically [duplicate]

This question already has an answer here:
rails dynamic where sql query
(1 answer)
Closed 5 years ago.
I have an Order model in my ruby on rails application which has several attributes. I want to query those orders according to parameters given by users such as itemCount, totalPrice and created date.
If one of those attributes is given, I mean it's not nil, I need to query model by using it.
I can do something like:
if params[:totalPrice] and params[:itemCount] and params[:created_date]
#product = Product.where(totalPrice: params[:totalPrice],itemCount: params[:itemCount],created_date: params[:created_date])
elsif params[:totalPrice] and params[:itemCount]
#product = Product.where(totalPrice: params[:totalPrice],itemCount: params[:itemCount])
elsif params[:totalPrice] and params[:created_date]
#product = Product.where(totalPrice: params[:totalPrice],created_date: params[:created_date])
elsif params[:itemCount] and params[:created_date]
#product = Product.where(itemCount: params[:itemCount],created_date: params[:created_date])
elseif ....(and continues)
However, I can't be sure about that. Maybe there is there a "Ruby" way to achieve that problem.
What is the best practice to do that,
Thanks.
You can chain the different scopes with ActiveRecord:
#products = Product.all
#products = #products.where(totalPrice: params[:totalPrice]) if params[:totalPrice]
#products = #products.where(itemCount: params[:itemCount]) if params[:itemCount]
#products = #products.where(created_date: params[:created_date]) if params[:created_date]
# etc...
And this can easily be dynamic (but white-listed):
filterable_columns = %i(itemCount totalPrice created_date)
#products = Product.all
filterable_columns.each do |column|
#products = #products.where(column => params[column]) if params[column]
end

Alternative to using 'order' within an array

I've been doing some edits to an output when working with some records and i've ran into a problem where the sorting option no longer is working.
Initially with how things were created when I would do a #record.class the output was Record::ActiveRecord_Relation < ActiveRecord::Relation
However now after making my changes the class has changed. So now when I run a #record.class the output is Array < Object.
I think this is the root reason why i've ran into this problem.
My code is
#q = #records.search(params[:q])
#records = #q.result(distinct: true).select { |k,_v| k[:disabled] }
#records = #records.order("records.updated_at desc").page(params[:page] || 1).per(params[:per] || 30)
The error I am getting is NoMethodError: undefined methodorder' for #`
Now i've tried to workout around this by
#records = #records.sort_by("records.updated_at desc")
#records = #records.paginate.page(params[:page] || 1).per(params[:per] || 30)
However the error with the first line of my solution is #records = #records.sort_by("records.updated_at desc") I'm not able to get past that line in case there is an error with my paginate solution.
If anyone could take a look, I would really appreciate it!
your #records is a Ruby array, not an ActiveRecord "array"
You can try #records.sort_by(&:updated_at) to sort your array
The issue is that you are calling result, which is causing the SQL query to be executed and data returned from the database. You don't want to do that if you want to continue forming your query using the Arel AST that ActiveRecord uses. You want something closer to this (you'll likely need to adapt):
r = records.where(some_param: some_value, disabled: true) \
.order(updated_at: :desc) \
.page(params[:page] || 1).per(params[:per] || 30)
The signature you the methods you use look like you are using ransack.
Instead of loading all records into memory and selecting matching records in Ruby it might be much faster to only load matching records from database in the first place.
Assuming that disabled is a boolean column in your database, I would advise to change
#q = #records.search(params[:q])
#records = #q.result(distinct: true).select { |k,_v| k[:disabled] }
#records = #records.order("records.updated_at desc").page(params[:page] || 1).per(params[:per] || 30)
to
#q = #records.where(disabled: true).search(params[:q])
#records = #q.result(distinct: true)
#records = #records.order("records.updated_at desc").page(params[:page] || 1).per(params[:per] || 30)

Rails OR condition inside where with same input

I have the following active record query:
User.where(["id = ? OR token = ?", params[:id], params[:id]]).first
Here, params[:id] = 9MrEflgr
PROBLEM
As per logic, params[:id] can be numeric id or alphanumeric token.
I want to get something like User.find_by_id_or_token(params[:id]) in where clause.
Here, since the params[:id] starts with '9', so active record gives me user with id 9 instead of checking for token field. How to avoid this?
As the comment mentioned, you need to check if the params is an integer. This SO question has good suggestions on how to do that (where you can implement is_integer? below).
if params[:id].is_integer?
User.where(["id = ? OR token = ?", params[:id], params[:id]]).first
else
User.where(["token = ?", params[:id]]).first
end

How do I create instance variables from an array?

I'm using Rails 3.2. Here's my code:
transports = %w(car bike)
transports.each do |transport|
#transport = transport.classify.all
end
That code is not working, but I want the results to be:
#cars = Car.all
#bikes = Bike.all
How do I do that?
transports.each do |transport|
instance_variable_set("##{transport}",
transport.classify.constantize.all)
end
Update Given that the entries in the transports array are now singular the correct code to get the result you want is
transports.each do |transport|
instance_variable_set("##{transport.pluralize}",
transport.classify.constantize.all)
end

Rails Given an array of objects from a db, is there a way to get an item in the array w/o having to rehit the db?

Given:
#votes (user_id, option_id)
If do: #project.votes I get all the votes for that project.
If I then want to see what the current user voted for I have to do:
Votes.where(:user_id => current_user.id).first
This is a record that's already in the #project votes query. Is there a way I can find the record in that first query w/o having to rehit the db?
Thanks
You can just use the regular ruby Enumerable#select method:
#votes = project.votes.all
# ... other code ...
current_user_votes = #votes.select{ |v| v.user_id == current_user.id }
This will return an array of all the user's votes for the project. If the user is only allowed one vote, and you want a single value, not an array, just use .first like so:
#votes = project.votes.all
# ... other code ...
current_user_vote = #votes.select{ |v| v.user_id == current_user.id }.first

Resources