I'm trying to sort ordered by updated_at of User record, which is associated from Code table.
#codes = Code.joins(:user).where('body like ?', "%"+params[:search]+"%").order('user.updated_at DESC').page(params[:page]).per(10)
However, it won't let me sort:(
This is the error message I get.
Error Message
Mysql2::Error: Unknown column 'user.created_at' in 'order clause
Your database table should be users not user (plural not singular). Update your order method as follows:
order('users.updated_at DESC')
Related
I have the following Rails models: Chat and Messages where a chat can have many messages. I have the following Rails query to pull the last message from the user for each chat where he is a recipient:
def index
messages = Message.where(recipient_id: id)
.select('DISTINCT ON ("chat_id") *')
.order(:chat_id, created_at)
end
This gives me the last message to the user of each chat that the user is a part of. I would now like to sort the results of this query by when the messages were created so that the latest messages go to the top. However, if I add
sorted = messages.order(created_at: :desc)
It doesn't sort the results of the first query, it simply appends the order by to the first query (which I know is the expected behavior) so I don't get a sorted list by created date. How can I do an order by to the result of the first query? Essentially something that would mimic the following with Rails syntax:
SELECT *
FROM (SELECT DISTINCT ON (chat_id) *
FROM messages
ORDER BY chat_id, created_at DESC) last_messages
ORDER BY created_at DESC
try this
Message.from(
Message.where(recipient_id: id)
.select('DISTINCT ON ("chat_id") *')
.order("chat_id, created_at DESC"),
:messages
).order(created_at: :desc)
You could do something like this -
def index
messages = Message.where(recipient_id: id)
.select('DISTINCT ON ("chat_id") *, created_at')
.order(:chat_id, created_at)
.sort_by(&:created_at).reverse
end
The first option is to unscope the :order of messages then order it again with your desired column.
sorted = messages.unscope(:order).order(created_at: :desc)
In case you can't unscope the messages, another option is turning messages into a subquery.
sorted = Message.where(id: messages).order(created_at: :desc)
I have a model, for example, Post, and a Post has_many comments. I would like to query posts in order of posts with the most comments to the least. How can I do this with an active record query?
Right now I am trying:
Post.includes(:comments).order('COUNT(comments.post_id) DESC')
but I am getting the error:
ActiveRecord::StatementInvalid (PG::UndefinedTable: ERROR: missing FROM-clause entry for table "comments")
Post.left_outer_joins(:comments)
.group(:id) # required by Postgres
.order(Arel.sql('COUNT(comments.*) DESC')) # https://github.com/rails/rails/issues/32995
If you want to use the count in the result you can select it as well:
Post.left_outer_joins(:comments)
.select('posts.*, COUNT(comments.*) AS comment_count')
.group(:id) # required by Postgres
.order('comment_count DESC') # Use COUNT(comments.*) in Oracle
Another way to solve this is by using counter_cache.
I have a table named property_audit_version_histories.
i am fetching the records using the following code
#version_logs = PropertyAuditVersionHistory
.includes(:property_audit_version, :user)
.where(property_audit_version_id: params[:id])
The result contain 3 records, 2 of which have the same action and user_id
Now i need to group the records using the columns action, user_id
I am getting the following error when i try to group the records
#version_logs = PropertyAuditVersionHistory
.includes(:property_audit_version, :user)
.where(property_audit_version_id: params[:id])
.group("action, user_id")
PG::GroupingError: ERROR: column "property_audit_version_histories.id" must appear in the GROUP BY clause or be used in an aggregate function
Based on the thread PG::GroupingError: ERROR: column "events.id" must appear in the GROUP BY clause or be used in an aggregate function i have modified the code as follows
#version_logs = PropertyAuditVersionHistory
.includes(:property_audit_version, :user)
.group("property_audit_version_histories.id")
.where(property_audit_version_id: params[:id])
.group("action, user_id")
Now the error is gone but still the result is having 3 records. After grouping i expect only 2 records.
Any idea on how to fix this?
You cant select all columns like mysql in postgresql when doing aggregrates.
So I guess this should work.
#version_logs = PropertyAuditVersionHistory
.where(property_audit_version_id: params[:id])
.group("action", "user_id", "property_audit_version_id")
.select("user_id", "action", "property_audit_version_id")
I dont know how is your model but this should work. If you need more fields let me know
What you need to do is specify which columns you want with
.select("user_id")
But for the columns you know will be the same use max(columnName) as columnName
for example:
.select("MAX(user_id) as user_id, action")
Make sure you are 100% sure that those columns will be the same value after grouping.
An Event has_many Votes and a Vote belongs_to a User. How can I get a user's event's that they personally have not voted on? This was my best shot:
Event.includes(:votes).where.not("votes.user_id = ?", current_user.id)
But I am getting the below error:
PG::UndefinedTable: ERROR: missing FROM-clause entry for table
"votes"
You need to either use a hash within the final parenthesis or use references as per Active Record Query Interface. Here's the resulting code:
Event.includes(:votes).where.not("votes.user_id = ?", current_user.id).references(:votes)
I have a simple Model called Token that has a user_id (integer) attribute.
If I do this:
Token.where(:user_id => 1)
it returns a record. But when I do:
Token.delete(:user_id => 1)
it gives me this error:
ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'id.user_id' in 'where clause': DELETE FROM `tokens` WHERE `id`.`user_id` = 1
For some reason it appends id to user_id in SQL statement. Why is it doing that? it works just fine for where clause.
delete expects an id or an array of ids:
Token.delete(1)
Token.delete([2,3,4])
To delete records matching a condition, use delete_all instead:
Token.delete_all(:user_id => 1)
You can also append it to your query:
Token.where(:user_id => 1).delete_all
Both delete all tokens with user_id 1.
What about reading some docs?
http://apidock.com/rails/ActiveRecord/Base/delete/class
delete(id) public
Token.delete_all("tokens.user_id = ?", 1)
Token.delete expects a record ID, not condition hash (documentation).
You want something like this:
Token.where(:user_id => 1).delete_all