marcamillion
marcamillion

Reputation: 33755

How do I create a dynamic scope where I can pass in an object if possible?

I have these two scopes:

  scope :posted_yesterday, -> { where(created_at: (Time.now.midnight - 1.day)..Time.now.midnight)}
  scope :num_posted_yesterday, -> { posted_yesterday.count }  

What I want to happen is, I would love to be able to calculate many versions of posted_yesterday. i.e. posted_num_days_ago(n).

There anyway for me to create dynamic scopes to allow this, or should I just create a method on my Post model?

Upvotes: 1

Views: 981

Answers (3)

Anuja
Anuja

Reputation: 654

Do as follows:

scope :posted_on, -> (day) { where(created_at: day.beginning_of_day..(day + 1.day).beginning_of_day)}
scope :num_posted_on, -> { posted_on.count}

And suppose model name is Post then call it as follows.

Post.posted_on(Date.today - 4.days)

OR (but above is better option)

scope :posted_yesterday, -> (n) { day  = (Time.now - n.days)
   where(created_at: (day - 1.day).beginning_of_day..day.beginning_of_day)
}

And call:

Post.posted_yesterday(4)

Upvotes: 1

Almaron
Almaron

Reputation: 4147

You have 2 options here.

  1. Creating a class method on the Post model, as you suggested. Don't forget to define it as def self.posted_days_ago(n) and use self inside the method to represent the class.

  2. Use a parameter inside a scope. It will look something like this:

    scope :posted_num_days_ago, ->(n=1) {where(created_at: ((Time.now.midnight - n.days)..(Time.now.midnight - (n-1).days)))}
    

Notice the default value I set in this example. You may set it to whatever you need.

Upvotes: 1

6ft Dan
6ft Dan

Reputation: 2435

Scopes are using standard Procs known as lambdas. You should be able to by adding a parameter to you lambda. It would be something like:

scope :posted_num_days_ago -> (days_ago) {
  where(
    created_at: (
      Time.now.midnight - (days_ago + 1).day)
    )..(Time.now.midnight - days_ago.day)
  )
}

This may not be exact. I haven't tested this.

But the idea is to use -> (params) { ... }

Upvotes: 1

Related Questions