Count from associate table - ruby-on-rails

I want to have some stats from my app, User can publish post that I call Idee, and I want to know how many user have publish at least one idee.
I'm assuming that should be something like:
#total_user_active = User.where(idee.size >= 1).count
But this doesn't work.
It's user who is in table idee so maybe I should count how much unique user_id are in this column but how?

You can do the following:
#total_user_active = Idee.distinct.count(:user)

Related

How to get only one db record from couple of same?

I have records in the db table that can differ only by ids and creation/update time. How can I get only the unique records?
I tried this way, but it didn't work:
msg_to_user = user.messages.new_messages.uniq
I'll explain. User can follow post manually but also same post can be followed by user automatically. So I want to send only one message if post have been commented by someone.
1747 test message TamadaTours 12 new 2016-01-29 06:14:04.736869 2016-01-29 06:48:55.948529 32964382
1748 test message TamadaTours 12 new 2016-01-29 06:14:04.741184 2016-01-29 06:48:55.951371 32964382
All records in the database are uniq (at least because of ID column, which by default has a uniq constraint).
You would want to use DISTINCT:
Model.select('DISTINCT column_name1, column_name2')
Your question is flawed...
The point of having an id... otherwise known as primary_key... in a relational database is so that you can actively identify the unique records you want:
A primary key uniquely specifies a tuple within a table. In order for an attribute to be a good primary key it must not repeat
When you write... "How can I get only the unique records" ... the answer is to pull only the records based on their id.
If you refine your question to what you really want...
I want to send only one message if post have been commented by someone
--
In other words, you want to pull a collection of unique user_ids (no duplicates), to which you can send new messages?
To do this, you can use...
#recipients = Message.select(:user_id).distinct #-> all unique user_ids
If you're trying to pull the "new" messages for a user, but only show the first (if they're the same), you'll want to use something like the following:
#msg_to_user = user.messages.new_messages.uniq(:title)
Ref
A better pattern to implement would be to validate the uniqueness of new messages:
#app/models/message.rb
class Message < ActiveRecord::Base
validates :user_id, uniqueness: { scope: :message_id } #-> replace message_id with other unique identifier
end
This would ensure only one new message is present for a user.
you can also use group by in your query like this
Model.all.group("column_name")
One way to extract the data but get rid of the ORM context.
# maps every record to hash, remove the ID entry and then removes duplicates
msg_to_user = user.messages.new_messages.attributes.map { |e| e.except('ID') }.uniq

find user vote count for specific voteable (thumbs_up gem)

I'm using this gem and I would like to get a user's vote count for posts
https://github.com/bouchard/thumbs_up/blob/master/lib/acts_as_voter.rb
However when I do
#user.vote_count
It returns the user's vote count for everything I have comments, photos, etc.
I want to do something like #user.vote_count.where('voteable_type = Micropost') but obviously that doesn't make any sense
Vote.find_by_sql("SELECT COUNT(*) FROM votes WHERE votes.voter_id = #{#user.id} AND votes.voter_type = 'User' AND votes.voteable_type = 'Micropost'").count
probably not the best to use SQL but it works

Count current users on the page

I'm trying to count current viewers on the particular page. I need this count to be stored in the DB. The main trouble is to clean up after user leaves the page.
Users are anonymous. Every active user sends AJAX-request every 5 seconds.
What's the best algorithm to do that? Any suggestions?
UPD: I'm trying to reduce amount of queries to the DB, so, I think, I don't really need to store that count in the DB while I can access it other way from the code.
Don't even think about storing this in database, your app will be incredibly slowed down.
So use Cache for this kind of operation.
To count the number of people, I'd say:
assign a random ID to each anonymous user and store it in his session
send the ID within your ajax call
store an Array of Hashes in cache with [{ :user_id, :latest_ping }, {} ] (create a cache var for each page)
delete the elements of the array which appear to be too old
you've your solution: number of users = nb of elements in the array
If you store the users in the database somehow, you could store a last_seen_at field in the users table, and update that with Time.now for every AJAX request that user sends.
To display how many users you currently have, you can just perform a query such as:
#user_count = User.where("last_seen_at < ?", 5.seconds.ago).count
If you want to clean up old users, I suggest that you run some kind of cron job, or use the whenever gem, or something like that, to periodically delete all users that haven't been seen for some time.
I would suggest you create a model that contains a unique key (cookie-id or something) that you save or update with every AJAX heartbeat request.
You then have a session controller that could look like this:
def create
ActiveUser.where(:cookie => params[:id]) || ActiveUser.new
ActiveUser.cookie = prams[:id]
ActiveUser.timestamp = Time.now
ActiveUser.save
end
Your number of active users is then simply a SELECT COUNT(*) FROM ActiveUsers WHERE timestamp > NOW() - 5 or something like that.
Martin Frost is on the right track. There's the #touch method to update last_seen_at: user.touch(:last_seen_at)
But it would be even more efficient to just update the user without having to fetch the model from the database:
> User.update_all({:last_seen_at => Time.now}, {:id => params[:user_id})
SQL (3.1ms) UPDATE "users" SET "last_seen_at" = '2011-11-17 12:37:46.863660' WHERE "users"."id" = 27
=> 1

How to select all of a unique attribute

I would like to find all the Records that have unique email addresses. I am trying to perform this :
#uniq_referrals = []
CardReferral.all.select{|a| #uniq_referrals << a.email}
#referral_count = #uniq_referrals.uniq.each{|a|CardReferral.find_by_email(a)}
But I would like to do it in a single call. Is that possible?
You can use:
CardReferral.select("distinct(email), other_field_you_need")
where other_field_you_need it's a list of field name you need to use from the objects you get from ActiveRecord.
To get the count of unique email record you can use:
CardReferral.count("distinct(email)")
I would like to find all the Records that have unique email addresses. I am trying to perform this :
#uniq_referrals = []
CardReferral.all.select{|a| #uniq_referrals << a.email}
#referral_count = #uniq_referrals.uniq.each{|a|CardReferral.find_by_email(a)}
But I would like to do it in a single call. Is that possible?
I think that it would help you:
Model.group("email")
when we group all the record by email id then you will find all the record that have uniq email. if some record have same id then you will get first record.
please prefer to image for more understanding.
If you could not get yet, then i will explain elaborate more.

Order two #variables together by date

I have a messaging system with two tables: Message and MessageCopy, where each time a message is sent it generates a message_copy for each recipient (with info like read, saved, deleted, etc.).
I would like to show a 'conversation' with sent and received messages for my user, and I would like to splice together sent and received messages, ordered by created_at.
Here are my two currently separated relations.
#sentmessages = Message.where("author_id = ? AND project_id = ?", current_user.id, #project.id).order("created_at DESC")
#receivedmessages = MessageCopy.where("recipient_id = ? AND project_id = ?", current_user.id, #project.id).order("created_at DESC")
I'd like to put these together into one relation using Rails if possible rather than MySQL. Thanks!
I hope I understand correctly - you want a single variable that stores these objects ordered by date.
(#sentmessages + #receivedmessages).sort_by(&:created_at).reverse

Resources