metaforce-beta 1.2.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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +1 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +193 -0
- data/Rakefile +10 -0
- data/bin/metaforce +14 -0
- data/examples/example.rb +52 -0
- data/lib/metaforce.rb +34 -0
- data/lib/metaforce/abstract_client.rb +86 -0
- data/lib/metaforce/cli.rb +130 -0
- data/lib/metaforce/client.rb +31 -0
- data/lib/metaforce/config.rb +100 -0
- data/lib/metaforce/job.rb +203 -0
- data/lib/metaforce/job/crud.rb +13 -0
- data/lib/metaforce/job/deploy.rb +87 -0
- data/lib/metaforce/job/retrieve.rb +102 -0
- data/lib/metaforce/login.rb +39 -0
- data/lib/metaforce/manifest.rb +106 -0
- data/lib/metaforce/metadata/client.rb +18 -0
- data/lib/metaforce/metadata/client/crud.rb +86 -0
- data/lib/metaforce/metadata/client/file.rb +113 -0
- data/lib/metaforce/reporters.rb +2 -0
- data/lib/metaforce/reporters/base_reporter.rb +56 -0
- data/lib/metaforce/reporters/deploy_reporter.rb +69 -0
- data/lib/metaforce/reporters/retrieve_reporter.rb +11 -0
- data/lib/metaforce/services/client.rb +84 -0
- data/lib/metaforce/version.rb +3 -0
- data/metaforce.gemspec +34 -0
- data/spec/fixtures/package.xml +17 -0
- data/spec/fixtures/payload.zip +0 -0
- data/spec/fixtures/requests/check_deploy_status/done.xml +33 -0
- data/spec/fixtures/requests/check_deploy_status/error.xml +26 -0
- data/spec/fixtures/requests/check_retrieve_status/success.xml +37 -0
- data/spec/fixtures/requests/check_status/done.xml +19 -0
- data/spec/fixtures/requests/check_status/not_done.xml +19 -0
- data/spec/fixtures/requests/create/in_progress.xml +12 -0
- data/spec/fixtures/requests/delete/in_progress.xml +12 -0
- data/spec/fixtures/requests/deploy/in_progress.xml +13 -0
- data/spec/fixtures/requests/describe_layout/success.xml +15 -0
- data/spec/fixtures/requests/describe_metadata/success.xml +230 -0
- data/spec/fixtures/requests/foo/invalid_session.xml +15 -0
- data/spec/fixtures/requests/list_metadata/no_result.xml +6 -0
- data/spec/fixtures/requests/list_metadata/objects.xml +33 -0
- data/spec/fixtures/requests/login/failure.xml +15 -0
- data/spec/fixtures/requests/login/success.xml +39 -0
- data/spec/fixtures/requests/retrieve/in_progress.xml +12 -0
- data/spec/fixtures/requests/send_email/success.xml +1 -0
- data/spec/fixtures/requests/update/in_progress.xml +12 -0
- data/spec/lib/cli_spec.rb +42 -0
- data/spec/lib/client_spec.rb +39 -0
- data/spec/lib/config_spec.rb +12 -0
- data/spec/lib/job/deploy_spec.rb +54 -0
- data/spec/lib/job/retrieve_spec.rb +28 -0
- data/spec/lib/job_spec.rb +111 -0
- data/spec/lib/login_spec.rb +18 -0
- data/spec/lib/manifest_spec.rb +35 -0
- data/spec/lib/metadata/client_spec.rb +135 -0
- data/spec/lib/metaforce_spec.rb +42 -0
- data/spec/lib/reporters/base_reporter_spec.rb +79 -0
- data/spec/lib/reporters/deploy_reporter_spec.rb +124 -0
- data/spec/lib/reporters/retrieve_reporter_spec.rb +14 -0
- data/spec/lib/services/client_spec.rb +37 -0
- data/spec/spec_helper.rb +37 -0
- data/spec/support/client.rb +39 -0
- data/wsdl/23.0/metadata.xml +3520 -0
- data/wsdl/23.0/partner.xml +3190 -0
- data/wsdl/26.0/metadata.xml +4750 -0
- data/wsdl/26.0/partner.xml +3340 -0
- data/wsdl/34.0/metadata.xml +7981 -0
- data/wsdl/34.0/partner.xml +5398 -0
- data/wsdl/35.0/metadata.xml +8183 -0
- data/wsdl/35.0/partner.xml +5755 -0
- data/wsdl/40.0/metadata.xml +29052 -0
- data/wsdl/40.0/partner.xml +7642 -0
- metadata +327 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
require 'listen'
|
|
2
|
+
require 'thor'
|
|
3
|
+
require 'metaforce/reporters'
|
|
4
|
+
|
|
5
|
+
Metaforce.configure do |config|
|
|
6
|
+
config.log = false
|
|
7
|
+
config.threading = false
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
module Metaforce
|
|
11
|
+
class CLI < Thor
|
|
12
|
+
CONFIG_FILE = '.metaforce.yml'
|
|
13
|
+
|
|
14
|
+
include Thor::Actions
|
|
15
|
+
|
|
16
|
+
class << self
|
|
17
|
+
def credential_options
|
|
18
|
+
method_option :username, :aliases => '-u', :desc => 'Username.'
|
|
19
|
+
method_option :password, :aliases => '-p', :desc => 'Password.'
|
|
20
|
+
method_option :security_token, :aliases => '-t', :desc => 'Security Token.'
|
|
21
|
+
method_option :environment, :aliases => '-e', :default => 'default', :desc => 'Environment to use from config file (if present).'
|
|
22
|
+
method_option :host, :aliases => '-h', :desc => 'Salesforce host to connect to.'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def deploy_options
|
|
26
|
+
method_option :deploy_options, :aliases => '-o', :type => :hash, :default => { :run_all_tests => true }, :desc => 'Deploy Options'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def retrieve_options
|
|
30
|
+
method_option :retrieve_options, :aliases => '-o', :type => :hash, :default => {}, :desc => 'Retrieve Options'
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
desc 'deploy <path>', 'Deploy <path> to the target organization.'
|
|
35
|
+
|
|
36
|
+
credential_options
|
|
37
|
+
deploy_options
|
|
38
|
+
|
|
39
|
+
def deploy(path)
|
|
40
|
+
say "Deploying: #{path} ", :cyan
|
|
41
|
+
say "#{options[:deploy_options].inspect}"
|
|
42
|
+
client.deploy(path, options[:deploy_options].symbolize_keys!)
|
|
43
|
+
.on_complete { |job| report job.result, :deploy }
|
|
44
|
+
.on_error(&error)
|
|
45
|
+
.on_poll(&polling)
|
|
46
|
+
.perform
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
desc 'retrieve <manifest> <path>', 'Retrieve the components specified in <manifest> (package.xml) to <path>.'
|
|
50
|
+
|
|
51
|
+
credential_options
|
|
52
|
+
retrieve_options
|
|
53
|
+
|
|
54
|
+
def retrieve(manifest, path=nil)
|
|
55
|
+
unless path
|
|
56
|
+
path = manifest
|
|
57
|
+
manifest = File.join(path, 'package.xml')
|
|
58
|
+
end
|
|
59
|
+
say "Retrieving: #{manifest} ", :cyan
|
|
60
|
+
say "#{options[:retrieve_options].inspect}"
|
|
61
|
+
client.retrieve_unpackaged(manifest, options[:retrieve_options].symbolize_keys!)
|
|
62
|
+
.extract_to(path)
|
|
63
|
+
.on_complete { |job| report(job.result, :retrieve) }
|
|
64
|
+
.on_complete { |job| say "Extracted: #{path}", :green }
|
|
65
|
+
.on_error(&error)
|
|
66
|
+
.on_poll(&polling)
|
|
67
|
+
.perform
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
desc 'watch <path>', 'Deploy <path> to the target organization whenever files are changed.'
|
|
71
|
+
|
|
72
|
+
credential_options
|
|
73
|
+
deploy_options
|
|
74
|
+
|
|
75
|
+
def watch(path)
|
|
76
|
+
say "Watching: #{path}"
|
|
77
|
+
@watching = true
|
|
78
|
+
Listen.to(path) { deploy path }
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
def report(results, type)
|
|
84
|
+
reporter = "Metaforce::Reporters::#{type.to_s.camelize}Reporter".constantize.new(results)
|
|
85
|
+
reporter.report
|
|
86
|
+
exit 1 if reporter.issues?
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def exit(status)
|
|
90
|
+
super(status) if not watching?
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def watching?
|
|
94
|
+
!!@watching
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def error
|
|
98
|
+
proc { |job| say "Error: #{job.result.inspect}" }
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def polling
|
|
102
|
+
proc { |job| say 'Polling ...', :cyan }
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def client
|
|
106
|
+
credentials = Thor::CoreExt::HashWithIndifferentAccess.new(environment_config)
|
|
107
|
+
credentials.merge!(options.slice(:username, :password, :security_token, :host))
|
|
108
|
+
credentials.tap do |credentials|
|
|
109
|
+
credentials[:username] ||= ask('username:')
|
|
110
|
+
credentials[:password] ||= ask('password:')
|
|
111
|
+
credentials[:security_token] ||= ask('security token:')
|
|
112
|
+
end
|
|
113
|
+
Metaforce.configuration.host = credentials[:host]
|
|
114
|
+
Metaforce.new credentials
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def environment_config
|
|
118
|
+
(config && config[options[:environment]]) ? config[options[:environment]] : {}
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def config
|
|
122
|
+
YAML.load(File.open(config_file)) if File.exists?(config_file)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def config_file
|
|
126
|
+
File.expand_path(CONFIG_FILE)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Metaforce
|
|
2
|
+
class Client
|
|
3
|
+
def initialize(options = {})
|
|
4
|
+
@options = options
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
# Public: Used to interact with the Metadata API.
|
|
8
|
+
def metadata
|
|
9
|
+
@metadata ||= Metaforce::Metadata::Client.new(@options)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Public: Used to interact with the Services API.
|
|
13
|
+
def services
|
|
14
|
+
@services ||= Metaforce::Services::Client.new(@options)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def inspect
|
|
18
|
+
"#<#{self.class} @options=#{@options.inspect}>"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def method_missing(method, *args, &block)
|
|
22
|
+
if metadata.respond_to? method, false
|
|
23
|
+
metadata.send(method, *args, &block)
|
|
24
|
+
elsif services.respond_to? method, false
|
|
25
|
+
services.send(method, *args, &block)
|
|
26
|
+
else
|
|
27
|
+
super
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
module Metaforce
|
|
2
|
+
class << self
|
|
3
|
+
attr_writer :log
|
|
4
|
+
|
|
5
|
+
# Returns the current Configuration
|
|
6
|
+
#
|
|
7
|
+
# Metaforce.configuration.username = "username"
|
|
8
|
+
# Metaforce.configuration.password = "password"
|
|
9
|
+
def configuration
|
|
10
|
+
@configuration ||= Configuration.new
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Yields the Configuration
|
|
14
|
+
#
|
|
15
|
+
# Metaforce.configure do |config|
|
|
16
|
+
# config.username = "username"
|
|
17
|
+
# config.password = "password"
|
|
18
|
+
# end
|
|
19
|
+
def configure
|
|
20
|
+
yield configuration
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def log?
|
|
24
|
+
@log ||= false
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def log(message)
|
|
28
|
+
return unless Metaforce.log?
|
|
29
|
+
Metaforce.configuration.logger.send :debug, message
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class Configuration
|
|
34
|
+
# The Salesforce API version to use. Defaults to 23.0
|
|
35
|
+
attr_accessor :api_version
|
|
36
|
+
# The username to use during login.
|
|
37
|
+
attr_accessor :username
|
|
38
|
+
# The password to use during login.
|
|
39
|
+
attr_accessor :password
|
|
40
|
+
# The security token to use during login.
|
|
41
|
+
attr_accessor :security_token
|
|
42
|
+
# Set this to true if you're authenticating with a Sandbox instance.
|
|
43
|
+
# Defaults to false.
|
|
44
|
+
attr_accessor :host
|
|
45
|
+
# A block that gets called when the session becomes invalid and the
|
|
46
|
+
# client needs to reauthenticate. Passes in the client and the client
|
|
47
|
+
# options. The block should set the options to a hash containing a valid
|
|
48
|
+
# session_id and service urls.
|
|
49
|
+
attr_accessor :authentication_handler
|
|
50
|
+
# Enables or disables threading when polling for job status. If disabled,
|
|
51
|
+
# calling .perform on a job will block until completion and all callbacks
|
|
52
|
+
# have run. (default: true).
|
|
53
|
+
attr_accessor :threading
|
|
54
|
+
|
|
55
|
+
def initialize
|
|
56
|
+
@threading = false
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def api_version
|
|
60
|
+
@api_version ||= '26.0'
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def host
|
|
64
|
+
@host ||= 'login.salesforce.com'
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def authentication_handler
|
|
68
|
+
@authentication_handler ||= lambda { |client, options|
|
|
69
|
+
Metaforce.login(options)
|
|
70
|
+
}
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def log=(log)
|
|
74
|
+
Savon.configure do |config|
|
|
75
|
+
config.log = log
|
|
76
|
+
end
|
|
77
|
+
HTTPI.log = log
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def partner_wsdl
|
|
81
|
+
File.join(wsdl, 'partner.xml')
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def metadata_wsdl
|
|
85
|
+
File.join(wsdl, 'metadata.xml')
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def endpoint
|
|
89
|
+
"https://#{host}/services/Soap/u/#{api_version}"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def wsdl
|
|
93
|
+
File.expand_path("../../../wsdl/#{api_version}", __FILE__)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def logger
|
|
97
|
+
@logger ||= ::Logger.new STDOUT
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
require 'zip'
|
|
2
|
+
require 'base64'
|
|
3
|
+
|
|
4
|
+
module Metaforce
|
|
5
|
+
class Job
|
|
6
|
+
DELAY_START = 1
|
|
7
|
+
DELAY_MULTIPLIER = 2
|
|
8
|
+
|
|
9
|
+
autoload :Deploy, 'metaforce/job/deploy'
|
|
10
|
+
autoload :Retrieve, 'metaforce/job/retrieve'
|
|
11
|
+
autoload :CRUD, 'metaforce/job/crud'
|
|
12
|
+
|
|
13
|
+
# Public: The id of the AsyncResult returned from Salesforce for
|
|
14
|
+
# this job.
|
|
15
|
+
attr_reader :id
|
|
16
|
+
|
|
17
|
+
# Public: Instantiate a new job. Doesn't actually do anything until
|
|
18
|
+
# .perform is called.
|
|
19
|
+
#
|
|
20
|
+
# Examples
|
|
21
|
+
#
|
|
22
|
+
# job = Metaforce::Job.new(client)
|
|
23
|
+
# # => #<Metaforce::Job @id=nil>
|
|
24
|
+
#
|
|
25
|
+
# Returns self.
|
|
26
|
+
def initialize(client)
|
|
27
|
+
@_callbacks = Hash.new { |h,k| h[k] = [] }
|
|
28
|
+
@client = client
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Public: Perform the job.
|
|
32
|
+
#
|
|
33
|
+
# Examples
|
|
34
|
+
#
|
|
35
|
+
# job = Metaforce::Job.new
|
|
36
|
+
# job.perform
|
|
37
|
+
# # => #<Metaforce::Job @id=nil>
|
|
38
|
+
#
|
|
39
|
+
# Returns self.
|
|
40
|
+
def perform
|
|
41
|
+
start_heart_beat
|
|
42
|
+
self
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Public: Utility method to determine if .perform has been called yet.
|
|
46
|
+
#
|
|
47
|
+
# Returns true if @id is set, false otherwise.
|
|
48
|
+
def started?
|
|
49
|
+
!!@id
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Public: Register a block to be called when an event occurs.
|
|
53
|
+
#
|
|
54
|
+
# Yields the job.
|
|
55
|
+
#
|
|
56
|
+
# &block - Proc or Lambda to be run when the event is triggered.
|
|
57
|
+
#
|
|
58
|
+
# Examples
|
|
59
|
+
#
|
|
60
|
+
# job.on_complete do |job|
|
|
61
|
+
# puts "Job ##{job.id} completed!"
|
|
62
|
+
# end
|
|
63
|
+
#
|
|
64
|
+
# job.on_error do |job|
|
|
65
|
+
# puts "Job failed!"
|
|
66
|
+
# end
|
|
67
|
+
#
|
|
68
|
+
# job.on_poll do |job|
|
|
69
|
+
# puts "Polled status for #{job.id}"
|
|
70
|
+
# end
|
|
71
|
+
#
|
|
72
|
+
# Returns self.
|
|
73
|
+
#
|
|
74
|
+
# Signature
|
|
75
|
+
#
|
|
76
|
+
# on_complete(&block)
|
|
77
|
+
# on_error(&block)
|
|
78
|
+
# on_poll(&block)
|
|
79
|
+
%w[complete error poll].each do |type|
|
|
80
|
+
define_method :"on_#{type}" do |&block|
|
|
81
|
+
@_callbacks[:"on_#{type}"] << block
|
|
82
|
+
self
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Public: Queries the job status from the API.
|
|
87
|
+
#
|
|
88
|
+
# Examples
|
|
89
|
+
#
|
|
90
|
+
# job.status
|
|
91
|
+
# # => { :id => '1234', :done => false, ... }
|
|
92
|
+
#
|
|
93
|
+
# Returns the AsyncResult (http://www.salesforce.com/us/developer/docs/api_meta/Content/meta_asyncresult.htm).
|
|
94
|
+
def status
|
|
95
|
+
@status ||= client.status(id)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Public: Returns true if the job has completed.
|
|
99
|
+
#
|
|
100
|
+
# Examples
|
|
101
|
+
#
|
|
102
|
+
# job.done
|
|
103
|
+
# # => true
|
|
104
|
+
#
|
|
105
|
+
# Returns true if the job has completed, false otherwise.
|
|
106
|
+
def done?
|
|
107
|
+
status.done
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Public: Returns the state if the job has finished processing.
|
|
111
|
+
#
|
|
112
|
+
# Examples
|
|
113
|
+
#
|
|
114
|
+
# job.state
|
|
115
|
+
# # => 'Completed'
|
|
116
|
+
#
|
|
117
|
+
# Returns the state of the job.
|
|
118
|
+
def state
|
|
119
|
+
status.state
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Public: Check if the job is in a given state.
|
|
123
|
+
#
|
|
124
|
+
# Examples
|
|
125
|
+
#
|
|
126
|
+
# job.queued?
|
|
127
|
+
# # => false
|
|
128
|
+
#
|
|
129
|
+
# Returns true or false.
|
|
130
|
+
#
|
|
131
|
+
# Signature
|
|
132
|
+
#
|
|
133
|
+
# queued?
|
|
134
|
+
# in_progress?
|
|
135
|
+
# completed?
|
|
136
|
+
# error?
|
|
137
|
+
%w[Queued InProgress Completed Error].each do |state|
|
|
138
|
+
define_method :"#{state.underscore}?" do; self.state == state end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def inspect
|
|
142
|
+
"#<#{self.class} @id=#{@id.inspect}>"
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def self.disable_threading!
|
|
146
|
+
ActiveSupport::Deprecation.warn <<-WARNING.strip_heredoc
|
|
147
|
+
Metaforce::Job.disable_threading! is deprecated. Use Metaforce.configuration.threading = false instead.
|
|
148
|
+
WARNING
|
|
149
|
+
Metaforce.configuration.threading = false
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
private
|
|
153
|
+
attr_reader :client
|
|
154
|
+
|
|
155
|
+
# Internal: Starts a heart beat in a thread, which polls the job status
|
|
156
|
+
# until it has completed or timed out.
|
|
157
|
+
def start_heart_beat
|
|
158
|
+
if threading?
|
|
159
|
+
Thread.abort_on_exception = true
|
|
160
|
+
@heart_beat ||= Thread.new &run_loop
|
|
161
|
+
else
|
|
162
|
+
run_loop.call
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Internal: Starts the run loop, and blocks until the job has completed or
|
|
167
|
+
# failed.
|
|
168
|
+
def run_loop
|
|
169
|
+
proc {
|
|
170
|
+
delay = DELAY_START
|
|
171
|
+
loop do
|
|
172
|
+
@status = nil
|
|
173
|
+
sleep (delay = delay * DELAY_MULTIPLIER)
|
|
174
|
+
trigger :on_poll
|
|
175
|
+
if completed? || error?
|
|
176
|
+
trigger callback_type
|
|
177
|
+
Thread.stop if threading?
|
|
178
|
+
break
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
}
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def trigger(type)
|
|
185
|
+
@_callbacks[type].each do |block|
|
|
186
|
+
block.call(self)
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def callback_type
|
|
191
|
+
if completed?
|
|
192
|
+
:on_complete
|
|
193
|
+
elsif error?
|
|
194
|
+
:on_error
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def threading?
|
|
199
|
+
Metaforce.configuration.threading
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
end
|
|
203
|
+
end
|