Ruby - Order an Array - ruby-on-rails

I have a table with 2 columns. "car" "year". I want to do a collect into an array of all cars and then sort them by year. How do I do that?
<% #cars_pre = Car.find(:all) %>
<% #cars = #cars_pre.collect {|x| x.car} %>
I need the steps to order the #cars array by year, keep in mind I am not keeping year values in the #cars array, just cars. Thanks in advance.

From the code sample, I'm guessing you are using Ruby on Rails. If you are, I would recommend you allow your database to order the results. For example:
#cars = Card.order("year").all

Use sort:
#cars.sort_by!(:year) # in-place sort
Why remove the information by which you wish to sort then sort it by that information? Just keep the information in the array–there's no need to remove it. Plus you need it for the sort.
That said, why not sort it on the DB side using order("year")?

Related

Rails: Join arrays from two queries

I'm sorry to ask a stupid question. I've got an array that I want to populate with two similar queries to my database.
#experience_items = #user.experience_items.where(current: true).order(start_date: :desc)
#experience_items << #user.experience_items.where(current: false).order(end_date: :desc)
This is currently returning an ActiveRecord::AssociationRelation, which I can't iterate through with <% #experience_items.each do |item| %>
I know this is basic, but I just don't understand it. Why can't I iterate through #experience_items?
It's because you add ActiveRecord::Relation to #experience_items as an element instead of concatenating these array-like objects. This should work:
#experience_items += #user.experience_items.where(current: false).order(end_date: :desc)

RoR: How to sort an array with the help of scopes

I have an array #products. Each element of the array is a hash, containing a few fields (but not all) from Product table and the corresponding values.
I have a scope descend_by_popularity in Product which allows me to sort the products based on popularity field. I'd like to sort the array #products using this scope.
What I tried:
#product_group = Array.new
#products.each do |product|
#product_group.push(Product.find(product['id']))
end
#product_group1 = #product_group.descend_by_popularity
But this gives me error:
undefined method `descend_by_popularity' for #<Array:0xb2497200>
I also want to change the sorted Product list back to the format of #products array.
Thanks
Scopes only make sense within the ActiveRecord context for requests to the database (since it is used to change the SQL query). What you did is throwing a lot of products into an array. This array then knows nothing about the scope anymore. You would have to use the scope when you create the #products object. (and it does not seem to make a lot of sense to move the result of a query into an array)
So something like
#products = Product.descend_by_popularity.where(some more stuff)
should work for you. After that you should have the records in the order defined by the scope and can then either use them directly or still push them into an array if that's what you want to do.
With the updated info from the comments it looks like maybe the best way to go would be to first collect only the Product ids from the solr response into an array and then run that as search together with your scope:
#product_group = #products.map{|product| product.id}
#result = Product.where(id: #product_group).descend_by_popularity
this should technically work, peformance is a different question. I would consider aggregating this data into the Solr document, if it doesn't change too often.
Now assuming you are only interested in the order of products as such, you could do something like this to get #products into this order:
#result.map{|r| #products.find{|p| p[:id] == r.id}
though this may slow down things a bit.
Try this: find_by_id as params
#product_group = Array.new
#products.each do |product|
#product_group.push(Product.find(params['id']))
end
and return the array of #product_group
#product_group1 = #product_group.descend_by_popularity

Sort an array object containing activerecord query results using sort method in reverse order (DESC)

I have an array object #questions which is a collection of two Active record query results based on two conditions. #questions have a set of questions along with their attributes. I want to sort it in descending order only by using sort method based on one of its attribute created_at.
Please help to get that work :)-
I got it.
There is a ruby way of doing it on array object #questions.
#questions = #questions.sort { |value1, value2| value2.created_at <=> value1.created_at }
The above just works fine for me.
try this one
#questions = Question.order("created_at desc")

rails where() sql query on array

I'll explain this as best as possible. I have a query on user posts:
#selected_posts = Posts.where(:category => "Baseball")
I would like to write the following statement. Here it is in pseudo terms:
User.where(user has a post in #selected_posts)
Keep in mind that I have a many to many relationship setup so post.user is usable.
Any ideas?
/EDIT
#posts_matches = User.includes(#selected_posts).map{ |user|
[user.company_name, user.posts.count, user.username]
}.sort
Basically, I need the above to work so that it uses the users that HAVE posts in selected_posts and not EVERY user we have in our database.
Try this:
user.posts.where("posts.category = ?", "Baseball")
Edit 1:
user.posts.where("posts.id IN (?)", #selected_posts)
Edit 2:
User.select("users.company_name, count(posts.id) userpost_count, user.username").
joins(:posts).
where("posts.id IN (?)", #selected_posts).
order("users.company_name, userpost_count, user.username")
Just use the following:
User.find(#selected_posts.map(&:user_id).uniq)
This takes the user ids from all the selected posts, turns them into an array, and removes any duplicates. Passing an array to user will just find all the users with matching ids. Problem solved.
To combine this with what you showed in your question, you could write:
#posts_matches = User.find(#selected_posts.map(&:user_id).uniq).map{ |user|
[user.company_name, user.posts.size, user.username]
}
Use size to count a relation instead of count because Rails caches the size method and automatically won't look it up more than once. This is better for performance.
Not sure what you were trying to accomplish with Array#sort at the end of your query, but you could always do something like:
#users_with_posts_in_selected = User.find(#selected_posts.map(&:user_id).uniq).order('username DESC')
I don't understand your question but you can pass an array to the where method like this:
where(:id => #selected_posts.map(&:id))
and it will create a SQL query like WHERE id IN (1,2,3,4)
By virtue of your associations your selected posts already have the users:
#selected_posts = Posts.where("posts.category =?", "Baseball")
#users = #selected_posts.collect(&:user);
You'll probably want to remove duplicate users from #users.

Sorting and searching on a field which model doesn't have

I have an HTML table where I show the data from a particular model but I also show a column in the HTML table which doesn't belongs to that model. this column comes after some calculation(In this calculation I use 3-4 more tables). I want to give the sorting and searching functionality on that column. Anyone having idea what is the best way to do that?
Updated:
The main problem is if I provide sorting/searching on that column then I have to fetch all records from database for calculation which will not be good idea.
If you are looking for performance solution: just add new field into your table to store your calculation.
Anyway, you can't solve your problem without fetching all your records.
Or you can use JavaScript for searching and sorting, but only if there are not many items.
You can sort you model:
q_new.sort! { |x, y|
y.creation_date <=> x.creation_date
}
creation_date is a any field or a method of the model.
I would create a virtual resource on the model, which contains the sorter in Ruby-code. Assuming sum is your virtual property.
def by_sum(options = {})
#items = self.class.find(options)
#items.sort! { |a,b| a.sum <=> b.sum }
end
In your controller you can call:
Item.by_sum({:where => "'foo' = 'bar'"})

Resources