Order Rails Active Record by Count in Another Table - ruby-on-rails

I have a comment model which has likes associated with it. I keep the likes in a separate table and the comment model has_many likes. However, I want to order the comments by most popular and I do not know how to do an active directory query to return the order I want. I have tried:
Comment.order(:likes.count)
This isn't working. Any advice?

This is working for me currently with Rails 5:
Comment.joins(:likes)
.select('comments.*, count(likes) as like_count')
.group('comments.id')
.order('like_count desc')
It even adds a like_count attribute to each returned comment, so you can call comment.like_count.

Try this:
Comment.joins(:likes).order('count(likes.*) desc')

Related

"Index" page to display all items associated with current_user using '.where' but result is ActiveRecord, and I need to run each do on it

Sorry for the long title, I wanted to make sure I was being as specific as possible. This is my first question so please be patient!
I am building an index page that displays all the items in the consultations model that are associated with the current user. This used to be easy when I set #consultations = Consultation.where(user_id: current_user.id) in my controller. However, because consultations should be able to have more than one consultant assigned to each one, I changed the Consultation.user_id field to be a string array (I wasn't able to change to an integer array). I also connected the User and Consultation models via has_and_belongs_to_many and a join table.
I am now trying to query them with #consultation = Consultation.where {|a| a.user_id == ['current_user.id']} so that I can display all consultations in which the Consultation.user_id array contains the current_user.id.
This works as expected in pry, but on the actual view page I'm getting an error: NoMethodError: undefined method /'each/' for #<ActiveRecord::QueryMethods::WhereChain:0x007f82c23fe840>.
I understand that this is to be expected, since .where returns an ActiveRecord, which does not support methods such as each do, which is what I'm using on the index page to show all the consultations.
Any idea on how I can properly display all the consultations associated with the current_user.id? Thanks in advance.
you can do it like
#consultations = current_user.consultations
use associations instead of query
BTW
#consultation = Consultation.where {|a| a.user_id == ['current_user.id']}
this will not work because 'current_user.id' is string, it isn't id
it means that you try find all consultations where user_id == 'current_user.id'.
Do you see what I mean?
It sounds like you have a many-to-many relationship between consultants and clients. You can solve this by having a join table in the middle that holds both the client_id and the consultant_id. This would be a 3rd model to the consultant model and client models that you already have. You shouldn't try to store arrays as fields in ActiveRecord. ActiveRecord is just helping you organize data that is being written to a database.
Once you have a join table with both foreign_id's you can easily set up has_many relationships for both the client and consultants and then a has_may_through association. Then you won't need to worry about any #where calls because you can just call the associations.
The problem is that the syntax where you pass a block to where is something that you've just made up. Because no actual arguments are passed to where you don't get an ActiveRecord::Relation
You could change relationship between consultation and users to be has many through. If that join model was called assignments, then you could write a query such as
Consultation.joins(:assignments).where(assignments: {user_id: current_user.id})
If you keep your current approach with a user_id array column then, assuming this is Postgres, you can use the array query methods:
Consultation.where("user_id #> ARRAY[?]", current_user.id)

Find last record for specific user (Rails)

I want to do something like Report.last, but instead of the last record entered, I want the last record that a specific user entered.
You are probably looking for something like
Report.where(created_by_id: user_id).last
where the key in the where clause is the foreign key in a reports table record to the association with the user. I'd have to know how your models associate reports with their creators to know the right syntax.
You need to include the user_id or some sort of user indicator to be able to get the last record for a specific user. You will need to post more information like the model for your users and reports. But I think you are looking for something like this:
Report.select([:user_id, :id, 'MAX(created_at)']).group(:user_id).limit(5)
user = User.where(:some_condition => "some_value").first
user.reports.last
This would work if user is a local variable representing an active record user and records would query its associated records and find the last one.
I assume you have model relationship between User & Report
user = User.first
user.reports.order("updated_at DESC").last

Rails "where" method to find parent by child attribute

I have a Rails app where I'm trying to create a list of parent classes based on the date of their child classes.
right now I have:
orders = Order.where("order_reminders.date < ?", 1.month.from_now)
But I'm receiving an error.
"no such column: order_reminders.date"
I'm sure my problem is with my query but I'm not sure how to fix it.
You need to use methods like references, joins, includes or eager_load depending on what you need. The simplest way to determine what to select is to go to the documentation/api and read them.
As for the answer, if order_reminders is defined as an association in Order, just use joins which uses an INNER JOIN by default, meaning it won't return orders without order_reminders which is most probably what you want when you're searching for something.
Order.joins(:order_reminders).where('order_reminders.date < ?', 1.month.from_now)
Is order_reminders another table in your app?
If order has_many order_reminders then try this query
Order.joins(:order_reminders).where("order_reminders.date < ?", 1.month.from_now)

Rails eager load association with selected attributes

Can anyone tell me if it's possible to eager load an association but only return specific attributes?
I'd like to retrieve some orders with their accounts but only require the account names.
Order.select([:id, :account_id]).includes(:account).limit(2)
I think jvnill's comment says it all:
I'm not sure that is possible. You can however add the account_name to the returned order records.
orders = Order.joins(:account).select('orders.id, orders.account_id, accounts.name AS account_name')
then just use account_name like orders.first.account_name

Rails :HOw to order a table by associated model

I think the problem is trivial. I have two models: User and Betting.
User
has_many :bettings
Betting
belongs_to :user
I just want to get the users ordered by who made more bettings.
Are you on Rails2 or Rails3?
On Rails3, you can use the Ruby sort method and something like:
User.includes(:bettings).sort{|x,y| x.bettings.size <=> y.bettings.size}
Of course, in this case the sorting occurs after the SQL request, which is not optimum if you have large tables… I'm trying to figure how to do it at the SQL level with no answer yet…

Resources