metaforce 0.5.3 → 1.0.0a

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/.gitignore +1 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +1 -11
  4. data/LICENSE +22 -0
  5. data/README.md +91 -96
  6. data/Rakefile +6 -14
  7. data/examples/example.rb +51 -0
  8. data/lib/metaforce/abstract_client.rb +76 -0
  9. data/lib/metaforce/client.rb +27 -0
  10. data/lib/metaforce/config.rb +41 -19
  11. data/lib/metaforce/job/crud.rb +13 -0
  12. data/lib/metaforce/job/deploy.rb +87 -0
  13. data/lib/metaforce/job/retrieve.rb +92 -0
  14. data/lib/metaforce/job.rb +183 -0
  15. data/lib/metaforce/login.rb +39 -0
  16. data/lib/metaforce/manifest.rb +18 -93
  17. data/lib/metaforce/metadata/client/crud.rb +86 -0
  18. data/lib/metaforce/metadata/client/file.rb +113 -0
  19. data/lib/metaforce/metadata/client.rb +7 -225
  20. data/lib/metaforce/services/client.rb +45 -86
  21. data/lib/metaforce/version.rb +1 -1
  22. data/lib/metaforce.rb +27 -7
  23. data/metaforce.gemspec +19 -16
  24. data/spec/fixtures/package.xml +1 -1
  25. data/spec/fixtures/payload.zip +0 -0
  26. data/spec/fixtures/requests/{describe_layout → foo}/invalid_session.xml +0 -0
  27. data/spec/fixtures/requests/send_email/success.xml +1 -0
  28. data/spec/lib/client_spec.rb +34 -0
  29. data/spec/lib/config_spec.rb +8 -50
  30. data/spec/lib/job/deploy_spec.rb +53 -0
  31. data/spec/lib/job/retrieve_spec.rb +28 -0
  32. data/spec/lib/job_spec.rb +95 -0
  33. data/spec/lib/login_spec.rb +18 -0
  34. data/spec/lib/manifest_spec.rb +22 -168
  35. data/spec/lib/metadata/client_spec.rb +84 -179
  36. data/spec/lib/metaforce_spec.rb +20 -0
  37. data/spec/lib/services/client_spec.rb +22 -35
  38. data/spec/spec_helper.rb +24 -3
  39. data/spec/support/client.rb +38 -0
  40. data/wsdl/26.0/metadata.xml +4750 -0
  41. data/wsdl/26.0/partner.xml +3340 -0
  42. metadata +114 -77
  43. data/Guardfile +0 -9
  44. data/bin/metaforce +0 -6
  45. data/lib/metaforce/core_extensions/string.rb +0 -31
  46. data/lib/metaforce/core_extensions.rb +0 -1
  47. data/lib/metaforce/custom_actions.rb +0 -29
  48. data/lib/metaforce/error.rb +0 -3
  49. data/lib/metaforce/login_details.rb +0 -28
  50. data/lib/metaforce/metadata/crud.rb +0 -103
  51. data/lib/metaforce/metadata/file.rb +0 -74
  52. data/lib/metaforce/metadata/transaction.rb +0 -100
  53. data/lib/metaforce/metadata.rb +0 -4
  54. data/lib/metaforce/rake/deploy.rb +0 -35
  55. data/lib/metaforce/rake/retrieve.rb +0 -39
  56. data/lib/metaforce/rake/tests.rb +0 -62
  57. data/lib/metaforce/rake.rb +0 -43
  58. data/lib/metaforce/services.rb +0 -1
  59. data/lib/metaforce/tasks/README.md +0 -62
  60. data/lib/metaforce/tasks/metaforce.rake +0 -5
  61. data/lib/metaforce/thor/metaforce.rb +0 -117
  62. data/lib/metaforce/types.rb +0 -249
  63. data/spec/.gitignore +0 -1
  64. data/spec/fixtures/sample/Rakefile +0 -2
  65. data/spec/fixtures/sample/metaforce.yml +0 -13
  66. data/spec/fixtures/sample/src/classes/TestClass.cls +0 -2
  67. data/spec/fixtures/sample/src/classes/TestClass.cls-meta.xml +0 -5
  68. data/spec/fixtures/sample/src/package.xml +0 -8
  69. data/spec/lib/core_extensions/string_spec.rb +0 -23
  70. data/spec/lib/metadata/crud_spec.rb +0 -66
  71. data/spec/lib/metadata/file_spec.rb +0 -17
  72. data/spec/lib/metadata/transaction_spec.rb +0 -68
data/.gitignore CHANGED
@@ -2,6 +2,7 @@
2
2
  .bundle
3
3
  Gemfile.lock
4
4
  pkg/*
5
+ examples/tmp
5
6
  deploy.zip
6
7
  retrieve.zip
7
8
  test.rb
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/Gemfile CHANGED
@@ -1,14 +1,4 @@
1
- source "http://rubygems.org"
2
- gem 'highline'
3
- gem 'thor'
1
+ source :rubygems
4
2
 
5
3
  # Specify your gem's dependencies in metaforce.gemspec
6
4
  gemspec
7
-
8
- group :development do
9
- gem "guard"
10
- gem "guard-rspec"
11
- gem "growl"
12
- gem "yard"
13
- gem "redcarpet"
14
- end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Eric J. Holmes
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,139 +1,134 @@
1
- # Metaforce [![travis-ci](https://secure.travis-ci.org/ejholmes/metaforce.png)](https://secure.travis-ci.org/ejholmes/metaforce)
1
+ # Metaforce
2
2
 
3
- Metaforce is a Ruby gem for interacting with the [Salesforce Metadata API](http://www.salesforce.com/us/developer/docs/api_meta/index.htm).
4
- The goal of this project is to make the [Migration Tool](http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_deploying_ant.htm) obsolete, favoring Rake over Ant.
3
+ [![travis-ci](https://secure.travis-ci.org/ejholmes/metaforce.png)](https://secure.travis-ci.org/ejholmes/metaforce) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/ejholmes/metaforce) [![Dependency Status](https://gemnasium.com/ejholmes/metaforce.png)](https://gemnasium.com/ejholmes/metaforce)
4
+
5
+ Metaforce is a Ruby gem for interacting with the Salesforce [Metadata](http://www.salesforce.com/us/developer/docs/api_meta/index.htm)
6
+ and [Services](http://www.salesforce.com/us/developer/docs/api/index.htm) APIs.
5
7
 
6
8
  [Documentation](http://rubydoc.info/gems/metaforce/frames)
7
9
 
8
10
  ## Installation
11
+
9
12
  ```bash
10
13
  gem install metaforce
11
14
  ```
12
15
 
13
16
  ## Usage
14
- ``` ruby
15
- client = Metaforce::Metadata::Client.new :username => 'username',
16
- :password => 'password',
17
- :security_token => 'security token')
18
-
19
- # Describe the metadata on the organization
20
- client.metadata_objects
21
- # => [{ :child_xml_names => "CustomLabel", :directory_name => "labels" ... }]
22
-
23
- # List all custom objects
24
- client.list(:custom_object)
25
- # => [{ :created_by_id => "005U0000000EGpcIAG", :created_by_name => "Eric Holmes", ... }]
26
-
27
- # Deploy metadata to the organization
28
- deployment = client.deploy(File.expand_path('path/to/src'))
29
- # => #<Metaforce::Transaction:0x00000102779bf8 @id="04sU0000000WNWoIAO" @type=:deploy>
30
17
 
31
- # Get the result
32
- deployment.result
33
- # => { :id => "04sU0000000WNWoIAO", :messages => [{ :changed => true ... :success => true }
18
+ ### Initialization
34
19
 
35
- # Retrieve the metadata components specified in package.xml and unzip to the "retrieved" directory
36
- client.retrieve(File.expand_path('path/to/package.xml')).to('retrieved')
20
+ #### Username and Password
37
21
 
38
- # Create a Visualforce page
39
- client.create_apex_page(:full_name => 'TestPage', :label => 'TestPage')
22
+ To initialize a new client, you call `Metaforce.new` with a hash that specifies
23
+ the `:username`, `:password`, and `:security_token`.
40
24
 
41
- # Update a Visualforce page
42
- client.update_apex_page('OldName', :full_name => 'NewName')
43
-
44
- # Delete a Visualforce page
45
- client.delete_apex_page('TestPage')
25
+ ```ruby
26
+ client = Metaforce.new :username => 'username',
27
+ :password => 'password',
28
+ :security_token => 'security token'
46
29
  ```
47
30
 
48
- ## Roadmap
49
- This gem is far from being feature complete. Here's a list of things that still
50
- need to be done.
51
-
52
- * Implement command line utility that can watch the directory and deploy when a
53
- file changes.
54
- * Implement some helper methods for diffing metadata.
55
- * Ability to deploy directly from a git repository.
56
- * And some other stuff that I haven't quite thought of yet...
57
-
58
- ## Contributing
59
- If you'd like to contribute code, please fork the repository and implement your
60
- feature on a new branch, then send me a pull request with a detailed
61
- description. Please provide applicable rspec specs.
62
-
63
- ## Version History
64
- **0.5.3** (June 8, 2012)
65
- * Only trigger reauthentication if the response contains `INVALID_SESSION_ID`.
31
+ #### Asynchronous Tasks
66
32
 
67
- **0.5.2** (June 8, 2012)
68
- * The services client now reauthentications on Savon::SOAP::Fault.
33
+ Some calls to the SOAP API's are performed asynchronously (such as deployments),
34
+ meaning the response needs to be polled for. Any call to the SOAP API's that
35
+ are performed asynchronously will return a Metaforce::Job object, which can be used to
36
+ subscribe to `on_complete` and `on_error` callbacks. The Metaforce::Job class
37
+ will poll the status of the asynchronous job in a thread until it completes or
38
+ fails.
69
39
 
70
- **0.5.1**
40
+ * * *
71
41
 
72
- * Add thor integration.
42
+ ### deploy(path, options={})
73
43
 
74
- **0.5.0** (March 23, 2012)
44
+ Takes a path (can be a path to a directory, or a zip file), and a set of
45
+ [DeployOptions](http://www.salesforce.com/us/developer/docs/api_meta/Content/meta_deploy.htm#deploy_options)
46
+ and returns a `Metaforce::Job::Deploy`.
75
47
 
76
- * Implemented CRUD calls.
77
-
78
- **0.4.1** (March 8, 2012)
79
-
80
- * Bug fixes
48
+ ```ruby
49
+ client.deploy(File.expand_path('./src'))
50
+ .on_complete { |job| puts "Finished deploy #{job.id}!" }
51
+ .on_error { |job| puts "Something bad happened!" }
52
+ .perform
53
+ #=> #<Metaforce::Job::Deploy @id='1234'>
54
+ ```
81
55
 
82
- **0.4.0** (March 2, 2012)
56
+ * * *
83
57
 
84
- * Various bug fixes and improvements.
85
- * Removed DSL to focus on core functionality.
58
+ ### retrieve\_unpackaged(manifest, options={})
86
59
 
87
- **0.3.5** (February 11, 2012)
60
+ Takes a manifest (`Metaforce::Manifest` or a path to a package.xml file) and a
61
+ set of [RetrieveOptions](http://www.salesforce.com/us/developer/docs/api_meta/Content/meta_retrieve_request.htm)
62
+ and returns a `Metaforce::Job::Retrieve`.
88
63
 
89
- * Allow rake tasks to get credentials from a metaforce.yml file.
64
+ ```ruby
65
+ manifest = Metaforce::Manifest.new(:custom_object => ['Account'])
66
+ client.retrieve_unpackaged(manifest)
67
+ .extract_to('./tmp')
68
+ .perform
69
+ #=> #<Metaforce::Job::Retrieve @id='1234'>
70
+ ```
90
71
 
91
- **0.3.4** (February 9, 2012)
72
+ * * *
92
73
 
93
- * Add rake tasks.
74
+ ### create(type, metadata={})
94
75
 
95
- **0.3.3** (February 9, 2012)
76
+ Takes a Symbol type and a Hash of [Metadata Attributes](http://www.salesforce.com/us/developer/docs/api_meta/Content/meta_types_list.htm)
77
+ and returns a `Metaforce::Job::CRUD`.
96
78
 
97
- * Added a logger for logging requests.
98
- * Allow api version to be set when calling `Metaforce::Metadata::Client.describe`.
79
+ ```ruby
80
+ client.create(:apex_page, full_name: 'Foobar', content: 'Hello World!')
81
+ .on_complete { |job| puts "ApexPage created." }
82
+ .perform
83
+ #=> #<Metaforce::Job::CRUD @id='1234'>
84
+ ```
99
85
 
100
- **0.3.2** (February 3, 2012)
86
+ * * *
101
87
 
102
- * Improved documentation.
103
- * Added `.status` method to Transaction class.
88
+ ### update(type, current\_name metadata={})
104
89
 
105
- **0.3.1** (February 3, 2012)
90
+ Takes a Symbol type, the current `full_name` of the resource, and a Hash of
91
+ [Metadata Attributes](http://www.salesforce.com/us/developer/docs/api_meta/Content/meta_types_list.htm)
92
+ and returns a `Metaforce::Job::CRUD`.
106
93
 
107
- * Dynamically defined helper methods for .list (e.g. `client.list_apex_class`, `client.list_custom_object`).
108
- * The `Metaforce::Metadata::Client.describe` method now caches the results to minimize latency. `describe!`
109
- can be used to force a refresh.
94
+ ```ruby
95
+ client.update(:apex_page, 'Foobar', content: 'Hello World! Some new content!')
96
+ .on_complete { |job| puts "ApexPage updated." }
97
+ .perform
98
+ #=> #<Metaforce::Job::CRUD @id='1234'>
99
+ ```
110
100
 
111
- **0.3.0.alpha** (January 29, 2012)
101
+ * * *
112
102
 
113
- * Ability to retrieve metadata from an organization.
114
- * Added a DSL.
103
+ ### delete(type, \*args)
115
104
 
116
- **0.2.0.alpha** (January 28, 2012)
105
+ Takes a Symbol type, and the `full_name` of a resource and returns a `Metaforce::Job::CRUD`.
117
106
 
118
- * Gem now supports interacting with the metadata api.
107
+ ```ruby
108
+ client.delete(:apex_page, 'Foobar')
109
+ .on_complete { |job| puts "ApexPage deleted." }
110
+ .perform
111
+ #=> #<Metaforce::Job::CRUD @id='1234'>
112
+ ```
119
113
 
120
- **0.1.0.alpha** (January 10, 2012)
114
+ * * *
121
115
 
122
- * Ability to parse and modify package.xml files easily.
116
+ ### send\_email(options={})
123
117
 
124
- ## License
125
- Copyright (C) 2012 Eric Holmes
118
+ Sends a [SingleEmailMessage](http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_calls_sendemail.htm) using Salesforce.
126
119
 
127
- This program is free software; you can redistribute it and/or
128
- modify it under the terms of the GNU General Public License
129
- as published by the Free Software Foundation; either version 2
130
- of the License, or (at your option) any later version.
120
+ ```ruby
121
+ client.send_email(
122
+ to_addresses: ['foo@bar.com'],
123
+ subject: 'Hello World',
124
+ plain_text_body: 'Hello World'
125
+ )
126
+ ```
131
127
 
132
- This program is distributed in the hope that it will be useful,
133
- but WITHOUT ANY WARRANTY; without even the implied warranty of
134
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
135
- GNU General Public License for more details.
128
+ ## Contributing
136
129
 
137
- You should have received a copy of the GNU General Public License
138
- along with this program; if not, write to the Free Software
139
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
130
+ 1. Fork it
131
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
132
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
133
+ 4. Push to the branch (`git push origin my-new-feature`)
134
+ 5. Create new Pull Request
data/Rakefile CHANGED
@@ -1,18 +1,10 @@
1
+ #!/usr/bin/env rake
1
2
  require "bundler/gem_tasks"
2
3
 
3
- task :default => :spec
4
+ task :default => [:spec]
4
5
 
5
- desc "Run rspec specs"
6
- task :spec do
7
- sh "bundle exec rspec spec"
8
- end
9
-
10
- desc "Start an irb session"
11
- task :console do
12
- sh "irb -I lib -r metaforce"
13
- end
14
-
15
- desc "Build and publish gem on rubygems.org"
16
- task :publish do
17
- sh "gem build metaforce.gemspec && gem push metaforce-*.gem"
6
+ require 'rspec/core/rake_task'
7
+ desc "Run specs"
8
+ RSpec::Core::RakeTask.new do |t|
9
+ t.pattern = 'spec/**/*_spec.rb'
18
10
  end
@@ -0,0 +1,51 @@
1
+ require 'metaforce'
2
+
3
+ # Run with: `USER=user PASS=pass TOKEN=securitytoken bundle exec ruby example.rb`
4
+
5
+ Metaforce.configuration.log = false
6
+
7
+ client = Metaforce.new :username => ENV['USER'],
8
+ :password => ENV['PASS'],
9
+ :security_token => ENV['TOKEN']
10
+
11
+ Metaforce::Job.disable_threading!
12
+
13
+ # Test sending an email.
14
+ print 'send email to: '
15
+ client.send_email(
16
+ to_addresses: [STDIN.gets.chomp],
17
+ subject: 'Test',
18
+ plain_text_body: 'Test'
19
+ )
20
+
21
+ # Test deployment.
22
+ client.deploy('../spec/fixtures/payload.zip')
23
+ .on_complete { |job| puts "Deploy Completed: #{job.id}."}
24
+ .on_error { |job| puts "Deploy Failed: #{job.id}."}
25
+ .perform
26
+
27
+ # Test retrieve.
28
+ manifest = Metaforce::Manifest.new(:custom_object => ['Account'])
29
+ client.retrieve_unpackaged(manifest)
30
+ .on_complete { |job| puts "Retrieve Completed: #{job.id}."}
31
+ .on_error { |job| puts "Retrieve Failed: #{job.id}."}
32
+ .extract_to('./tmp')
33
+ .perform
34
+
35
+ # Test delete.
36
+ client.delete(:apex_page, 'TestPage')
37
+ .on_complete { |job| puts "Delete Completed: #{job.id}."}
38
+ .on_error { |job| puts "Delete Failed: #{job.id}."}
39
+ .perform
40
+
41
+ # Test create.
42
+ client.create(:apex_page, :full_name => 'TestPage', label: 'Test page', :content => '<apex:page>foobar</apex:page>')
43
+ .on_complete { |job| puts "Create Completed: #{job.id}."}
44
+ .on_error { |job| puts "Create Failed: #{job.id}."}
45
+ .perform
46
+
47
+ # Test update.
48
+ client.update(:apex_page, 'TestPage', :full_name => 'TestPage', :label => 'Test page', :content => '<apex:page>hello world</apex:page>')
49
+ .on_complete { |job| puts "Update Completed: #{job.id}."}
50
+ .on_error { |job| puts "Update Failed: #{job.id}."}
51
+ .perform
@@ -0,0 +1,76 @@
1
+ module Metaforce
2
+ class AbstractClient
3
+ class << self
4
+ # Internal
5
+ def endpoint(key)
6
+ define_method :endpoint do; @options[key] end
7
+ end
8
+
9
+ # Internal
10
+ def wsdl(wsdl)
11
+ define_method :wsdl do; wsdl end
12
+ end
13
+ end
14
+
15
+ # Public: Initialize a new client.
16
+ #
17
+ # options - A hash of options, which should have a :session_id key
18
+ def initialize(options={})
19
+ raise 'Please specify a hash of options' unless options.is_a?(Hash)
20
+ @options = options
21
+ end
22
+
23
+ private
24
+
25
+ # Internal: The Savon client to send SOAP requests with.
26
+ def client
27
+ @client ||= Savon.client(wsdl) do |wsdl|
28
+ wsdl.endpoint = endpoint
29
+ end.tap do |client|
30
+ client.config.soap_header = soap_headers
31
+ client.http.auth.ssl.verify_mode = :none
32
+ end
33
+ end
34
+
35
+ # Internal: Performs a SOAP request. If the session is invalid, it will
36
+ # attempt to reauthenticate by called the reauthentication handler if
37
+ # present.
38
+ def request(*args, &block)
39
+ begin
40
+ authenticate! unless session_id
41
+ _request(*args, &block)
42
+ rescue Savon::SOAP::Fault => e
43
+ raise e unless e.message =~ /INVALID_SESSION_ID/ && authentication_handler
44
+ authenticate!
45
+ _request(*args, &block)
46
+ end
47
+ end
48
+
49
+ def _request(*args, &block)
50
+ response = client.request(*args, &block)
51
+ Hashie::Mash.new(response.body)[:"#{args[0]}_response"].result
52
+ end
53
+
54
+ # Internal Calls the authentication handler, which should set @options to a new
55
+ # hash.
56
+ def authenticate!
57
+ authentication_handler.call(self, @options)
58
+ end
59
+
60
+ # A proc object that gets called when the client needs to reauthenticate.
61
+ def authentication_handler
62
+ Metaforce.configuration.authentication_handler
63
+ end
64
+
65
+ # Internal: Soap headers to set for authenticate.
66
+ def soap_headers
67
+ { 'ins0:SessionHeader' => { 'ins0:sessionId' => session_id } }
68
+ end
69
+
70
+ # Internal: The session id, which can be obtained by calling
71
+ # Metaforce.login or through OAuth.
72
+ def session_id
73
+ @options[:session_id]
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,27 @@
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 method_missing(method, *args, &block)
18
+ if metadata.respond_to? method, false
19
+ metadata.send(method, *args, &block)
20
+ elsif services.respond_to? method, false
21
+ services.send(method, *args, &block)
22
+ else
23
+ super
24
+ end
25
+ end
26
+ end
27
+ end
@@ -41,26 +41,48 @@ module Metaforce
41
41
  attr_accessor :security_token
42
42
  # Set this to true if you're authenticating with a Sandbox instance.
43
43
  # Defaults to false.
44
- attr_accessor :test
45
- # Causes Metaforce::Transaction.result to loop until the transaction is
46
- # complete. Defaults to true.
47
- #
48
- # If you want to do custom polling, set this to false.
49
- #
50
- # == Example
51
- #
52
- # Metaforce.configuration.wait_until_done = false;
53
- #
54
- # deploy = client.deploy File.expand_path("myeclipseproj")
55
- # begin; while !deploy.done?
56
- # deploy.result
57
- attr_accessor :wait_until_done
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
+
51
+ def api_version
52
+ @api_version ||= '26.0'
53
+ end
54
+
55
+ def host
56
+ @host ||= 'login.salesforce.com'
57
+ end
58
+
59
+ def authentication_handler
60
+ @authentication_handler ||= lambda { |client, options|
61
+ options.merge!(Metaforce.login(options))
62
+ }
63
+ end
64
+
65
+ def log=(log)
66
+ Savon.configure do |config|
67
+ config.log = log
68
+ end
69
+ HTTPI.log = log
70
+ end
71
+
72
+ def partner_wsdl
73
+ File.join(wsdl, 'partner.xml')
74
+ end
75
+
76
+ def metadata_wsdl
77
+ File.join(wsdl, 'metadata.xml')
78
+ end
79
+
80
+ def endpoint
81
+ "https://#{host}/services/Soap/u/#{api_version}"
82
+ end
58
83
 
59
- def initialize
60
- HTTPI.log = false
61
- @api_version = "23.0"
62
- @test = false
63
- @wait_until_done = true
84
+ def wsdl
85
+ File.expand_path("../../../wsdl/#{api_version}", __FILE__)
64
86
  end
65
87
 
66
88
  def logger
@@ -0,0 +1,13 @@
1
+ module Metaforce
2
+ class Job::CRUD < Job
3
+ def initialize(client, method, args)
4
+ super(client)
5
+ @method, @args = method, args
6
+ end
7
+
8
+ def perform
9
+ @id = @client.send(@method, *@args).id
10
+ super
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,87 @@
1
+ module Metaforce
2
+ class Job::Deploy < Job
3
+
4
+ # Public: Instantiate a new deploy job.
5
+ #
6
+ # Examples
7
+ #
8
+ # job = Metaforce::Job::Deploy.new(client, './path/to/deploy')
9
+ # # => #<Metaforce::Job::Deploy @id=nil>
10
+ #
11
+ # Returns self.
12
+ def initialize(client, path, options={})
13
+ super(client)
14
+ @path, @options = path, options
15
+ end
16
+
17
+ # Public: Perform the job.
18
+ #
19
+ # Examples
20
+ #
21
+ # job = Metaforce::Job::Deploy.new(client, './path/to/deploy')
22
+ # job.perform
23
+ # # => #<Metaforce::Job::Deploy @id='1234'>
24
+ #
25
+ # Returns self.
26
+ def perform
27
+ @id = client._deploy(payload, @options).id
28
+ super
29
+ end
30
+
31
+ # Public: Get the detailed status of the deploy.
32
+ #
33
+ # Examples
34
+ #
35
+ # job.result
36
+ # # => { :id => '1234', :success => true, ... }
37
+ #
38
+ # Returns the DeployResult (http://www.salesforce.com/us/developer/docs/api_meta/Content/meta_deployresult.htm).
39
+ def result
40
+ client.status(id, :deploy)
41
+ end
42
+
43
+ # Public: Returns true if the deploy was successful.
44
+ #
45
+ # Examples
46
+ #
47
+ # job.success?
48
+ # # => true
49
+ #
50
+ # Returns true or false based on the DeployResult.
51
+ def success?
52
+ result.success
53
+ end
54
+
55
+ # Public: Base64 encodes the contents of the zip file.
56
+ #
57
+ # Examples
58
+ #
59
+ # job.payload
60
+ # # => '<lots of base64 encoded content>'
61
+ #
62
+ # Returns the content of the zip file encoded to base64.
63
+ def payload
64
+ Base64.encode64(File.open(file, 'rb').read)
65
+ end
66
+
67
+ private
68
+
69
+ # Internal: Returns the path to the zip file.
70
+ def file
71
+ File.file?(@path) ? @path : zip_file
72
+ end
73
+
74
+ # Internal: Creates a zip file with the contents of the directory.
75
+ def zip_file
76
+ path = Dir.mktmpdir
77
+ File.join(path, 'deploy.zip').tap do |path|
78
+ Zip::ZipFile.open(path, Zip::ZipFile::CREATE) do |zip|
79
+ Dir["#{@path}/**/**"].each do |file|
80
+ zip.add(file.sub("#{File.dirname(@path)}/", ''), file)
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ end
87
+ end