Counting User registration for a day, week, month - ruby-on-rails

I want to count the users that registered on the website on specific periods.
For example:
Today: 5
Yesterday: 7
Over last week: 28
Over last month: 101
I used this stackoveflow question that is somewhat relevant to what I want to do. But when I try to apply it it has several problems in terms of logic for what I try to do.
So what I figured out is that I should use something like:
#lastfivedays = User.where(
'created_at >= :five_days_ago',
:five_days_ago => Time.now - 5.days,
)
But where am I placing this and how do I use it in the view?
Yes I am lost on how I do something like this in Rails as I am new to this. Any guidance, tip will be extremely helpful.

Your query should go in the controller and you can then access the instance variable in the view.
Controller:
#lastfivedays = User.where(
'created_at >= :five_days_ago',
:five_days_ago => 5.days.ago,
).count
View:
Number of users who registered in last 5 days: <%= #lastfivedays %>

I would recommend using ActiveRecord Scopes
You could have something like:
class User < ActiveRecord::Base
...
scope :joined_within_five_days, -> { where('created_at >= :five_days_ago',
:five_days_ago => Time.now - 5.days,) }
...
end
Your controller could then use the approriate one. For example
#users = User.joined_within_five_days

Related

Track daily users signin

So I want to output users that signed in 2 hours ago with the hope I will call it on the front end, and I have a database attribute (created_at)that keeps track of the time you sign in.
What I did was to define a scope to handle that which got nothing from. Here is my code below:
class SignupHistory < ActiveRecord::Base
scope :one_hour_ago, -> { where 'created_at > ?', Time.now - 2.hours.ago }
end
How do I go about showing users that logged in 2 hours ago?
Am I correct to understand that you are trying to find all the records that were created within the last two hours? Then, you can just test against 2.hours.ago without any subtraction operator:
scope :two_hours_ago, -> { where 'created_at > ?', 2.hours.ago }
I think your problem is that you're calling .ago.
You should be able to accomplish what you need by calling:
scope :one_hour_ago, -> { where 'created_at > ?', Time.zone.now - 2.hours }

Rails: Ordering objects created in 3 days

I want to display the hottest posts in 3 days, so this is what I do
#posts = Post.created_in_days(3).order_by_likes.first(4)
For queries:
scope :order_by_likes, -> { order('likes IS NULL, likes DESC') }
scope :created_in_days, ->(number) {where('created_at >= ?', Time.zone.now - number.days)}
This works fine. But the problem is, sometimes there is not enough posts generate in 3 days. Maybe just 3, or even no post at all.
How can I handle this so when #posts created in 3 days is not enough, it would extend the time, till it get enough #posts? (In this case, 4 post needed).
scope :created_in_days, ->(number) do
filtered = where('created_at >= ?', Time.zone.now - number.days)
if filtered.length < 4
order(:created_at => :desc).limit(4) # takes last 4 created
else
filtered
end
end

Find and display nearest date in RoR

I am new to ruby on rails and I'm not sure where to start with this. I have a model for users, and one for projects. Users have many projects, and projects have one user. There is an end_date column in the projects table (as well as a name column).
What I want to do is find the project with the nearest end_date and display it's name and end date on the user's show page.
I tried putting this code in the projects controller, but I do not know if it is working, because I don't know how to access it and display the project name in the view.
def next_deadline(after = DateTime.now, limit = 1)
find(:all, :conditions => ['end_date > ?', after], :limit => limit)
end
Any help would be appreciated. Let me know if more information is needed.
As #Dan mentioned, you do need the :order clause to get the first one, but you should add it to your query and not replace the :conditions (otherwise you'll get the project with the earliest end_date irrespective of your after argument). The way you're defining this method is a bit off though. It should be defined in your Project model (and definitely not the controller) as a class method, or, what I think is a better approach, as a scope. In Rails < 3 (which it seems that you're using):
class Project < ActiveRecord::Base
named_scope :next_deadline, Proc.new { |after = DateTime.now, limit = 1| {:conditions => ['end_date > ?', after], :order => "end_date ASC", :limit => limit} }
...
end
Or in Rails >= 3:
class Project < ActiveRecord::Base
scope :next_deadline, Proc.new { |after = DateTime.now, limit = 1| where('end_date > ?', after).order("end_date ASC").limit(limit) }
...
end
Also, you can always test this kind of code using the Rails console: script/console in Rails < 3, rails c in Rails >= 3.
#projects = Project.find_by_sql("SELECT projects.* FROM projects
JOIN users ON users.id = projects.user_id AND projects.user_id = " + #user.id.to_s + "
WHERE projects.end_date > now()
ORDER BY projects.end_date ASC
LIMIT " + limit)
or
#projects = Project.where(:user_id => #user.id)
.where("end_date > ?", DateTime.now)
.order("end_date ASC")
You want to use :order, not :conditions.
Model.find(:all , :order => "end_date ASC")
Then the first result will be the item with the closest end_date
As Dan said, the condition you wrote won't get the nearest end date, but the dates that are greater than today, or the date passed in as a parameter.
In your User model you could write
def next_deadline_project
self.projects.first
end
as long as you give projects a default scope that orders records by end_date
In order to show information on the view you must set it in an instance variable in the User's controller show method. Instance variables are passed to views and you can access them to display the data.
#project = next_deadline_project
And in your show.html.erb you can use something like:
<%= #project.name %> - <%= #project.end_date %>

how to paginate records from multiple models? (do I need a polymorphic join?)

After quite a bit of searching, I'm still a bit lost. There are a few other similar questions out there that deal with paginating multiple models, but they are either unanswered or they pagainate each model separately.
I need to paginate all records of an Account at once.
class Account
:has_many :emails
:has_many :tasks
:has_many :notes
end
So, I'd like to find the 30 most recent "things" no matter what they are. Is this even possible with the current pagination solutions out there?
Like using some combination of eager loading and Kaminari or will_paginate?
Or, should I first set up a polymorphic join of all these things, called Items. Then paginate the most recent 30 items, then do a lookup of the associated records of those items.
And if so, I'm not really sure what that code should look like. Any suggestions?
Which way is better? (or even possible)
Rails 3.1, Ruby 1.9.2, app not in production.
with will_paginate :
#records = #do your work and fetch array of records you want to paginate ( various types )
then do the following :
current_page = params[:page] || 1
per_page = 10
#records = WillPaginate::Collection.create(current_page, per_page, records.size) do |pager|
pager.replace(#records)
end
then in your view :
<%=will_paginate #records%>
Good question... I'm not sure of a "good" solution, but you could do a hacky one in ruby:
You'd need to first fetch out the 30 latest of each type of "thing", and put them into an array, indexed by created_at, then sort that array by created_at and take the top 30.
A totally non-refactored start might be something like:
emails = Account.emails.all(:limit => 30, :order => :created_at)
tasks = Account.tasks.all(:limit => 30, :order => :created_at)
notes = Account.notes.all(:limit => 30, :order => :created_at)
thing_array = (emails + tasks + notes).map {|thing| [thing.created_at, thing] }
# sort by the first item of each array (== the date)
thing_array_sorted = thing_array.sort_by {|a,b| a[0] <=> b[0] }
# then just grab the top thirty
things_to_show = thing_array_sorted.slice(0,30)
Note: not tested, could be full of bugs... ;)
emails = account.emails
tasks = account.tasks
notes = account.notes
#records = [emails + tasks + notes].flatten.sort_by(&:updated_at).reverse
#records = WillPaginate::Collection.create(params[:page] || 1, 30, #records.size) do |pager|
pager.replace(#records)
end
Thats it... :)

Get number of rows associated model has with complicated join

I'm new to rails and am unsure of the best way of doing this. I have a User which "has many" Events. I want to be able to go user.active? in a view which will display whether the user has one or more associated Events created in the last 5 minutes.
I know the syntax isn't correct but this is what I've got so far:
def active?
find(:conditions => {:events => ["created_at >= ?", DateTime.now - 5.minute]}).count > 0
end
You can just do a find on the events collection:
def active?
events.where('created_at >= ?', 5.minutes.ago).count > 0
end

Resources