riaction 1.3.5 → 1.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/CHANGELOG.md +5 -0
- data/README.md +20 -1
- data/lib/generators/riaction/{USAGE → install/USAGE} +1 -1
- data/lib/generators/riaction/install/install_generator.rb +23 -0
- data/lib/generators/riaction/{templates → install/templates}/i_actionable.yml +0 -0
- data/lib/generators/riaction/install/templates/riaction.rb +21 -0
- data/lib/generators/riaction_generator.rb +11 -0
- data/lib/riaction/api_failure.rb +21 -0
- data/lib/riaction/event_performer.rb +41 -41
- data/lib/riaction/profile_creator.rb +32 -18
- data/lib/riaction/railtie.rb +0 -4
- data/lib/riaction/riaction.rb +1 -0
- data/lib/riaction/version.rb +1 -1
- data/spec/event_performer_spec.rb +47 -35
- data/spec/profile_creation_spec.rb +46 -4
- metadata +28 -26
- data/lib/generators/riaction/riaction_generator.rb +0 -17
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# CHANGELOG #
|
|
2
2
|
|
|
3
|
+
## 1.4.0 ##
|
|
4
|
+
|
|
5
|
+
* Since IActionable creates non-existent profiles named in an event logging, the event logger no longer tries to confirm profile existence as a pre-condition.
|
|
6
|
+
* Adding support to provide custom behavior when the API returns a 500 on creating a profile or logging an event.
|
|
7
|
+
|
|
3
8
|
## 1.3.4 ##
|
|
4
9
|
|
|
5
10
|
* background logging of events will first check if the profile exists, and re-enqueue the job if it doesn't, up to a max number of retries, at which point it will log the event regardless.
|
data/README.md
CHANGED
|
@@ -16,7 +16,9 @@ Riaction uses [Resque](https://github.com/defunkt/resque) to schedule and perfor
|
|
|
16
16
|
|
|
17
17
|
Riaction comes with a generator for creating a YAML file to contain your credentials for each environment of your application. The YAML file is necessary for riaction to run correctly in your rails app.
|
|
18
18
|
|
|
19
|
-
rails g riaction development:12345:abcde production:54321:edcba
|
|
19
|
+
rails g riaction:install development:12345:abcde production:54321:edcba
|
|
20
|
+
|
|
21
|
+
This generator will also create an initializer in config/initializers/riaction.rb, where you can provide custom error handling if you wish (see below in *Custom API Error Handling*).
|
|
20
22
|
|
|
21
23
|
### Declaring A Model As A Profile ###
|
|
22
24
|
|
|
@@ -177,6 +179,23 @@ If you want to avoid the automatic creation of a profile, or the automatic loggi
|
|
|
177
179
|
Review.riactionless{ @user_instance.reviews.create(:text => "loved it!") } # won't fire the 'write_a_review' event
|
|
178
180
|
Review.riactionless{ @review_instance.trigger_thumbs_up! } # won't fire the 'receive_thumbs_up' event
|
|
179
181
|
|
|
182
|
+
#### Custom API Error Handling ####
|
|
183
|
+
|
|
184
|
+
When the API returns a status code 500 on internal error the [Ruby-IActionable gem](https://github.com/zortnac/Ruby-IActionable) will raise an exception of class IActionable::Error::Internal. The default behavior in riaction is to re-raise the error. You can create custom behavior to log the error through a third party service (like Airbrake), have riaction re-schedule the task to try again, save the information to have it be re-attempted later through your own means, or any combination of the above:
|
|
185
|
+
|
|
186
|
+
::Riaction::EventPerformer.handle_api_failure_with do |exception, event_name, class_name, id|
|
|
187
|
+
# log the error through a third party service and then re-attempt
|
|
188
|
+
Airbrake.notify(exception)
|
|
189
|
+
true
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
::Riaction::ProfileCreator.handle_api_failure_with do |exception, class_name, id|
|
|
193
|
+
# log the error through a third party service, punish the user for their failure, and do not re-attempt
|
|
194
|
+
Airbrake.notify(exception)
|
|
195
|
+
class_name.constantize.find_by_id(id).flog(:lashes => 100)
|
|
196
|
+
false
|
|
197
|
+
end
|
|
198
|
+
|
|
180
199
|
### Rails Rake Tasks ###
|
|
181
200
|
|
|
182
201
|
There are 3 rake tasks included for summarizing all of your models' declarations as well as a way to initialize profiles on IActionable. To see a report of all the events declared across your application, run the following:
|
|
@@ -2,7 +2,7 @@ Description:
|
|
|
2
2
|
Generate a Yaml file in your config directory to contain your IActionable credentials.
|
|
3
3
|
|
|
4
4
|
Example:
|
|
5
|
-
rails generate riaction ENVIRONMENT:APP_KEY:API_KEY ENVIRONMENT:APP_KEY:API_KEY
|
|
5
|
+
rails generate riaction:install ENVIRONMENT:APP_KEY:API_KEY ENVIRONMENT:APP_KEY:API_KEY
|
|
6
6
|
|
|
7
7
|
This will create:
|
|
8
8
|
config/i_actionable.yml
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'generators/riaction_generator'
|
|
2
|
+
|
|
3
|
+
module Riaction
|
|
4
|
+
module Generators
|
|
5
|
+
class InstallGenerator < Base
|
|
6
|
+
argument :credentials, :type => :array, :required => true, :banner => "environment:app_key:api_key environment:app_key:api_key"
|
|
7
|
+
|
|
8
|
+
def create_credentials_file
|
|
9
|
+
credentials.map!{|credential| { :env => credential[credential_regexp,1],
|
|
10
|
+
:app_key => credential[credential_regexp,2],
|
|
11
|
+
:api_key => credential[credential_regexp,3] } }
|
|
12
|
+
template "i_actionable.yml", "config/i_actionable.yml"
|
|
13
|
+
template "riaction.rb", "config/initializers/riaction.rb"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def credential_regexp
|
|
19
|
+
/^(\w+):(\w+):(\w+)$/
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# When the IActionable API returns a 500 for logging an event or creating a profile, a custom handler can be defined below,
|
|
2
|
+
# useful for making calls to external exception notifier services (airbrake, etc), or handling the failure in some specific way
|
|
3
|
+
# useful to the application.
|
|
4
|
+
#
|
|
5
|
+
# ::Riaction::EventPerformer.handle_api_failure_with do |exception, event_name, class_name, id|
|
|
6
|
+
# # re-raise the exception
|
|
7
|
+
# raise exception
|
|
8
|
+
# # return true to have the event rescheduled
|
|
9
|
+
# true
|
|
10
|
+
# # return false to not have the event rescheduled
|
|
11
|
+
# false
|
|
12
|
+
# end
|
|
13
|
+
#
|
|
14
|
+
# ::Riaction::ProfileCreator.handle_api_failure_with do |exception, class_name, id|
|
|
15
|
+
# # re-raise the exception
|
|
16
|
+
# raise exception
|
|
17
|
+
# # return true to have the event rescheduled
|
|
18
|
+
# true
|
|
19
|
+
# # return false to not have the event rescheduled
|
|
20
|
+
# false
|
|
21
|
+
# end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
require 'rails/generators/named_base'
|
|
2
|
+
|
|
3
|
+
module Riaction
|
|
4
|
+
module Generators
|
|
5
|
+
class Base < Rails::Generators::Base
|
|
6
|
+
def self.source_root
|
|
7
|
+
@_riaction_source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'riaction', generator_name, 'templates'))
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Riaction
|
|
2
|
+
module ApiFailure
|
|
3
|
+
def handle_api_failure(exception)
|
|
4
|
+
if @api_failure_handler_block
|
|
5
|
+
@api_failure_handler_block.call(exception)
|
|
6
|
+
else
|
|
7
|
+
default_behavior(exception)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def handle_api_failure_with(&block)
|
|
12
|
+
if block_given?
|
|
13
|
+
@api_failure_handler_block = block
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def default_behavior(exception)
|
|
18
|
+
raise exception
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -3,56 +3,56 @@ require "resque"
|
|
|
3
3
|
|
|
4
4
|
module Riaction
|
|
5
5
|
class EventPerformer
|
|
6
|
+
extend ::Riaction::ApiFailure
|
|
7
|
+
|
|
6
8
|
@queue = :riaction_event_logger
|
|
7
9
|
|
|
8
10
|
# Sends an event to IActionable based on the name of a riaction class and the ID used to locate the instance
|
|
9
11
|
def self.perform(event_name, klass_name, id, attempt=0)
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
12
|
+
check_class_requirements!(event_name, klass_name)
|
|
13
|
+
begin
|
|
14
|
+
log_event(event_name, klass_name, id)
|
|
15
|
+
rescue IActionable::Error::BadRequest => e
|
|
16
|
+
# Log event should never throw this as of IActionable API v3
|
|
17
|
+
rescue Faraday::Error::TimeoutError, Timeout::Error => e
|
|
18
|
+
Resque.enqueue(self, event_name, klass_name, id, attempt+1)
|
|
19
|
+
rescue IActionable::Error::Internal => e
|
|
20
|
+
# handle_api_failure(event_name, klass_name, id, attempt)
|
|
21
|
+
handle_api_failure(e, event_name, klass_name, id)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.check_class_requirements!(event_name, klass_name)
|
|
26
|
+
unless klass_name.constantize.riactionary? &&
|
|
27
|
+
klass_name.constantize.riaction_events? &&
|
|
28
|
+
klass_name.constantize.riaction_defines_event?(event_name.to_sym)
|
|
29
|
+
raise ::Riaction::ConfigurationError.new("#{klass_name} does not define event #{event_name}")
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.log_event(event_name, klass_name, id)
|
|
34
|
+
iactionable_api = IActionable::Api.new
|
|
35
|
+
if event_object = klass_name.constantize.find_by_id(id)
|
|
36
|
+
event_params = event_object.riaction_event_params
|
|
37
|
+
if event_params.has_key?(event_name.to_sym)
|
|
38
|
+
iactionable_api.log_event( event_params[event_name.to_sym][:profile][:type],
|
|
39
|
+
event_params[event_name.to_sym][:profile][:id_type],
|
|
40
|
+
event_params[event_name.to_sym][:profile][:id],
|
|
41
|
+
event_name.to_sym,
|
|
42
|
+
event_params[event_name.to_sym][:params])
|
|
39
43
|
else
|
|
40
44
|
raise ::Riaction::ConfigurationError.new("Instance of #{klass_name} with ID #{id} could not construct event parameters for event #{event_name}. Is the profile a valid one?")
|
|
41
45
|
end
|
|
42
|
-
else
|
|
43
|
-
raise ::Riaction::ConfigurationError.new("#{klass_name} does not define event #{event_name}")
|
|
44
46
|
end
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if attempt < ::Riaction::Constants.retry_attempts_for_internal_error
|
|
53
|
-
Resque.enqueue(self, event_name, klass_name, id, attempt+1)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.handle_api_failure(exception, event_name, klass_name, id)
|
|
50
|
+
if @api_failure_handler_block
|
|
51
|
+
if @api_failure_handler_block.call(exception, event_name, klass_name, id)
|
|
52
|
+
Resque.enqueue(self, event_name, klass_name, id)
|
|
53
|
+
end
|
|
54
54
|
else
|
|
55
|
-
|
|
55
|
+
default_behavior(exception)
|
|
56
56
|
end
|
|
57
57
|
end
|
|
58
58
|
end
|
|
@@ -3,14 +3,33 @@ require "resque"
|
|
|
3
3
|
|
|
4
4
|
module Riaction
|
|
5
5
|
class ProfileCreator
|
|
6
|
+
extend ::Riaction::ApiFailure
|
|
7
|
+
|
|
6
8
|
@queue = :riaction_profile_creator
|
|
7
9
|
|
|
8
10
|
def self.perform(klass_name, id, attempt=0)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
check_class_requirements!(klass_name)
|
|
12
|
+
create_profile(klass_name, id)
|
|
13
|
+
rescue IActionable::Error::BadRequest => e
|
|
14
|
+
# This should only be thrown if the profile type names specified in the model don't match what's on IActionable's dashboard
|
|
15
|
+
raise e
|
|
16
|
+
rescue Faraday::Error::TimeoutError, Timeout::Error => e
|
|
17
|
+
Resque.enqueue(self, klass_name, id, attempt+1)
|
|
18
|
+
rescue IActionable::Error::Internal => e
|
|
19
|
+
handle_api_failure(e, klass_name, id)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.check_class_requirements!(klass_name)
|
|
23
|
+
unless klass_name.constantize.riactionary? &&
|
|
24
|
+
klass_name.constantize.riaction_profile? &&
|
|
25
|
+
klass_name.constantize.riaction_profile_types_defined > 0
|
|
26
|
+
raise ::Riaction::RuntimeError.new("#{klass_name} does not define any riaction profiles")
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.create_profile(klass_name, id)
|
|
31
|
+
iactionable_api = IActionable::Api.new
|
|
32
|
+
if record = klass_name.constantize.find_by_id(id)
|
|
14
33
|
record.riaction_profile_keys.each_pair do |profile_type, ids|
|
|
15
34
|
identifiers = ids.to_a
|
|
16
35
|
first_defined = identifiers.shift
|
|
@@ -19,21 +38,16 @@ module Riaction
|
|
|
19
38
|
iactionable_api.add_profile_identifier(profile_type.to_s, first_defined.first.to_s, first_defined.last.to_s, identifier.first.to_s, identifier.last.to_s)
|
|
20
39
|
end
|
|
21
40
|
end
|
|
22
|
-
else
|
|
23
|
-
raise ::Riaction::RuntimeError.new("#{klass_name} does not define any riaction profiles")
|
|
24
41
|
end
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
# after the max number of attempts, re-raise
|
|
33
|
-
if attempt < ::Riaction::Constants.retry_attempts_for_internal_error
|
|
34
|
-
Resque.enqueue(self, klass_name, id, attempt+1)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.handle_api_failure(exception, klass_name, id)
|
|
45
|
+
if @api_failure_handler_block
|
|
46
|
+
if @api_failure_handler_block.call(exception, klass_name, id)
|
|
47
|
+
Resque.enqueue(self, klass_name, id)
|
|
48
|
+
end
|
|
35
49
|
else
|
|
36
|
-
|
|
50
|
+
default_behavior(exception)
|
|
37
51
|
end
|
|
38
52
|
end
|
|
39
53
|
end
|
data/lib/riaction/railtie.rb
CHANGED
|
@@ -6,10 +6,6 @@ module Riaction
|
|
|
6
6
|
load "tasks/riaction.rake"
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
generators do
|
|
10
|
-
require "generators/riaction/riaction_generator"
|
|
11
|
-
end
|
|
12
|
-
|
|
13
9
|
initializer "riaction_railtie.configure_i_actionable_creds" do |app|
|
|
14
10
|
begin
|
|
15
11
|
IActionable::Api.init_settings(YAML.load_file("#{::Rails.root}/config/i_actionable.yml")[::Rails.env].symbolize_keys!)
|
data/lib/riaction/riaction.rb
CHANGED
data/lib/riaction/version.rb
CHANGED
|
@@ -93,36 +93,6 @@ describe "sending an event to IActionable from the name of a riaction class and
|
|
|
93
93
|
end
|
|
94
94
|
end
|
|
95
95
|
|
|
96
|
-
describe "when the profile attached to the event does not exist on IActionable" do
|
|
97
|
-
before do
|
|
98
|
-
Comment.class_eval do
|
|
99
|
-
riaction :event, :name => :make_a_comment, :trigger => :create, :profile => :user, :profile_type => :player
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
@comment = Comment.riactionless{ Comment.create(:user_id => @user.id, :content => 'this is a comment') }
|
|
103
|
-
|
|
104
|
-
@api.stub!(:get_profile_summary).and_raise(IActionable::Error::BadRequest.new(nil))
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
it "should not log the event, but reschedule the job with an incremented attempt count" do
|
|
108
|
-
@api.should_not_receive(:log_event)
|
|
109
|
-
Resque.should_receive(:enqueue).once.with(Riaction::EventPerformer, :make_a_comment, 'Comment', @comment.id, 1)
|
|
110
|
-
::Riaction::EventPerformer.perform(:make_a_comment, 'Comment', @comment.id)
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
describe "and the number of attempts has reached the max" do
|
|
114
|
-
it "should log the event, and not re-enqueue" do
|
|
115
|
-
@api.should_receive(:log_event).once.with(@comment.riaction_event_params[:make_a_comment][:profile][:type],
|
|
116
|
-
@comment.riaction_event_params[:make_a_comment][:profile][:id_type],
|
|
117
|
-
@comment.riaction_event_params[:make_a_comment][:profile][:id],
|
|
118
|
-
:make_a_comment,
|
|
119
|
-
{})
|
|
120
|
-
Resque.should_not_receive(:enqueue)
|
|
121
|
-
::Riaction::EventPerformer.perform(:make_a_comment, 'Comment', @comment.id, Riaction::Constants.retry_attempts_for_missing_profile)
|
|
122
|
-
end
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
|
|
126
96
|
describe "when fetching the event params raises a" do
|
|
127
97
|
before do
|
|
128
98
|
Comment.class_eval do
|
|
@@ -135,7 +105,7 @@ describe "sending an event to IActionable from the name of a riaction class and
|
|
|
135
105
|
describe "RuntimeError" do
|
|
136
106
|
before do
|
|
137
107
|
@comment.stub!(:riaction_event_params).and_raise(::Riaction::RuntimeError)
|
|
138
|
-
Comment.stub!(:find_by_id
|
|
108
|
+
Comment.stub!(:find_by_id).and_return(@comment)
|
|
139
109
|
end
|
|
140
110
|
|
|
141
111
|
it "should not try to create the event" do
|
|
@@ -154,7 +124,7 @@ describe "sending an event to IActionable from the name of a riaction class and
|
|
|
154
124
|
describe "ConfigurationError" do
|
|
155
125
|
before do
|
|
156
126
|
@comment.stub!(:riaction_event_params).and_raise(::Riaction::ConfigurationError)
|
|
157
|
-
Comment.stub!(:find_by_id
|
|
127
|
+
Comment.stub!(:find_by_id).and_return(@comment)
|
|
158
128
|
end
|
|
159
129
|
|
|
160
130
|
it "should not try to create the event" do
|
|
@@ -266,17 +236,59 @@ describe "sending an event to IActionable from the name of a riaction class and
|
|
|
266
236
|
|
|
267
237
|
describe "when the call to IActionable, through API wrapper, fails" do
|
|
268
238
|
before do
|
|
269
|
-
@
|
|
239
|
+
@exception = IActionable::Error::Internal.new("")
|
|
240
|
+
@api.stub!(:log_event).and_raise(@exception)
|
|
270
241
|
Comment.class_eval do
|
|
271
242
|
riaction :event, :name => :make_a_comment, :trigger => :create, :profile => :user, :profile_type => :npc, :params => {:foo => 'bar'}
|
|
272
243
|
end
|
|
273
244
|
@comment = Comment.riactionless{ Comment.create(:user_id => @user.id, :content => 'this is a comment') }
|
|
274
245
|
end
|
|
275
246
|
|
|
276
|
-
it "should
|
|
277
|
-
|
|
247
|
+
it "should handle the failure passing the exception, event name, class name, and model id" do
|
|
248
|
+
::Riaction::EventPerformer.should_receive(:handle_api_failure).once.with(@exception, :make_a_comment, 'Comment', @comment.id)
|
|
278
249
|
::Riaction::EventPerformer.perform(:make_a_comment, 'Comment', @comment.id)
|
|
279
250
|
end
|
|
251
|
+
|
|
252
|
+
describe "and the default behavior of the failure handler is in place" do
|
|
253
|
+
it "should re-raise the exception" do
|
|
254
|
+
lambda{::Riaction::EventPerformer.perform(:make_a_comment, 'Comment', @comment.id)}.should raise_error(@exception)
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
describe "and custom behavior of the failure handler is in place" do
|
|
259
|
+
before do
|
|
260
|
+
::Riaction::EventPerformer.handle_api_failure_with do |exception, event_name, class_name, id|
|
|
261
|
+
5.times do
|
|
262
|
+
exception.inspect
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
it "should perform the custom behavior" do
|
|
268
|
+
@exception.should_receive(:inspect).exactly(5).times
|
|
269
|
+
::Riaction::EventPerformer.perform(:make_a_comment, 'Comment', @comment.id)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
describe "and that custom behavior evaluates to true" do
|
|
273
|
+
it "should reschedule the event" do
|
|
274
|
+
Resque.should_receive(:enqueue).once.with(Riaction::EventPerformer, :make_a_comment, 'Comment', @comment.id)
|
|
275
|
+
::Riaction::EventPerformer.perform(:make_a_comment, 'Comment', @comment.id)
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
describe "and that custom behavior evaluates to false" do
|
|
280
|
+
before do
|
|
281
|
+
::Riaction::EventPerformer.handle_api_failure_with do |exception, event_name, class_name, id|
|
|
282
|
+
false
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
it "should not reschedule the event" do
|
|
287
|
+
Resque.should_not_receive(:enqueue)
|
|
288
|
+
::Riaction::EventPerformer.perform(:make_a_comment, 'Comment', @comment.id)
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
end
|
|
280
292
|
end
|
|
281
293
|
|
|
282
294
|
describe "when the call to IActionable, through API wrapper, times out" do
|
|
@@ -114,16 +114,58 @@ describe "automatic profile creation from riaction definitions:" do
|
|
|
114
114
|
|
|
115
115
|
describe "when the call to IActionable, through API wrapper, fails" do
|
|
116
116
|
before do
|
|
117
|
-
@
|
|
117
|
+
@exception = IActionable::Error::Internal.new("")
|
|
118
|
+
@api.stub!(:create_profile).and_raise(@exception)
|
|
118
119
|
User.class_eval do
|
|
119
120
|
riaction :profile, :type => :player, :custom => :id, :username => :name
|
|
120
121
|
end
|
|
121
122
|
@user = User.riactionless{ User.create(:name => 'zortnac') }
|
|
122
123
|
end
|
|
123
124
|
|
|
124
|
-
it "should
|
|
125
|
-
|
|
126
|
-
::Riaction::ProfileCreator.perform('User', @user.id
|
|
125
|
+
it "should handle the failure passing the exception, class name, and model id" do
|
|
126
|
+
::Riaction::ProfileCreator.should_receive(:handle_api_failure).once.with(@exception, 'User', @user.id)
|
|
127
|
+
::Riaction::ProfileCreator.perform('User', @user.id)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
describe "and the default behavior of the failure handler is in place" do
|
|
131
|
+
it "should re-raise the exception" do
|
|
132
|
+
lambda{::Riaction::ProfileCreator.perform('User', @user.id)}.should raise_error(@exception)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
describe "and custom behavior of the failure handler is in place" do
|
|
137
|
+
before do
|
|
138
|
+
::Riaction::ProfileCreator.handle_api_failure_with do |exception, class_name, id|
|
|
139
|
+
3.times do
|
|
140
|
+
exception.inspect
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it "should perform the custom behavior" do
|
|
146
|
+
@exception.should_receive(:inspect).exactly(3).times
|
|
147
|
+
::Riaction::ProfileCreator.perform('User', @user.id)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
describe "and that custom behavior evaluates to true" do
|
|
151
|
+
it "should reschedule the event" do
|
|
152
|
+
Resque.should_receive(:enqueue).once.with(Riaction::ProfileCreator, "User", @user.id)
|
|
153
|
+
::Riaction::ProfileCreator.perform('User', @user.id)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
describe "and that custom behavior evaluates to false" do
|
|
158
|
+
before do
|
|
159
|
+
::Riaction::ProfileCreator.handle_api_failure_with do |exception, class_name, id|
|
|
160
|
+
false
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
it "should not reschedule the event" do
|
|
165
|
+
Resque.should_not_receive(:enqueue)
|
|
166
|
+
::Riaction::ProfileCreator.perform('User', @user.id)
|
|
167
|
+
end
|
|
168
|
+
end
|
|
127
169
|
end
|
|
128
170
|
end
|
|
129
171
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: riaction
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.4.0
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -11,11 +11,11 @@ authors:
|
|
|
11
11
|
autorequire:
|
|
12
12
|
bindir: bin
|
|
13
13
|
cert_chain: []
|
|
14
|
-
date: 2012-
|
|
14
|
+
date: 2012-06-27 00:00:00.000000000Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: rspec
|
|
18
|
-
requirement: &
|
|
18
|
+
requirement: &2164272500 !ruby/object:Gem::Requirement
|
|
19
19
|
none: false
|
|
20
20
|
requirements:
|
|
21
21
|
- - ! '>='
|
|
@@ -23,10 +23,10 @@ dependencies:
|
|
|
23
23
|
version: '2.8'
|
|
24
24
|
type: :development
|
|
25
25
|
prerelease: false
|
|
26
|
-
version_requirements: *
|
|
26
|
+
version_requirements: *2164272500
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: sqlite3
|
|
29
|
-
requirement: &
|
|
29
|
+
requirement: &2164271940 !ruby/object:Gem::Requirement
|
|
30
30
|
none: false
|
|
31
31
|
requirements:
|
|
32
32
|
- - ! '>='
|
|
@@ -34,10 +34,10 @@ dependencies:
|
|
|
34
34
|
version: '0'
|
|
35
35
|
type: :development
|
|
36
36
|
prerelease: false
|
|
37
|
-
version_requirements: *
|
|
37
|
+
version_requirements: *2164271940
|
|
38
38
|
- !ruby/object:Gem::Dependency
|
|
39
39
|
name: ruby-debug19
|
|
40
|
-
requirement: &
|
|
40
|
+
requirement: &2164271140 !ruby/object:Gem::Requirement
|
|
41
41
|
none: false
|
|
42
42
|
requirements:
|
|
43
43
|
- - ! '>='
|
|
@@ -45,10 +45,10 @@ dependencies:
|
|
|
45
45
|
version: '0'
|
|
46
46
|
type: :development
|
|
47
47
|
prerelease: false
|
|
48
|
-
version_requirements: *
|
|
48
|
+
version_requirements: *2164271140
|
|
49
49
|
- !ruby/object:Gem::Dependency
|
|
50
50
|
name: yard
|
|
51
|
-
requirement: &
|
|
51
|
+
requirement: &2164270380 !ruby/object:Gem::Requirement
|
|
52
52
|
none: false
|
|
53
53
|
requirements:
|
|
54
54
|
- - ! '>='
|
|
@@ -56,10 +56,10 @@ dependencies:
|
|
|
56
56
|
version: '0'
|
|
57
57
|
type: :development
|
|
58
58
|
prerelease: false
|
|
59
|
-
version_requirements: *
|
|
59
|
+
version_requirements: *2164270380
|
|
60
60
|
- !ruby/object:Gem::Dependency
|
|
61
61
|
name: redcarpet
|
|
62
|
-
requirement: &
|
|
62
|
+
requirement: &2164268920 !ruby/object:Gem::Requirement
|
|
63
63
|
none: false
|
|
64
64
|
requirements:
|
|
65
65
|
- - ! '>='
|
|
@@ -67,10 +67,10 @@ dependencies:
|
|
|
67
67
|
version: '0'
|
|
68
68
|
type: :development
|
|
69
69
|
prerelease: false
|
|
70
|
-
version_requirements: *
|
|
70
|
+
version_requirements: *2164268920
|
|
71
71
|
- !ruby/object:Gem::Dependency
|
|
72
72
|
name: rake
|
|
73
|
-
requirement: &
|
|
73
|
+
requirement: &2164268200 !ruby/object:Gem::Requirement
|
|
74
74
|
none: false
|
|
75
75
|
requirements:
|
|
76
76
|
- - ! '>='
|
|
@@ -78,10 +78,10 @@ dependencies:
|
|
|
78
78
|
version: '0'
|
|
79
79
|
type: :runtime
|
|
80
80
|
prerelease: false
|
|
81
|
-
version_requirements: *
|
|
81
|
+
version_requirements: *2164268200
|
|
82
82
|
- !ruby/object:Gem::Dependency
|
|
83
83
|
name: activerecord
|
|
84
|
-
requirement: &
|
|
84
|
+
requirement: &2164267400 !ruby/object:Gem::Requirement
|
|
85
85
|
none: false
|
|
86
86
|
requirements:
|
|
87
87
|
- - ! '>='
|
|
@@ -89,10 +89,10 @@ dependencies:
|
|
|
89
89
|
version: 3.0.0
|
|
90
90
|
type: :runtime
|
|
91
91
|
prerelease: false
|
|
92
|
-
version_requirements: *
|
|
92
|
+
version_requirements: *2164267400
|
|
93
93
|
- !ruby/object:Gem::Dependency
|
|
94
94
|
name: activesupport
|
|
95
|
-
requirement: &
|
|
95
|
+
requirement: &2164266480 !ruby/object:Gem::Requirement
|
|
96
96
|
none: false
|
|
97
97
|
requirements:
|
|
98
98
|
- - ! '>='
|
|
@@ -100,10 +100,10 @@ dependencies:
|
|
|
100
100
|
version: 3.0.0
|
|
101
101
|
type: :runtime
|
|
102
102
|
prerelease: false
|
|
103
|
-
version_requirements: *
|
|
103
|
+
version_requirements: *2164266480
|
|
104
104
|
- !ruby/object:Gem::Dependency
|
|
105
105
|
name: resque
|
|
106
|
-
requirement: &
|
|
106
|
+
requirement: &2164265680 !ruby/object:Gem::Requirement
|
|
107
107
|
none: false
|
|
108
108
|
requirements:
|
|
109
109
|
- - ! '>='
|
|
@@ -111,10 +111,10 @@ dependencies:
|
|
|
111
111
|
version: '0'
|
|
112
112
|
type: :runtime
|
|
113
113
|
prerelease: false
|
|
114
|
-
version_requirements: *
|
|
114
|
+
version_requirements: *2164265680
|
|
115
115
|
- !ruby/object:Gem::Dependency
|
|
116
116
|
name: ruby-iactionable
|
|
117
|
-
requirement: &
|
|
117
|
+
requirement: &2164264420 !ruby/object:Gem::Requirement
|
|
118
118
|
none: false
|
|
119
119
|
requirements:
|
|
120
120
|
- - ! '>='
|
|
@@ -122,7 +122,7 @@ dependencies:
|
|
|
122
122
|
version: 0.1.2
|
|
123
123
|
type: :runtime
|
|
124
124
|
prerelease: false
|
|
125
|
-
version_requirements: *
|
|
125
|
+
version_requirements: *2164264420
|
|
126
126
|
description: Wrapper for IActionable's restful API and an "acts-as" style interface
|
|
127
127
|
for models to behave as profiles and drive game events.
|
|
128
128
|
email:
|
|
@@ -175,10 +175,13 @@ files:
|
|
|
175
175
|
- doc/js/jquery.js
|
|
176
176
|
- doc/method_list.html
|
|
177
177
|
- doc/top-level-namespace.html
|
|
178
|
-
- lib/generators/riaction/USAGE
|
|
179
|
-
- lib/generators/riaction/
|
|
180
|
-
- lib/generators/riaction/templates/i_actionable.yml
|
|
178
|
+
- lib/generators/riaction/install/USAGE
|
|
179
|
+
- lib/generators/riaction/install/install_generator.rb
|
|
180
|
+
- lib/generators/riaction/install/templates/i_actionable.yml
|
|
181
|
+
- lib/generators/riaction/install/templates/riaction.rb
|
|
182
|
+
- lib/generators/riaction_generator.rb
|
|
181
183
|
- lib/riaction.rb
|
|
184
|
+
- lib/riaction/api_failure.rb
|
|
182
185
|
- lib/riaction/constants.rb
|
|
183
186
|
- lib/riaction/crud_event_callback.rb
|
|
184
187
|
- lib/riaction/event_performer.rb
|
|
@@ -189,7 +192,6 @@ files:
|
|
|
189
192
|
- lib/riaction/version.rb
|
|
190
193
|
- lib/rspec/matchers/riaction.rb
|
|
191
194
|
- lib/tasks/riaction.rake
|
|
192
|
-
- riaction-1.3.5.gem
|
|
193
195
|
- riaction.gemspec
|
|
194
196
|
- spec/custom_matchers_spec.rb
|
|
195
197
|
- spec/event_performer_spec.rb
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
class RiactionGenerator < Rails::Generators::Base
|
|
2
|
-
source_root File.expand_path("../templates", __FILE__)
|
|
3
|
-
argument :credentials, :type => :array, :required => true, :banner => "environment:app_key:api_key environment:app_key:api_key"
|
|
4
|
-
|
|
5
|
-
def create_credentials_file
|
|
6
|
-
credentials.map!{|credential| { :env => credential[credential_regexp,1],
|
|
7
|
-
:app_key => credential[credential_regexp,2],
|
|
8
|
-
:api_key => credential[credential_regexp,3] } }
|
|
9
|
-
template "i_actionable.yml", "config/i_actionable.yml"
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
private
|
|
13
|
-
|
|
14
|
-
def credential_regexp
|
|
15
|
-
/^(\w+):(\w+):(\w+)$/
|
|
16
|
-
end
|
|
17
|
-
end
|