recognition 0.4.0 → 0.5.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 CHANGED
@@ -80,11 +80,63 @@ app/controllers/profiles_controller.rb:
80
80
  end
81
81
  end
82
82
 
83
+ Example:
84
+
85
+ The following won't work:
86
+
87
+ class Post < ActiveRecord::Base
88
+ attr_accessible :title, :user_id
89
+ recognize :user, for: :foo, gain: 2
90
+ def foo
91
+ # do something useful
92
+ end
93
+ end
94
+
95
+ This one will:
96
+
97
+ class Post < ActiveRecord::Base
98
+ attr_accessible :title, :user_id
99
+ def foo
100
+ # do something useful
101
+ end
102
+ recognize :user, for: :foo, gain: 2
103
+ end
104
+
83
105
  ### Vouchers
84
106
 
107
+ Use an existing model or generate a new one using:
108
+
109
+ $ rails generate recogintion:voucher
110
+
111
+ Your model might have the following attributes:
112
+
113
+ * `:code` **required**
114
+ * `:amount` **required**
115
+ * `:expires_at` _optional_
116
+ * `:reusable` _optional_
117
+
118
+ You can specify the following extra parameters for vouchers:
119
+
120
+ * `:prefix` can be a number, string or method name or even an anonymous function.
121
+ * `:suffix` can be a number, string or method name or even an anonymous function.
122
+
123
+ app/models/voucher.rb:
124
+
125
+ class Voucher < ActiveRecord::Base
126
+ attr_accessible :code, :amount, :expires_at, :reusable
127
+ acts_as_voucher code_length: 14
128
+ end
129
+
130
+ Then, you may do:
131
+
132
+ voucher = Voucher.create!(amount: 20, expires_at: (DateTime.now + 1.day), reusable: true)
133
+ voucher.redeem current_user
134
+
135
+ ### Gifts
136
+
85
137
  Use an existing model or generate a new one using:
86
138
 
87
- $ rails generate recogintion:voucher
139
+ $ rails generate recogintion:gift
88
140
 
89
141
  Your model might have the following attributes:
90
142
 
@@ -93,44 +145,22 @@ Your model might have the following attributes:
93
145
  * `:expires_at` _optional_
94
146
  * `:reusable` _optional_
95
147
 
96
- You can specify the following extra parameters for vouchers:
148
+ You can specify the following extra parameters for gifts:
97
149
 
98
150
  * `:prefix` can be a number, string or method name or even an anonymous function.
99
151
  * `:suffix` can be a number, string or method name or even an anonymous function.
100
152
 
101
- app/models/voucher.rb:
153
+ app/models/gift.rb:
102
154
 
103
- class Voucher < ActiveRecord::Base
155
+ class Gift < ActiveRecord::Base
104
156
  attr_accessible :code, :amount, :expires_at, :reusable
105
- acts_as_voucher code_length: 14
157
+ acts_as_gift code_length: 14
106
158
  end
107
159
 
108
160
  Then, you may do:
109
161
 
110
- voucher = Voucher.create!(amount: 20, expires_at: (DateTime.now + 1.day), reusable: true)
111
- voucher.redeem current_user
112
-
113
- ## Example
114
- The following won't work:
115
-
116
- class Post < ActiveRecord::Base
117
- attr_accessible :title, :user_id
118
- recognize :user, for: :foo, gain: 2
119
- def foo
120
- # do something useful
121
- end
122
- end
123
-
124
- This one will:
125
-
126
- class Post < ActiveRecord::Base
127
- attr_accessible :title, :user_id
128
- def foo
129
- # do something useful
130
- end
131
- recognize :user, for: :foo, gain: 2
132
- end
133
-
162
+ gift = Gift.create!(amount: 20, expires_at: (DateTime.now + 1.day), reusable: true)
163
+ gift.redeem current_user
134
164
 
135
165
  ## Contributing
136
166
 
@@ -0,0 +1,25 @@
1
+ module Recognition
2
+ module Generators
3
+ class GiftGenerator < ::Rails::Generators::Base
4
+ desc "Generates a Recognition Gift"
5
+
6
+ def scaffold
7
+ generate 'scaffold gift code amount:integer reusable:boolean expires_at:datetime'
8
+ end
9
+
10
+ def set_defaults
11
+ line = "t.boolean :reusable"
12
+ gsub_file Dir.glob("db/migrate/*_create_gifts.rb").first, /(#{Regexp.escape(line)})/mi do |match|
13
+ "#{match}, default: false"
14
+ end
15
+ end
16
+
17
+ def add_stanza
18
+ line = "class Gift < ActiveRecord::Base"
19
+ gsub_file 'app/models/gift.rb', /(#{Regexp.escape(line)})/mi do |match|
20
+ "#{match}\n acts_as_gift code_length: 20 \n"
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,6 +1,8 @@
1
1
  module Recognition
2
2
  module Generators
3
- class VoucherGenerator < Rails::Generators::Base
3
+ class VoucherGenerator < ::Rails::Generators::Base
4
+ desc "Generates a Recognition Voucher"
5
+
4
6
  def scaffold
5
7
  generate 'scaffold voucher code amount:integer reusable:boolean expires_at:datetime'
6
8
  end
@@ -29,17 +29,22 @@ module Recognition
29
29
  Recognition.log 'foo', condition.to_s
30
30
  condition[:bucket] ||= "#{ object.class.to_s.camelize }:#{ action }"
31
31
  user = Recognition::Parser.parse_recognizable(object, condition[:recognizable], condition[:proc_params])
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"
34
- false
35
- else
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
38
- if condition[:maximum].nil? || ground_total <= condition[:maximum]
39
- log(user.id, total.to_i, condition[:bucket])
32
+ # Do we have a valid user?
33
+ if user.respond_to?(:points)
34
+ if condition[:amount].nil? && condition[:gain].nil? && condition[:loss].nil?
35
+ Recognition.log 'validation', "Unable to determine points: no 'amount', 'gain' or 'loss' specified"
36
+ false
40
37
  else
41
- Recognition.log 'validation', "Unable to add points: bucket maximum reached for bucket '#{condition[:bucket]}'"
38
+ 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])
39
+ ground_total = user.recognition_counter(condition[:bucket]) + total
40
+ if condition[:maximum].nil? || ground_total <= condition[:maximum]
41
+ log(user.id, total.to_i, condition[:bucket])
42
+ else
43
+ Recognition.log 'validation', "Unable to add points: bucket maximum reached for bucket '#{condition[:bucket]}'"
44
+ end
42
45
  end
46
+ else
47
+ Recognition.log 'validation', "Unable to add points to #{condition[:recognizable]}, make sure it 'acts_as_recognizable'"
43
48
  end
44
49
  end
45
50
 
@@ -53,16 +53,28 @@ module Recognition
53
53
  after_save :recognize_creating
54
54
  end
55
55
 
56
- # to be called from user-model
57
56
  def acts_as_voucher options = {}
58
57
  require "recognition/models/voucher"
59
58
  include Recognition::Models::Voucher
60
59
  self.recognitions = options
61
- cattr_accessor :voucher_validators
60
+ cattr_accessor :redemption_validators
62
61
  def self.validates_voucher_redmeption validators
63
- self.voucher_validators ||= []
64
- self.voucher_validators << validators
65
- self.voucher_validators.flatten!
62
+ self.redemption_validators ||= []
63
+ self.redemption_validators << validators
64
+ self.redemption_validators.flatten!
65
+ end
66
+ before_create :regenerate_code
67
+ end
68
+
69
+ def acts_as_gift options = {}
70
+ require "recognition/models/gift"
71
+ include Recognition::Models::Gift
72
+ self.recognitions = options
73
+ cattr_accessor :redemption_validators
74
+ def self.validates_gift_redmeption validators
75
+ self.redemption_validators ||= []
76
+ self.redemption_validators << validators
77
+ self.redemption_validators.flatten!
66
78
  end
67
79
  before_create :regenerate_code
68
80
  end
@@ -1,65 +1,18 @@
1
+ require 'recognition/models/redeemable'
2
+
1
3
  module Recognition
2
4
  module Models
3
5
  module Gift
4
- def regenerate_code
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
- 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.gift_validators
25
- self.class.gift_validators.each do |validator|
26
- # quit if any validator returned false
27
- return if send(validator) == false
28
- end
29
- end
30
- # If all went well:
31
- Database.redeem_gift recognizable.id, self.code, self.amount
32
- end
33
- end
34
- end
35
-
6
+ include Recognition::Models::Redeemable
7
+
36
8
  def redeemable? recognizable
37
- # default: not redeemable
38
- pass = false
39
- # only check if the gift did not expire
40
- unless expired?
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
- pass = false
46
- # is the gift reusable?
47
- elsif defined?(self.reusable?) && self.reusable?
48
- pass = true
49
- end
50
- else
51
- pass = true
52
- end
53
- end
54
- pass
9
+ recognizable.points >= self.amount && is_redeemable?(recognizable)
55
10
  end
56
11
 
57
- def expired?
58
- defined?(self.expires_at) && self.expires_at.present? && self.expires_at < DateTime.now
12
+ def execute_redemption id
13
+ actual_amount = (self.amount.to_i * -1)
14
+ Recognition::Database.redeem id, bucket, self.class.to_s.downcase, self.code, actual_amount
59
15
  end
60
-
61
- private
62
-
63
16
  end
64
17
  end
65
18
  end
@@ -0,0 +1,81 @@
1
+ module Recognition
2
+ module Models
3
+ module Redeemable
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 expired?
20
+ defined?(self.expires_at) && self.expires_at.present? && self.expires_at < DateTime.now
21
+ end
22
+
23
+ def is_redeemable? recognizable
24
+ # default: not redeemable
25
+ pass = false
26
+ # only check if the redeemable did not expire
27
+ unless expired?
28
+ # has the redeemable ever been redeemed?
29
+ if transactions.any?
30
+ # has the redeemable ever been redeemed by this user?
31
+ if get_user_counter(recognizable.id) != 0
32
+ pass = false
33
+ # is the redeemable reusable?
34
+ elsif defined?(self.reusable?) && self.reusable?
35
+ pass = true
36
+ end
37
+ else
38
+ pass = true
39
+ end
40
+ end
41
+ pass
42
+ end
43
+
44
+ def redeem recognizable
45
+ # Make sure we have an amount beforehand
46
+ if defined? self.amount
47
+ if self.redeemable? recognizable
48
+ # Call custom validators
49
+ if defined? self.class.redemption_validators
50
+ self.class.redemption_validators.each do |validator|
51
+ # quit if any validator returned false
52
+ if send(validator) == false
53
+ Recognition.log self.class.to_s.to_sym, "validation error for #{self.class.to_s}:#{self.id}"
54
+ return
55
+ end
56
+ end
57
+ end
58
+ # If all went well:
59
+ execute_redemption recognizable.id
60
+ end
61
+ end
62
+ end
63
+
64
+
65
+ def bucket
66
+ "#{self.class.to_s.downcase}:#{ self.code }"
67
+ end
68
+
69
+ def get_user_counter id
70
+ Recognition::Database.get_counter "user:#{id}", bucket
71
+ end
72
+
73
+ def transactions page = 0, per = 20
74
+ start = page * per
75
+ stop = (1 + page) * per
76
+ Recognition::Database.get_transactions bucket, start, stop
77
+ end
78
+
79
+ end
80
+ end
81
+ end
@@ -1,82 +1,17 @@
1
+ require 'recognition/models/redeemable'
2
+
1
3
  module Recognition
2
4
  module Models
3
5
  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
6
+ include Recognition::Models::Redeemable
65
7
 
66
- def bucket
67
- "voucher:#{ self.code }"
68
- end
69
-
70
- def get_user_voucher id
71
- Recognition::Database.get_counter "user:#{id}", bucket
8
+ def redeemable? recognizable
9
+ is_redeemable? recognizable
72
10
  end
73
11
 
74
- def transactions page = 0, per = 20
75
- start = page * per
76
- stop = (1 + page) * per
77
- Recognition::Database.get_transactions bucket, start, stop
12
+ def execute_redemption id
13
+ Recognition::Database.redeem id, bucket, self.class.to_s.downcase, self.code, self.amount.to_i
78
14
  end
79
-
80
15
  end
81
16
  end
82
17
  end
@@ -1,4 +1,4 @@
1
1
  module Recognition
2
2
  # Current Version
3
- VERSION = "0.4.0"
3
+ VERSION = "0.5.0"
4
4
  end
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.0
4
+ version: 0.5.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -146,6 +146,7 @@ executables: []
146
146
  extensions: []
147
147
  extra_rdoc_files: []
148
148
  files:
149
+ - lib/generators/recognition/gift_generator.rb
149
150
  - lib/generators/recognition/install_generator.rb
150
151
  - lib/generators/recognition/templates/recognition.rb
151
152
  - lib/generators/recognition/templates/recognition.yml
@@ -159,6 +160,7 @@ files:
159
160
  - lib/recognition/models/gift.rb
160
161
  - lib/recognition/models/recognizable.rb
161
162
  - lib/recognition/models/recognizer.rb
163
+ - lib/recognition/models/redeemable.rb
162
164
  - lib/recognition/models/voucher.rb
163
165
  - lib/recognition/parser.rb
164
166
  - lib/recognition/rails/engine.rb
@@ -183,7 +185,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
183
185
  version: '0'
184
186
  segments:
185
187
  - 0
186
- hash: -4080240542959513995
188
+ hash: 2026242214967045348
187
189
  required_rubygems_version: !ruby/object:Gem::Requirement
188
190
  none: false
189
191
  requirements:
@@ -192,7 +194,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
192
194
  version: '0'
193
195
  segments:
194
196
  - 0
195
- hash: -4080240542959513995
197
+ hash: 2026242214967045348
196
198
  requirements: []
197
199
  rubyforge_project:
198
200
  rubygems_version: 1.8.23