grabury
grabury

Reputation: 5559

How to get records created at the current month?

I have a candidate which has_many votes.

I am trying to get the votes of a candidate that were created in the current month?

@candidate.votes.from_this_month

scope :from_this_month, where("created_at > ? AND created_at < ?", Time.now.beginning_of_month, Time.now.end_of_month)

That gives me a PG error: PG::Error: ERROR: column reference \"created_at\" is ambiguous

If I try

scope :from_this_month, where("vote.created_at > ? AND vote.created_at < ?", Time.now.beginning_of_month, Time.now.end_of_month)

I get the following error

PG::Error: ERROR:  missing FROM-clause entry for table "vote"

Upvotes: 10

Views: 7124

Answers (5)

Joseph N.
Joseph N.

Reputation: 2457

From Rails 5 you have a much cleaner syntax. On your votes model add a scope this_month

 scope :this_month, -> { where(created_at: Date.today.all_month) }

You can now query @candidates.votes.this_month

Upvotes: 6

giapnh
giapnh

Reputation: 3258

  scope :this_month, -> { where(created_at: Time.zone.now.beginning_of_month..Time.zone.now.end_of_month) }

and you can call the scope:

Model.this_month

Upvotes: 3

Hardik
Hardik

Reputation: 3895

Correct scope

scope :from_this_month, lambda {where("votes.created_at > ? AND votes.created_at < ?", Time.now.beginning_of_month, Time.now.end_of_month)}

This is because in rails the model names are singular(i.e Vote) and tables created are pural (e.g. votes) by convection

EDIT

This can be written simpler with lambda {where(created_at: Time.now.beginning_of_month..(Time.now.end_of_month))} and we need to use lambda due to the reason given in below comments.

Thanx BroiSatse for reminding :D

Upvotes: 12

bridiver
bridiver

Reputation: 1714

You need to enclose the where in a lamda as well.

scope :from_this_month, lambda { where("votes.created_at > ? AND votes.created_at < ?", Time.now.beginning_of_month, Time.now.end_of_month) }

Otherwise it may appear to work and your tests will all pass, but if your app runs for more than a month you will start to get incorrect results because Time.now is evaluated when the class loads, not when the method is called.

Upvotes: 8

Richard Peck
Richard Peck

Reputation: 76774

You could use an ActiveRecord Association Extension:

#app/models/Candidate.rb
Class Candidate < ActiveRecord::Base
   has_many :votes do
       def from_this_month
           where("created_at > ? AND created_at < ?", Time.now.beginning_of_month, Time.now.end_of_month)
       end
   end
end

This should allow you to call @candidate.votes.from_this_month to return the required conditional data

Upvotes: 1

Related Questions