User Points System

Hi,

I am currently writing an ROR application which I am looking to add user
points to. I've been looking at Merit for this, but I don't know if it
is going to be right for what I am looking to get out of it. The points
are the main thing, but I may use the badges and rating features in the
future.

The part I'm not sure of is that I want users to be able to “spend”
points on the site at some point in the future.

I'd like users to accumulate a points total for various actions across
the site, but also to have a rolling “last 2 months” total, which could
be “spent”. ie when they have been spent they would be removed from the
last 2 months total but would still be shown in the total points. Also,
as its rolling, if a user gains 10 points on 1st January, those 10
points will drop off on 1st March if not spent before then.

I don't know if I have explained this well, but I don't think this sort
of functionality is available with Merit. Has anyone with experience of
this gem got any ideas as to whether this is possible?

If not, how much of a job would rolling my own points system with the
features above be? I have a feeling this might be a big job… So if I can
use Merit or something similar that would be better.

Any input anyone can give would be appreciated,

Thanks,

J.

You could model the problem by having a User model + many associated Point
models. Point would store the number of points awarded + created_at (+
other data if needed). Spending points would result in creating a Point
model with a negative number of awarded points.

1. Computing the total number of points of a user:

user.points.where('number > 0').sum(:number)

or with a scope:

user.points.awarded.sum(:number)

2. Computing the total number of spendable points:

user.points.awarded.where('created_at > ?', 2.months.ago).sum(:number)

Again, the where part can be expressed as a scope:

user.points.awarded.spendable.sum(:number)

3. Spending points would require a check against currently spendable points:

if points_to_spend <= user.points.awarded.spendable.sum(:number)
  user.points.create!(number: -points_to_spend)
else
  fail("not enough points")
end

You may also define methods like User#total_awarded_points,
User#spendable_points and User#spend_points.

Would this work for you?

Hi Greg,

yeah - I think I have abandoned using a gem for this and will roll my
own. I've had more of a look into it now and it doesn't look like as big
a job as I had imagined..

I think it will be easier to put a "spent" boolean on the point model
though, rather than create negative point objects. We'll see.. Thanks
for the feedback,

J.

Yes, gems often make things more complicated than necessary. Regarding
`spent` - if I earned 10 points and want to spend 2 how would you model
this? I'm not sure whether that's possible in your app but it's a thing to
keep in mind.

Greg Navis wrote in post #1184584:

Yes, gems often make things more complicated than necessary. Regarding
`spent` - if I earned 10 points and want to spend 2 how would you model
this? I'm not sure whether that's possible in your app but it's a thing
to
keep in mind.

Good point - I will probably just not give "change" :slight_smile: