recognition 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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