I have an user array like this:
users_array = [[1,text for 1],[2,text for 2],[3,text for 3],[4,text for 4],[5,text for 5]]
here first element is user_id and second element is text which is specific to user_id in the same array.
Now I am trying to have user object from instead of ids in array like these.
users_array = [[#<User id: 1, encrypted_email: "">,text for 1],[#<User id: 2, encrypted_email: "">,text for 2],[#<User id: 3, encrypted_email: "">,text for 3],[#<User id: 4, encrypted_email: "">,text for 4],[#<User id: 5, encrypted_email: "">,text for 5]]
I am trying not to loop the array and hit the db thousand times for thousands user.
data = users_array.to_h
# find all users with single query and build your map
User.where(id: data.keys).map { |user| [user, data[user.id]] }
You could use transpose to extract ids and values, and zip to combine users and values:
ids, values = users_array.transpose
users_array = User.find(ids).zip(values)
Related
Using Rails 6.
My dirty code
active_card_ids = JSON.parse(cookies[:card_ids])
#active_cards = []
#best_cards = Houses.where("#{payment_category} IS NOT NULL").order("#{payment_category} DESC")
#best_cards.each do |card|
if active_card_ids.include? card.id
#active_cards << card
end
end
What I am trying to do
I have an array of records queried: queried_records = [<object id: 1>, <object id: 3>, <object id: 4>, <object id: 7>]
Another array of IDs: wanted_ids = [4, 5]
Create another array: selected_records = []
I want to move queried_records found in wanted_ids, to selected_records.
In this example, we found <object id: 4> from queried_records, so we want to move (not copy) it to selected_records.
The results should be selected_records return an array [<object id: 4>]
If I understood your problem correctly, there will be id's in active_card_ids and you want another array with those id's only.
You can try querying the DB directly, then you don't have to run the loop.
The below sample takes an array of id's and passes it to where IN clause to query only active cards.
active_card_ids = JSON.parse(cookies[:card_ids])
#active_cards = Houses.where(id: active_card_ids).where("#{payment_category} IS NOT NULL").order("#{payment_category} DESC")
#best_cards = Houses.where("#{payment_category} IS NOT NULL").order("#{payment_category} DESC")
Another approach you can try is:
active_card_ids = JSON.parse(cookies[:card_ids])
#best_cards = Houses.where("#{payment_category} IS NOT NULL").order("#{payment_category} DESC")
#active_cards = #best_cards.select{ |card| active_card_ids.include? card.id }
I need to retrieve records from an array of Ids like:
User.where(id: [1,1,2])
BUT the problem is that I only get two records from this request and I want to have the [#User id:1] in double as number 1 appears twice in the array.
I could do a n+1 request but that's not very optimistic...
The steps you should follow if you want a single simple query to database:
Create a hash based on the array like:
hash = {1=>2, 2=>1, 3=>1, 4=>3} for [1, 1, 2, 3, 4, 4, 4]
Query simply:
users = User.where(id: your_array.uniq)
# Your case
users = User.where(id: [1, 1, 2].uniq) # because [1, 1, 2].uniq => [1, 2]
make your array:
the_way_i_want = []
hash.each do |key, value|
value.times do
the_way_i_want.push users.where(id: key)
end
end
set the users = the_way_i_want and return
users = the_way_i_want
crude but will save database access :-)
How about creating 1 request to DB, and then just format your data
user_ids = [1, 1, 2] # this you have
Create a hash { user_id: user_record, .... }
users = User.where(id: user_ids).map { |u| [u.id, u]}.to_h
Then create an array with all the records you want
user_ids.map do |u_id|
users[u_id]
end
I have this active record query:
shop = Shop.find(12934)
I then go and get a collection of products from this shop like so
#product_templates = []
shop.products.each do |product|
#product_templates.push(product.template)
end
So now I have an array of active record objects which look like this:
[
#<Product::Template id: 185549, name: "1:30pm", position: 0>,
#<Product::Template id: 185522, name: "11:30am", position: 1>,
#<Product::Template id: 185580, name: "7:00pm", position: 2>,
#<Product::Template id: 185556, name: "10:00am", position: 3>,
]
I want to update the position attribute by ordering each of these Product::Template by the time in the name e.g.
10:00am, 11:30am, 1:30pm, 7:00pm would be the order of the objects so the 10:00am object would get position: 0, 7:00pm would get position:3 etc.
How would I do this? Thanks for your time in advance
try this:
#product_templates.sort { |t1, t2| Time.strptime(t1, "%I:%M%P") <=> Time.strptime(t2, "%I:%M%P") }.each_with_index { |template, index| product.position = index }
What I did there was sorting your template array first, then updating position based on array index.
First of all, your way of filling #product_templates before sort is not a good way.
#product_templates =
shop.products
.map(&:template)
.sort_by{|template| template.name.to_time}
I have an array of hashes that I am trying to seed into a database.
shoe_array = [{:department_id=>8, :follower_id=>31}, {:department_id=>9, :follower_id=>41}, {:department_id=>4, :follower_id=>49}, {:department_id=>2, :follower_id=>58}, {:department_id=>5, :follower_id=>36}, {:department_id=>9, :follower_id=>63}, {:department_id=>2, :follower_id=>52}, {:department_id=>23, :follower_id=>26}, {:department_id=>5, :follower_id=>52}, {:department_id=>6, :follower_id=>30}]
shoe_array.each do |n, k|
department_id = n,
follower_id = k,
user_id = 1
Relationship.create!(department_id: department_id,
follower_id: follower_id,
user_id: user_id)
end
I'm only getting null values for both department_id and follower_id. user_id is working.
I have tried using "#{n}" and "#{k}", to get the key values set to department and follower ids. I've also tried iterating over the array only using .each do |a| and setting department_id: a['department_id'], follower_id a['follower_id']
as seen here: iterate through array of hashes in ruby and here :How do I iterate over an array of hashes and return the values in a single string?
but I'm only still getting null values. How can I get my values into the database?
shoe_array is an array of hashes, so you should iterate over each hash, and access each key-value pair:
shoe_array.each do |hash|
department_id = hash[:department_id]
follower_id = hash[:follower_id]
user_id = 1
Relationship.create!(
department_id: department_id,
follower_id: follower_id,
user_id: user_id
)
end
According the documentation you can create records from an array of hashes:
Following should work (You can use create! as well as create)
shoe_array = [{:department_id=>8, :follower_id=>31}, {:department_id=>9, :follower_id=>41}, {:department_id=>4, :follower_id=>49}, {:department_id=>2, :follower_id=>58}, {:department_id=>5, :follower_id=>36}, {:department_id=>9, :follower_id=>63}, {:department_id=>2, :follower_id=>52}, {:department_id=>23, :follower_id=>26}, {:department_id=>5, :follower_id=>52}, {:department_id=>6, :follower_id=>30}]
Relationship.create!(shoe_array.map{|arr| arr.merge!({user_id: 1})})
Change your iteration to
shoe_array.each do |shoe|
department_id = shoe[:department_id]
follower_id = shoe[:follower_id]
An example that can use |n, k| would be either a hash or an array of arrays. If you want to go down that route, you can call values on each hash in the array (assuming that the hash is consistent, meaning department_id always comes first before follower_id)
ids = shoe_array.map(&:values) # [[8, 31], [9, 41], [4, 49], [2, 58], [5, 36], [9, 63], [2, 52], [23, 26], [5, 52], [6, 30]]
Then you can just use your old code or refactor to
ids.each do |department_id, follower_id|
Relationship.create!(
department_id: department_id,
follower_id: follower_id,
user_id: 1
)
end
Take note though that you are iterating over the array twice and will be less efficient compared to the first one.
UPDATE
Another option is use the array elements as is.
shoe_array.each do |attributes|
relationship = Relationship.new(attributes)
relationship.user_id = 1
relationship.save!
end
Let me describe with simple example.
I have a list of numbers:
ex: list = [ 3, 1, 2 ]
and I have a table in DB named Products which have 3 rows with product_id = 1, 2and 3.
Now I need to query Products sort by list values (3,1,2) so the result will be:
product_3
product_1
product_2
Query will be like:
product.sort(list) or product.order(list) or some other alternative pls
This should work for you:
list = [3, 1, 2]
Product.where(product_id: list).sort_by { |p| list.find_index(p.product_id) })