recognition 0.3.8 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +4 -3
- data/lib/recognition.rb +5 -2
- data/lib/recognition/controllers/recognizer.rb +13 -0
- data/lib/recognition/database.rb +19 -99
- data/lib/recognition/extensions/action_controller.rb +21 -0
- data/lib/recognition/extensions/active_record.rb +72 -0
- data/lib/recognition/logger.rb +22 -0
- data/lib/recognition/{activerecord/voucher.rb → models/gift.rb} +16 -13
- data/lib/recognition/models/recognizable.rb +31 -0
- data/lib/recognition/{activerecord/model.rb → models/recognizer.rb} +2 -2
- data/lib/recognition/models/voucher.rb +82 -0
- data/lib/recognition/parser.rb +62 -0
- data/lib/recognition/rails/engine.rb +12 -0
- data/lib/recognition/rails/railtie.rb +16 -0
- data/lib/recognition/version.rb +1 -1
- metadata +15 -13
- data/lib/recognition/action_controller_extension.rb +0 -31
- data/lib/recognition/active_record_extension.rb +0 -72
- data/lib/recognition/activerecord/recognizable.rb +0 -26
- data/lib/recognition/condition.rb +0 -12
- data/lib/recognition/engine.rb +0 -10
- data/lib/recognition/railtie.rb +0 -21
- data/lib/recognition/transaction.rb +0 -11
data/README.md
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
# Recognition
|
2
|
+
[](https://travis-ci.org/rayasocialmedia/recognition)
|
2
3
|
|
3
4
|
A fully-fledged reward system for Rails 3.1+.
|
4
5
|
|
5
6
|
## Features
|
6
7
|
|
7
|
-
* Reward users with points for any model method or
|
8
|
+
* Reward users with points for any model method, ActiveRecord crud or even controller methods.
|
8
9
|
* Create vouchers that users can redeem for points.
|
9
10
|
|
10
11
|
## Links
|
11
12
|
|
12
13
|
* [Installation](#Installation)
|
13
|
-
* [Usage](#
|
14
|
-
* [Examples](#
|
14
|
+
* [Usage](#usage)
|
15
|
+
* [Examples](#example)
|
15
16
|
* [Wiki](https://github.com/rayasocialmedia/recognition/wiki)
|
16
17
|
* [Code Documentation](http://rubydoc.info/gems/recognition/frames)
|
17
18
|
* [Changelog](https://raw.github.com/rayasocialmedia/recognition/master/CHANGELOG.txt)
|
data/lib/recognition.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
|
-
require "recognition/engine"
|
2
1
|
require "recognition/version"
|
3
|
-
require "recognition/
|
2
|
+
require "recognition/logger"
|
3
|
+
require "recognition/rails/engine"
|
4
|
+
require "recognition/rails/railtie"
|
4
5
|
require "redis"
|
5
6
|
|
6
7
|
module Recognition
|
8
|
+
extend Recognition::Logger
|
9
|
+
|
7
10
|
mattr_accessor :redis
|
8
11
|
# Redis Db connection parameters
|
9
12
|
@@redis = 'localhost:6378'
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Recognition
|
2
|
+
module Controllers
|
3
|
+
module Recognizer
|
4
|
+
def recognize_actions
|
5
|
+
action = params[:action].to_sym
|
6
|
+
self.class.recognitions[action][:proc_params] = params
|
7
|
+
if self.class.recognitions.keys.include? action
|
8
|
+
Recognition::Database.update_points self, action, self.class.recognitions[action]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/recognition/database.rb
CHANGED
@@ -1,98 +1,54 @@
|
|
1
|
-
require
|
1
|
+
require 'recognition/parser'
|
2
2
|
|
3
3
|
module Recognition
|
4
4
|
# Handle all Transactions and logging to Redis
|
5
5
|
module Database
|
6
6
|
def self.log id, amount, bucket, code = nil
|
7
7
|
hash = Time.now.to_f.to_s
|
8
|
+
Recognition.log :transaction, "hash:'#{hash}' user:'#{id}' amount:'#{amount}' bucket:'#{bucket}'"
|
8
9
|
Recognition.backend.multi do
|
9
10
|
Recognition.backend.hincrby "recognition:user:#{ id }:counters", 'points', amount
|
10
11
|
Recognition.backend.hincrby "recognition:user:#{ id }:counters", bucket, amount
|
11
12
|
Recognition.backend.zadd "recognition:user:#{ id }:transactions", hash, { hash: hash, amount: amount, bucket: bucket, datetime: DateTime.now.to_s }.to_json
|
12
13
|
Recognition.backend.zadd 'recognition:transactions', hash, { hash: hash, id: id, amount: amount, bucket: bucket, datetime: DateTime.now.to_s }.to_json
|
13
14
|
unless code.nil?
|
14
|
-
Recognition.backend.zadd "recognition:
|
15
|
+
Recognition.backend.zadd "recognition:#{ code[:type] }:#{ code[:code] }:transactions", hash, { hash: hash, id: id, bucket: bucket, datetime: DateTime.now.to_s }.to_json
|
15
16
|
end
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
19
20
|
def self.get key
|
20
|
-
Recognition.backend.get key
|
21
|
+
Recognition.backend.get "recognition:#{key}"
|
21
22
|
end
|
22
23
|
|
23
|
-
def self.
|
24
|
-
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.get_user_counter id, counter
|
28
|
-
counter = Recognition.backend.hget("recognition:user:#{ id }:counters", counter)
|
29
|
-
counter.to_i
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.get_user_transactions id, page = 0, per = 20
|
33
|
-
start = page * per
|
34
|
-
stop = (1 + page) * per
|
35
|
-
keypart = "user:#{ id }"
|
36
|
-
self.get_transactions keypart, start, stop
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.get_voucher_transactions code, page = 0, per = 20
|
40
|
-
start = page * per
|
41
|
-
stop = (1 + page) * per
|
42
|
-
keypart = "voucher:#{ code }"
|
43
|
-
self.get_transactions keypart, start, stop
|
24
|
+
def self.get_counter hash, key
|
25
|
+
Recognition.backend.hget("recognition:#{hash}", key).to_i
|
44
26
|
end
|
45
27
|
|
46
28
|
def self.update_points object, action, condition
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
bucket = condition[:bucket]
|
51
|
-
end
|
52
|
-
user = parse_user(object, condition)
|
29
|
+
Recognition.log 'foo', condition.to_s
|
30
|
+
condition[:bucket] ||= "#{ object.class.to_s.camelize }:#{ action }"
|
31
|
+
user = Recognition::Parser.parse_recognizable(object, condition[:recognizable], condition[:proc_params])
|
53
32
|
if condition[:amount].nil? && condition[:gain].nil? && condition[:loss].nil?
|
33
|
+
Recognition.log 'validation', "Unable to determine points: no 'amount', 'gain' or 'loss' specified"
|
54
34
|
false
|
55
35
|
else
|
56
|
-
total = parse_amount(condition[:amount], object) + parse_amount(condition[:gain], object) - parse_amount(condition[:loss], object)
|
57
|
-
ground_total = user.recognition_counter(bucket) + total
|
36
|
+
total = Recognition::Parser.parse_amount(condition[:amount], object, condition[:proc_params]) + Recognition::Parser.parse_amount(condition[:gain], object, condition[:proc_params]) - Recognition::Parser.parse_amount(condition[:loss], object, condition[:proc_params])
|
37
|
+
ground_total = user.recognition_counter(condition[:bucket]) + total
|
58
38
|
if condition[:maximum].nil? || ground_total <= condition[:maximum]
|
59
|
-
|
39
|
+
log(user.id, total.to_i, condition[:bucket])
|
40
|
+
else
|
41
|
+
Recognition.log 'validation', "Unable to add points: bucket maximum reached for bucket '#{condition[:bucket]}'"
|
60
42
|
end
|
61
43
|
end
|
62
44
|
end
|
63
45
|
|
64
|
-
def self.
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
def self.get_user_voucher id, code
|
70
|
-
bucket = "Voucher:redeem##{ code }"
|
71
|
-
Database.get_user_counter id, bucket
|
72
|
-
end
|
73
|
-
|
74
|
-
def self.parse_voucher_part part, object
|
75
|
-
case part.class.to_s
|
76
|
-
when 'String'
|
77
|
-
value = part
|
78
|
-
when 'Integer'
|
79
|
-
value = part.to_s
|
80
|
-
when 'Fixnum'
|
81
|
-
value = part.to_s
|
82
|
-
when 'Symbol'
|
83
|
-
value = object.send(part).to_s
|
84
|
-
when 'Proc'
|
85
|
-
value = part.call(object).to_s
|
86
|
-
when 'NilClass'
|
87
|
-
# Do not complain about nil amounts
|
88
|
-
else
|
89
|
-
raise ArgumentError, "type mismatch for voucher part: expecting 'Integer', 'Fixnum', 'Symbol' or 'Proc' but got '#{ amount.class.to_s }' instead."
|
90
|
-
end
|
91
|
-
value || ''
|
46
|
+
def self.redeem id, bucket, type, code, value
|
47
|
+
certificate = { type: type, code: code }
|
48
|
+
Recognition.log type, "redeeming #{type}:#{code} for user: #{id}"
|
49
|
+
log id, value, bucket, certificate
|
92
50
|
end
|
93
51
|
|
94
|
-
private
|
95
|
-
|
96
52
|
def self.get_transactions keypart, start, stop
|
97
53
|
transactions = []
|
98
54
|
range = Recognition.backend.zrange "recognition:#{ keypart }:transactions", start, stop
|
@@ -101,41 +57,5 @@ module Recognition
|
|
101
57
|
end
|
102
58
|
transactions
|
103
59
|
end
|
104
|
-
|
105
|
-
def self.parse_user object, condition
|
106
|
-
if condition[:recognizable].nil?
|
107
|
-
user = object
|
108
|
-
else
|
109
|
-
case condition[:recognizable].class.to_s
|
110
|
-
when 'Symbol'
|
111
|
-
user = object.send(condition[:recognizable])
|
112
|
-
when 'String'
|
113
|
-
user = object.send(condition[:recognizable].to_sym)
|
114
|
-
when 'Proc'
|
115
|
-
user = object.call(condition[:proc_params])
|
116
|
-
else
|
117
|
-
user = condition[:recognizable]
|
118
|
-
end
|
119
|
-
end
|
120
|
-
user
|
121
|
-
end
|
122
|
-
|
123
|
-
def self.parse_amount amount, object
|
124
|
-
case amount.class.to_s
|
125
|
-
when 'Integer'
|
126
|
-
value = amount
|
127
|
-
when 'Fixnum'
|
128
|
-
value = amount
|
129
|
-
when 'Symbol'
|
130
|
-
value = object.send(amount)
|
131
|
-
when 'Proc'
|
132
|
-
value = amount.call(object)
|
133
|
-
when 'NilClass'
|
134
|
-
# Do not complain about nil amounts
|
135
|
-
else
|
136
|
-
raise ArgumentError, "type mismatch for amount: expecting 'Integer', 'Fixnum', 'Symbol' or 'Proc' but got '#{ amount.class.to_s }' instead."
|
137
|
-
end
|
138
|
-
value || 0
|
139
|
-
end
|
140
60
|
end
|
141
61
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Recognition
|
2
|
+
module Extensions
|
3
|
+
# Extending ActionController
|
4
|
+
module ActionController
|
5
|
+
def self.included(base)
|
6
|
+
base.extend ClassMethods
|
7
|
+
base.class_attribute :recognitions
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def recognize recognizable, condition
|
12
|
+
require "recognition/controllers/recognizer"
|
13
|
+
include Recognition::Controllers::Recognizer
|
14
|
+
self.recognitions ||= {}
|
15
|
+
self.recognitions[condition[:for]] = { recognizable: recognizable, amount: condition[:amount], gain: condition[:gain], loss: condition[:loss], maximum: condition[:maximum] }
|
16
|
+
after_filter :recognize_actions
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Recognition
|
2
|
+
module Extensions
|
3
|
+
module ActiveRecord
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
base.class_attribute :recognitions
|
7
|
+
base.class_attribute :recognizable
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
# to be called from user model
|
12
|
+
def acts_as_recognizable options = {}
|
13
|
+
require "recognition/models/recognizable"
|
14
|
+
include Recognition::Models::Recognizable
|
15
|
+
self.recognizable = true
|
16
|
+
self.recognitions ||= {}
|
17
|
+
self.recognitions[:initial] = {
|
18
|
+
amount: options[:initial]
|
19
|
+
}
|
20
|
+
after_save :add_initial_points
|
21
|
+
end
|
22
|
+
|
23
|
+
# to be called from other models
|
24
|
+
def recognize recognizable, condition
|
25
|
+
require "recognition/models/recognizer"
|
26
|
+
include Recognition::Models::Recognizer
|
27
|
+
self.recognitions ||= {}
|
28
|
+
self.recognitions[condition[:for]] = {
|
29
|
+
recognizable: recognizable,
|
30
|
+
bucket: condition[:group],
|
31
|
+
gain: condition[:gain],
|
32
|
+
loss: condition[:loss],
|
33
|
+
maximum: condition[:maximum]
|
34
|
+
}
|
35
|
+
# Due to the lack of ActiveRecord before_filter,
|
36
|
+
# we will have to alias the original method in order to intercept
|
37
|
+
if [:create, :update, :destroy].include? condition[:for]
|
38
|
+
include ActiveModel::Dirty
|
39
|
+
else
|
40
|
+
method = condition[:for]
|
41
|
+
define_method "#{method}_with_recognition" do |*args|
|
42
|
+
if self.send("#{method}_without_recognition", *args)
|
43
|
+
Recognition::Database.update_points self, condition[:for], self.class.recognitions[condition[:for]]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
alias_method_chain method, 'recognition'
|
47
|
+
end
|
48
|
+
# For actions that can be intercepted using ActiveRecord callbacks
|
49
|
+
before_destroy :recognize_destroying
|
50
|
+
after_save :recognize_updating
|
51
|
+
# We use after_save for creation to make sure all associations
|
52
|
+
# have been persisted
|
53
|
+
after_save :recognize_creating
|
54
|
+
end
|
55
|
+
|
56
|
+
# to be called from user-model
|
57
|
+
def acts_as_voucher options = {}
|
58
|
+
require "recognition/models/voucher"
|
59
|
+
include Recognition::Models::Voucher
|
60
|
+
self.recognitions = options
|
61
|
+
cattr_accessor :voucher_validators
|
62
|
+
def self.validates_voucher_redmeption validators
|
63
|
+
self.voucher_validators ||= []
|
64
|
+
self.voucher_validators << validators
|
65
|
+
self.voucher_validators.flatten!
|
66
|
+
end
|
67
|
+
before_create :regenerate_code
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module Recognition
|
4
|
+
module Logger
|
5
|
+
def log key, message
|
6
|
+
logger.info("[recognition] [#{key}] #{message}") if logging?
|
7
|
+
end
|
8
|
+
|
9
|
+
def logger #:nodoc:
|
10
|
+
@logger ||= ::Logger.new(STDOUT)
|
11
|
+
end
|
12
|
+
|
13
|
+
def logger=(logger)
|
14
|
+
@logger = logger
|
15
|
+
end
|
16
|
+
|
17
|
+
def logging? #:nodoc:
|
18
|
+
# TODO: Add an option to toggle logging
|
19
|
+
false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module Recognition
|
2
|
-
module
|
3
|
-
module
|
2
|
+
module Models
|
3
|
+
module Gift
|
4
4
|
def regenerate_code
|
5
|
-
prefix = Recognition::Database.
|
6
|
-
suffix = Recognition::Database.
|
5
|
+
prefix = Recognition::Database.parse_code_part(self.class.recognitions[:prefix], self)
|
6
|
+
suffix = Recognition::Database.parse_code_part(self.class.recognitions[:suffix], self)
|
7
7
|
l = (self.class.recognitions[:code_length] - (prefix.length + suffix.length)) || 10
|
8
8
|
dict = [('a'..'z'),('A'..'Z'),(0..9)].map{|i| i.to_a}.flatten
|
9
9
|
code = (1..l).map{ dict[rand(dict.length)] }.prepend(prefix).append(suffix).join
|
@@ -21,14 +21,14 @@ module Recognition
|
|
21
21
|
if defined? self.amount
|
22
22
|
if self.redeemable? recognizable
|
23
23
|
# Call custom validators
|
24
|
-
if defined? self.class.
|
25
|
-
self.class.
|
24
|
+
if defined? self.class.gift_validators
|
25
|
+
self.class.gift_validators.each do |validator|
|
26
26
|
# quit if any validator returned false
|
27
27
|
return if send(validator) == false
|
28
28
|
end
|
29
29
|
end
|
30
30
|
# If all went well:
|
31
|
-
Database.
|
31
|
+
Database.redeem_gift recognizable.id, self.code, self.amount
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
@@ -36,14 +36,14 @@ module Recognition
|
|
36
36
|
def redeemable? recognizable
|
37
37
|
# default: not redeemable
|
38
38
|
pass = false
|
39
|
-
# only check if the
|
39
|
+
# only check if the gift did not expire
|
40
40
|
unless expired?
|
41
|
-
# has the
|
42
|
-
if Database.
|
43
|
-
# has the
|
44
|
-
if Database.
|
41
|
+
# has the gift ever been redeemed?
|
42
|
+
if Database.get_gift_transactions(self.code).any?
|
43
|
+
# has the gift ever been redeemed by this user?
|
44
|
+
if Database.get_user_gift(recognizable.id, code) != 0
|
45
45
|
pass = false
|
46
|
-
# is the
|
46
|
+
# is the gift reusable?
|
47
47
|
elsif defined?(self.reusable?) && self.reusable?
|
48
48
|
pass = true
|
49
49
|
end
|
@@ -57,6 +57,9 @@ module Recognition
|
|
57
57
|
def expired?
|
58
58
|
defined?(self.expires_at) && self.expires_at.present? && self.expires_at < DateTime.now
|
59
59
|
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
60
63
|
end
|
61
64
|
end
|
62
65
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Recognition
|
2
|
+
module Models
|
3
|
+
module Recognizable
|
4
|
+
# Determine user current balance of points
|
5
|
+
def points
|
6
|
+
recognition_counter 'points'
|
7
|
+
end
|
8
|
+
|
9
|
+
def recognition_counter bucket
|
10
|
+
Recognition::Database.get_counter "user:#{ self.id }:counters", bucket
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_initial_points
|
14
|
+
amount = self.class.recognitions[:initial][:amount]
|
15
|
+
update_points amount, :initial
|
16
|
+
end
|
17
|
+
|
18
|
+
def update_points amount, bucket
|
19
|
+
require 'recognition/database'
|
20
|
+
Recognition::Database.log(self.id, amount.to_i, bucket)
|
21
|
+
end
|
22
|
+
|
23
|
+
def transactions page = 0, per = 20
|
24
|
+
start = page * per
|
25
|
+
stop = (1 + page) * per
|
26
|
+
keypart = "user:#{ self.id }"
|
27
|
+
Recognition::Database.get_transactions keypart, start, stop
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Recognition
|
2
|
-
module
|
3
|
-
module
|
2
|
+
module Models
|
3
|
+
module Recognizer
|
4
4
|
def recognize_creating
|
5
5
|
if self.id_changed? # Unless we are creating
|
6
6
|
Database.update_points self, :create, self.class.recognitions[:create] unless self.class.recognitions[:create].nil?
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Recognition
|
2
|
+
module Models
|
3
|
+
module Voucher
|
4
|
+
def regenerate_code
|
5
|
+
prefix = Recognition::Parser.parse_code_part(self.class.recognitions[:prefix], self)
|
6
|
+
suffix = Recognition::Parser.parse_code_part(self.class.recognitions[:suffix], self)
|
7
|
+
l = (self.class.recognitions[:code_length] - (prefix.length + suffix.length)) || 10
|
8
|
+
dict = [('a'..'z'),('A'..'Z'),(0..9)].map{|i| i.to_a}.flatten
|
9
|
+
code = (1..l).map{ dict[rand(dict.length)] }.prepend(prefix).append(suffix).join
|
10
|
+
# Prevent code collision at all costs
|
11
|
+
if self.class.to_s.constantize.find_all_by_code(code).any?
|
12
|
+
regenerate_code
|
13
|
+
else
|
14
|
+
self.code = code
|
15
|
+
self
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def redeem recognizable
|
20
|
+
# Make sure we have an amount beforehand
|
21
|
+
if defined? self.amount
|
22
|
+
if self.redeemable? recognizable
|
23
|
+
# Call custom validators
|
24
|
+
if defined? self.class.voucher_validators
|
25
|
+
self.class.voucher_validators.each do |validator|
|
26
|
+
# quit if any validator returned false
|
27
|
+
if send(validator) == false
|
28
|
+
Recognition.log :voucher, "validation error for voucher:#{self.id}"
|
29
|
+
return
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
# If all went well:
|
34
|
+
Recognition::Database.redeem recognizable.id, bucket, 'voucher', self.code, amount.to_i
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def redeemable? recognizable
|
40
|
+
# default: not redeemable
|
41
|
+
pass = false
|
42
|
+
# only check if the voucher did not expire
|
43
|
+
unless expired?
|
44
|
+
# has the voucher ever been redeemed?
|
45
|
+
if transactions.any?
|
46
|
+
# has the voucher ever been redeemed by this user?
|
47
|
+
if get_user_voucher(recognizable.id) != 0
|
48
|
+
pass = false
|
49
|
+
# is the voucher reusable?
|
50
|
+
elsif defined?(self.reusable?) && self.reusable?
|
51
|
+
pass = true
|
52
|
+
end
|
53
|
+
else
|
54
|
+
pass = true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
pass
|
58
|
+
end
|
59
|
+
|
60
|
+
def expired?
|
61
|
+
defined?(self.expires_at) && self.expires_at.present? && self.expires_at < DateTime.now
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def bucket
|
67
|
+
"voucher:#{ self.code }"
|
68
|
+
end
|
69
|
+
|
70
|
+
def get_user_voucher id
|
71
|
+
Recognition::Database.get_counter "user:#{id}", bucket
|
72
|
+
end
|
73
|
+
|
74
|
+
def transactions page = 0, per = 20
|
75
|
+
start = page * per
|
76
|
+
stop = (1 + page) * per
|
77
|
+
Recognition::Database.get_transactions bucket, start, stop
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Recognition
|
2
|
+
module Parser
|
3
|
+
def self.parse_recognizable object, recognizable, proc_params = nil
|
4
|
+
if recognizable.nil?
|
5
|
+
user = object
|
6
|
+
else
|
7
|
+
case recognizable.class.to_s
|
8
|
+
when 'Symbol'
|
9
|
+
user = object.send(recognizable)
|
10
|
+
when 'String'
|
11
|
+
user = object.send(recognizable.to_sym)
|
12
|
+
when 'Proc'
|
13
|
+
params = proc_params || object
|
14
|
+
user = recognizable.call(params)
|
15
|
+
else
|
16
|
+
user = recognizable
|
17
|
+
end
|
18
|
+
end
|
19
|
+
user
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.parse_amount amount, object, proc_params = nil
|
23
|
+
case amount.class.to_s
|
24
|
+
when 'Integer'
|
25
|
+
value = amount
|
26
|
+
when 'Fixnum'
|
27
|
+
value = amount
|
28
|
+
when 'Symbol'
|
29
|
+
value = object.send(amount)
|
30
|
+
when 'Proc'
|
31
|
+
params = proc_params || object
|
32
|
+
value = amount.call(params)
|
33
|
+
when 'NilClass'
|
34
|
+
# Do not complain about nil amounts
|
35
|
+
else
|
36
|
+
raise ArgumentError, "type mismatch for amount: expecting 'Integer', 'Fixnum', 'Symbol' or 'Proc' but got '#{ amount.class.to_s }' instead."
|
37
|
+
end
|
38
|
+
value || 0
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.parse_code_part part, object
|
42
|
+
case part.class.to_s
|
43
|
+
when 'String'
|
44
|
+
value = part
|
45
|
+
when 'Integer'
|
46
|
+
value = part.to_s
|
47
|
+
when 'Fixnum'
|
48
|
+
value = part.to_s
|
49
|
+
when 'Symbol'
|
50
|
+
value = object.send(part).to_s
|
51
|
+
when 'Proc'
|
52
|
+
value = part.call(object).to_s
|
53
|
+
when 'NilClass'
|
54
|
+
# Do not complain about nil amounts
|
55
|
+
else
|
56
|
+
raise ArgumentError, "type mismatch for voucher part: expecting 'Integer', 'Fixnum', 'Symbol' or 'Proc' but got '#{ amount.class.to_s }' instead."
|
57
|
+
end
|
58
|
+
value || ''
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Recognition
|
2
|
+
module Rails
|
3
|
+
class Engine < ::Rails::Engine
|
4
|
+
config.generators do |g|
|
5
|
+
g.test_framework :rspec, :fixture => false
|
6
|
+
g.fixture_replacement :factory_girl, :dir => 'spec/factories'
|
7
|
+
g.assets false
|
8
|
+
g.helper false
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "recognition/extensions/active_record"
|
2
|
+
require "recognition/extensions/action_controller"
|
3
|
+
require "rails"
|
4
|
+
|
5
|
+
module Recognition
|
6
|
+
class Railtie < ::Rails::Railtie
|
7
|
+
initializer 'recognition.initialize' do
|
8
|
+
ActiveSupport.on_load(:active_record) do
|
9
|
+
ActiveRecord::Base.send :include, Recognition::Extensions::ActiveRecord
|
10
|
+
end
|
11
|
+
ActiveSupport.on_load(:action_controller) do
|
12
|
+
ActionController::Base.send(:include, Recognition::Extensions::ActionController)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/recognition/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: recognition
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-05-
|
12
|
+
date: 2013-05-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -150,17 +150,19 @@ files:
|
|
150
150
|
- lib/generators/recognition/templates/recognition.rb
|
151
151
|
- lib/generators/recognition/templates/recognition.yml
|
152
152
|
- lib/generators/recognition/voucher_generator.rb
|
153
|
-
- lib/recognition/action_controller_extension.rb
|
154
|
-
- lib/recognition/active_record_extension.rb
|
155
|
-
- lib/recognition/activerecord/model.rb
|
156
|
-
- lib/recognition/activerecord/recognizable.rb
|
157
|
-
- lib/recognition/activerecord/voucher.rb
|
158
153
|
- lib/recognition/backend.rb
|
159
|
-
- lib/recognition/
|
154
|
+
- lib/recognition/controllers/recognizer.rb
|
160
155
|
- lib/recognition/database.rb
|
161
|
-
- lib/recognition/
|
162
|
-
- lib/recognition/
|
163
|
-
- lib/recognition/
|
156
|
+
- lib/recognition/extensions/action_controller.rb
|
157
|
+
- lib/recognition/extensions/active_record.rb
|
158
|
+
- lib/recognition/logger.rb
|
159
|
+
- lib/recognition/models/gift.rb
|
160
|
+
- lib/recognition/models/recognizable.rb
|
161
|
+
- lib/recognition/models/recognizer.rb
|
162
|
+
- lib/recognition/models/voucher.rb
|
163
|
+
- lib/recognition/parser.rb
|
164
|
+
- lib/recognition/rails/engine.rb
|
165
|
+
- lib/recognition/rails/railtie.rb
|
164
166
|
- lib/recognition/version.rb
|
165
167
|
- lib/recognition.rb
|
166
168
|
- lib/tasks/recognition_tasks.rake
|
@@ -181,7 +183,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
181
183
|
version: '0'
|
182
184
|
segments:
|
183
185
|
- 0
|
184
|
-
hash:
|
186
|
+
hash: -4080240542959513995
|
185
187
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
186
188
|
none: false
|
187
189
|
requirements:
|
@@ -190,7 +192,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
190
192
|
version: '0'
|
191
193
|
segments:
|
192
194
|
- 0
|
193
|
-
hash:
|
195
|
+
hash: -4080240542959513995
|
194
196
|
requirements: []
|
195
197
|
rubyforge_project:
|
196
198
|
rubygems_version: 1.8.23
|
@@ -1,31 +0,0 @@
|
|
1
|
-
require "recognition/database"
|
2
|
-
|
3
|
-
module Recognition
|
4
|
-
# Extending ActiveRecord
|
5
|
-
module ActionControllerExtension
|
6
|
-
def self.included(base)
|
7
|
-
base.extend ClassMethods
|
8
|
-
base.class_attribute :recognitions
|
9
|
-
end
|
10
|
-
|
11
|
-
module ClassMethods
|
12
|
-
def recognize recognizable, condition
|
13
|
-
include InstanceMethods
|
14
|
-
self.recognitions ||= {}
|
15
|
-
self.recognitions[condition[:for]] = { recognizable: recognizable, amount: condition[:amount], maximum: condition[:maximum] || 0 }
|
16
|
-
after_filter :recognize_actions
|
17
|
-
end
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
module InstanceMethods
|
22
|
-
def recognize_actions
|
23
|
-
action = params[:action].to_sym
|
24
|
-
if self.class.recognitions.keys.include? action
|
25
|
-
# update_points current_user.id, action, self.class.recognitions[action][:amount]
|
26
|
-
Database.update_points self, action, self.class.recognitions[action]
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,72 +0,0 @@
|
|
1
|
-
require "recognition/database"
|
2
|
-
|
3
|
-
module Recognition
|
4
|
-
module ActiveRecordExtension
|
5
|
-
def self.included(base)
|
6
|
-
base.extend ClassMethods
|
7
|
-
base.class_attribute :recognitions
|
8
|
-
base.class_attribute :recognizable
|
9
|
-
end
|
10
|
-
|
11
|
-
module ClassMethods
|
12
|
-
# to be called from user model
|
13
|
-
def acts_as_recognizable options = {}
|
14
|
-
require "recognition/activerecord/recognizable"
|
15
|
-
include Recognition::ActiveRecord::Recognizable
|
16
|
-
self.recognizable = true
|
17
|
-
self.recognitions ||= {}
|
18
|
-
self.recognitions[:initial] = {
|
19
|
-
amount: options[:initial]
|
20
|
-
}
|
21
|
-
after_save :add_initial_points
|
22
|
-
end
|
23
|
-
|
24
|
-
# to be called from other models
|
25
|
-
def recognize recognizable, condition
|
26
|
-
require "recognition/activerecord/model"
|
27
|
-
include Recognition::ActiveRecord::Model
|
28
|
-
self.recognitions ||= {}
|
29
|
-
self.recognitions[condition[:for]] = {
|
30
|
-
recognizable: recognizable,
|
31
|
-
bucket: condition[:group],
|
32
|
-
gain: condition[:gain],
|
33
|
-
loss: condition[:loss],
|
34
|
-
maximum: condition[:maximum]
|
35
|
-
}
|
36
|
-
# Due to the lack of ActiveRecord before_filter,
|
37
|
-
# we will have to alias the original method in order to intercept
|
38
|
-
if [:create, :update, :destroy].include? condition[:for]
|
39
|
-
include ActiveModel::Dirty
|
40
|
-
else
|
41
|
-
method = condition[:for]
|
42
|
-
define_method "#{method}_with_recognition" do |*args|
|
43
|
-
if self.send("#{method}_without_recognition", *args)
|
44
|
-
Database.update_points self, condition[:for], self.class.recognitions[condition[:for]]
|
45
|
-
end
|
46
|
-
end
|
47
|
-
alias_method_chain method, 'recognition'
|
48
|
-
end
|
49
|
-
# For actions that can be intercepted using ActiveRecord callbacks
|
50
|
-
before_destroy :recognize_destroying
|
51
|
-
after_save :recognize_updating
|
52
|
-
# We use after_save for creation to make sure all associations
|
53
|
-
# have been persisted
|
54
|
-
after_save :recognize_creating
|
55
|
-
end
|
56
|
-
|
57
|
-
# to be called from user-model
|
58
|
-
def acts_as_voucher options = {}
|
59
|
-
require "recognition/activerecord/voucher"
|
60
|
-
include Recognition::ActiveRecord::Voucher
|
61
|
-
self.recognitions = options
|
62
|
-
cattr_accessor :voucher_validators
|
63
|
-
def self.validates_voucher_redmeption validators
|
64
|
-
self.voucher_validators ||= []
|
65
|
-
self.voucher_validators << validators
|
66
|
-
self.voucher_validators.flatten!
|
67
|
-
end
|
68
|
-
before_create :regenerate_code
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
module Recognition
|
2
|
-
module ActiveRecord
|
3
|
-
module Recognizable
|
4
|
-
# Determine user current balance of points
|
5
|
-
def points
|
6
|
-
Database.get_user_points self.id
|
7
|
-
end
|
8
|
-
|
9
|
-
def recognition_counter bucket
|
10
|
-
Database.get_user_counter self.id, bucket
|
11
|
-
end
|
12
|
-
|
13
|
-
def add_initial_points
|
14
|
-
Database.update_points self, :initial, self.class.recognitions[:initial]
|
15
|
-
end
|
16
|
-
|
17
|
-
def update_points amount, bucket
|
18
|
-
Database.log(self.id, amount.to_i, bucket)
|
19
|
-
end
|
20
|
-
|
21
|
-
def transactions page = 0, per = 20
|
22
|
-
Database.get_user_transactions self.id, page, per
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
data/lib/recognition/engine.rb
DELETED
data/lib/recognition/railtie.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
require "recognition/active_record_extension"
|
2
|
-
require "recognition/action_controller_extension"
|
3
|
-
require "rails"
|
4
|
-
|
5
|
-
module Recognition
|
6
|
-
class Railtie < Rails::Railtie
|
7
|
-
initializer 'recognition.initialize' do
|
8
|
-
ActiveSupport.on_load(:active_record) do
|
9
|
-
ActiveRecord::Base.send :include, ActiveRecordExtension
|
10
|
-
end
|
11
|
-
ActiveSupport.on_load(:action_controller) do
|
12
|
-
ActionController::Base.send(:include, ActionControllerExtension)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
#
|
16
|
-
# initializer 'recognition.database' do
|
17
|
-
# #TODO: use a Rails initializer
|
18
|
-
# $REDIS = Redis.new #(host: 'localhost', port: redis_config[:port])
|
19
|
-
# end
|
20
|
-
end
|
21
|
-
end
|