Find records related to other records in controller (ruby on rails) - ruby-on-rails

I'm grabbing a list of users and storing in #users.
Now I need to find properties related to only this list of users I have queried.
if params[:company].present?
#users = User.where(parent_id: params[:company]).or(User.where(id: params[:company]))
##properties = #properties.where(user_id: params[:company])
end
I would basically like to include #users inside #properties.where()
I need to get each property that has a user_id present in my #users array
edit:
I just did the following which gives me the result, however, I'm sure there's a much better way of doing this via activerecord:
ids = []
#users.each do |user|
ids.push(user.id)
end
#properties = #properties.where(user_id: ids)

#properties.where(user_id: #users.ids)
That should work. It'll take the id of user ids and perform a filter using the IN clause.
Perhaps adding your models and their relationships we can think about something better.

Related

ajax-datatables-rails, passing ids of records from get_raw_records to view

I am using the gem ajax-datatables-rails and manage to build a table that works pretty well.
I would however to retrieve the list of IDs of my records at the get_raw_records function levels, before the data gets processed and formatted.
The reason is because I am using filters and I would like to call an action in the view that will affect ONLY the records filters (not only the ones in current page).
Could you please help me ?
my method looks as:
def get_raw_records
query = Book.where(user_id: user.id)
query = query.where(subject: params[:subject_id]) if params[:subject_id].present?
query
end

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

Does Rails Auto-Assign ID's?

I'm trying to sort my users in my controller, and I wanted to sort them by id number. My question is, does rails automatically assign orders an id when they are created, or do I need to add that to the create function in my create action in my controller? For example, can I say this:
def index
#users = User.all.order(:WHAT TO PUT HERE???????)
end
Would I put :id in the space? If I did so, would I need to define id somewhere else or is this something ruby does on the back end?
In most cases Rails would return you records sorted by id. But you should not rely on Rails as sorting is database-specific.
To explicitly add sorting by id you should use:
def index
#users = User.order(:id)
end
Id is automatically added, you don't need to declare it anywhere.
Rails only helps you create the table via migrations. When a migration creates a table it automatically adds the id column as a primary key set to auto increment. So why you create records it's actually the database that adds the id, or as aforementioned, it auto increments it +1 from the last id. Therefore, when you use ActiveRecord to create a record you don't need to specify an id.
Now for your main question: you can pass the name of the column to the order method when you want to sort ascending by that column. You don't need to call all though.
So just do this:
User.order(:id)
That will sort from lower ids to higher. To do the opposite:
User.order("id DESC")
This will give your the most recently created records first by sorting from higher ids to lower.
If you want to sort User by ID
#users = User.order(:id) #ASC default
#users = User.order('id ASC') #ASC explicit
#users = User.order('id DESC') #DESC explicit
...and never forget the User.order('-id') unary minus shortcut...

How to set default_scope order on attribute from another unassociated model

I have a Search resource that returns posts based on a filter as described in Railscast111, and have the following code:
def filter_posts
posts = Post.order('created_at DESC')
posts = posts.where("name ilike ?", "%#{keywords}%")
posts = posts.where(... #numerous other filters
posts
end
The filter itself seems to work fine. However, the content is not always returned in order of 'created_at DESC'. How can I sort the final output so that it's always in order of 'created_at DESC'? Currently, there is no association between the Post and Search models. Do I need to build one? If so, how?
Have you tried chaining the two conditions together?
posts = Post.where("name like?", "%#{keywords}%").order('created_at DESC')
Depending on how many filters you end up calling, you'll need to keep updating your original result, with the updated scope (based on your filter), as each time you use where it creates a new scope, instead of adjusting the original one. So you seem to be on the right path, as your original code does this, e.g
posts = Post.where("filter1")
posts = posts.where("filter2")
Have you tried sorting after all of the filters have been applied, so something like
posts = posts.order('created_at DESC')
or
posts = posts.sort_by &:created_at
Also, I'm not really sure what you mean by a Search resource, when (at least in this case) it appears you could keep the search logic within the Post model itself. Can you clarify, or maybe post the model?

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.

Resources