开发者

rails scope "expires_within"

Hey guys. I have a model, Item, which is set to "expire" in created_at + 100.days. I am trying to create a scope that will return the items which will expire in a supplied time, such as 10.days.

So far I have this:

scope :expires_within, lambda {|time| where("created_at > ?", time)}

So that I could eventually do something like:

Item.expires_within(10.days)

Which would return a collection of items which expire within 10 days.

This isn't right, I just wanted to have a skeleton of what I should have. I can't figure out if it's possible to do this through a scope or not. It seems to me like I would be able to if I had a column in the table called expires_at, but the problem is that I would rather not create such a column becau开发者_运维问答se I want the expiration time, above stated as created_at + 100.days, to be flexible.

I just wanted to see if it would be possible without such a column, or if it can be done but not with a scope, I'd like to hear that possibility as well. If not, I'll go ahead and add it.


from_now would do this:

10.days.from_now

Or dynamically:

scope :expires_within, lambda {|time| where("created_at > ?", time.from_now)}


You could create a scope for...

scope :expires_within_10_days, lambda { where('created at > ?', 90.days.ago) }

...which should fetch all items that were created over 90 days ago, which means they expire within 10 days. Add another condition to exclude already-expired items.

Update: Switched example to a scope, versus regular AR query...


I have come up with a solution I believe. I will continue to test it.

scope :expires_within, lambda {|time| where("created_at < ?", time.from_now - 100.days)}

Basically my original formula to calculate whether something was expired was:

Time.now > created_at + 100.days

Since I want to determine whether something expires within a future time (e.g. 10.days), I add it to the left-hand side:

Time.now + time > created_at + 100.days

Remember, 100.days is how long an item has to live before it expires.

Finally, I solve for created_at so that it's by itself, since that's what the sql query demands, by subtracting 100.days from the other side:

created_at < (Time.now + time) - 100.days

This could be made more concise, as Ryan pointed out, by doing:

created_at < time.from_now - 100.days

Basic math I guess. I'm still pretty dazed from thinking about it too hard, so I will test it a bit to make sure it works as intended. If it does, Item.expires_within(10.days) should return a collection of items which will expire within 10 days (or before).

EDIT: I've refactored this to ignore the items which have already expired. So the new scope looks for the items that have not yet expired and will expire within a specified time frame:

scope :expires_within, lambda {|time| where("created_at BETWEEN ? AND ?", 100.days.ago, time.from_now - 100.days)}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜