metaforce 0.3.0.alpha → 0.3.1

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
@@ -4,12 +4,9 @@
4
4
  Metaforce is a Ruby gem for interacting with the [Salesforce Metadata API](http://www.salesforce.com/us/developer/docs/api_meta/index.htm).
5
5
  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.
6
6
 
7
- **Metaforce is in active development and is currently in alpha status. Don't use
8
- it to deploy code to production instances. You've been warned!**
9
-
10
7
  ## Installation
11
8
  ```bash
12
- gem install metaforce --pre
9
+ gem install metaforce
13
10
  ```
14
11
 
15
12
  ## Usage
@@ -64,9 +61,10 @@ end
64
61
  This gem is far from being feature complete. Here's a list of things that still
65
62
  need to be done.
66
63
 
67
- * <del>Implement .retrieve for retrieving metadata.</del>
68
64
  * Implement CRUD based calls <http://www.salesforce.com/us/developer/docs/api_meta/Content/meta_crud_based_calls_intro.htm>.
69
65
  * Implement some helper methods for diffing metadata.
66
+ * Ability to deploy directly from a git repository.
67
+ * <del>Implement .retrieve for retrieving metadata.</del>
70
68
  * <del>Implement a DSL.</del>
71
69
  * And some other stuff that I haven't quite thought of yet...
72
70
 
@@ -76,6 +74,12 @@ feature on a new branch, then send me a pull request with a detailed
76
74
  description. Please provide applicable rspec specs.
77
75
 
78
76
  ## Version History
77
+ **0.3.1** (February 3, 2012)
78
+
79
+ * Dynamically defined helper methods for .list (e.g. `client.list_apex_classes`, `client.list_custom_objects`).
80
+ * The `describe` method now caches the results to minimize latency. `describe!`
81
+ can be used to force a refresh.
82
+
79
83
  **0.3.0.alpha** (January 29, 2012)
80
84
 
81
85
  * Ability to retrieve metadata from an organization.
@@ -49,12 +49,29 @@ module Metaforce
49
49
  response.body[:list_metadata_response][:result]
50
50
  end
51
51
 
52
- # Describe the organization's metadata
52
+ # Defines some helper methods for listing metadata types
53
+ #
54
+ # Example
55
+ #
56
+ # client.list_apex_classes
57
+ # client.list_custom_objects
58
+ METADATA_TYPES.each do |type, value|
59
+ define_method("list_#{value[:plural]}".to_sym) do
60
+ list :type => value[:name]
61
+ end
62
+ end
63
+
64
+ # Describe the organization's metadata and cache the response
53
65
  def describe
66
+ @describe ||= describe!
67
+ end
68
+
69
+ # Describe the organization's metadata
70
+ def describe!
54
71
  response = @client.request(:describe_metadata) do |soap|
55
72
  soap.header = @header
56
73
  end
57
- response.body[:describe_metadata_response][:result]
74
+ @describe = response.body[:describe_metadata_response][:result]
58
75
  end
59
76
 
60
77
  # Checks the status of an async result
@@ -1,4 +1,5 @@
1
1
  require 'nokogiri'
2
+ require 'metaforce/types'
2
3
 
3
4
  module Metaforce
4
5
  class Manifest
@@ -101,17 +102,17 @@ module Metaforce
101
102
 
102
103
  # Returns the components name
103
104
  def component_name(key) # :nodoc:
104
- COMPONENT_TYPE_MAP[key][:name]
105
+ METADATA_TYPES[key][:name]
105
106
  end
106
107
 
107
108
  # Returns the components folder
108
109
  def component_folder(key) # :nodoc:
109
- COMPONENT_TYPE_MAP[key][:folder]
110
+ METADATA_TYPES[key][:folder]
110
111
  end
111
112
 
112
113
  # Returns a key for the component name
113
114
  def component_key(name) # :nodoc:
114
- COMPONENT_TYPE_MAP.each do |key, component|
115
+ METADATA_TYPES.each do |key, component|
115
116
  return key if component[:name] == name
116
117
  end
117
118
  end
@@ -172,10 +173,7 @@ module Metaforce
172
173
  components = []
173
174
  @components.each do |type, members|
174
175
  name = component_name(type)
175
- components.push({
176
- :members => members,
177
- :name => name
178
- })
176
+ components.push :members => members, :name => name
179
177
  end
180
178
  components
181
179
  end
@@ -197,175 +195,5 @@ module Metaforce
197
195
  self
198
196
  end
199
197
 
200
- COMPONENT_TYPE_MAP = {
201
- :action_override => {
202
- :name => "ActionOverride",
203
- :folder => "objects"
204
- },
205
- :analytics_snapshot => {
206
- :name => "AnalyticsSnapshot",
207
- :folder => "analyticsnapshots"
208
- },
209
- :apex_class => {
210
- :name => "ApexClass",
211
- :folder => "classes"
212
- },
213
- :article_type => {
214
- :name => "ArticleType",
215
- :folder => "objects"
216
- },
217
- :apex_component => {
218
- :name => "ApexComponent",
219
- :folder => "components"
220
- },
221
- :apex_page => {
222
- :name => "ApexPage",
223
- :folder => "pages"
224
- },
225
- :apex_trigger => {
226
- :name => "ApexTrigger",
227
- :folder => "triggers"
228
- },
229
- :business_process => {
230
- :name => "BusinessProcess",
231
- :folder => "objects"
232
- },
233
- :custom_application => {
234
- :name => "CustomApplication",
235
- :folder => "applications"
236
- },
237
- :custom_field => {
238
- :name => "CustomField",
239
- :folder => "objects"
240
- },
241
- :custom_labels => {
242
- :name => "CustomLabels",
243
- :folder => "labels"
244
- },
245
- :custom_object => {
246
- :name => "CustomObject",
247
- :folder => "objects"
248
- },
249
- :custom_object_translation => {
250
- :name => "CustomObjectTranslation",
251
- :folder => "objectTranslations"
252
- },
253
- :custom_page_web_link => {
254
- :name => "CustomPageWebLink",
255
- :folder => "weblinks"
256
- },
257
- :custom_site => {
258
- :name => "CustomSite",
259
- :folder => "sites"
260
- },
261
- :custom_tab => {
262
- :name => "CustomTab",
263
- :folder => "tabs"
264
- },
265
- :dashboard => {
266
- :name => "Dashboard",
267
- :folder => "dashboards"
268
- },
269
- :data_category_group => {
270
- :name => "DataCategoryGroup",
271
- :folder => "datacategorygroups"
272
- },
273
- :document => {
274
- :name => "Document",
275
- :folder => "document"
276
- },
277
- :email_template => {
278
- :name => "EmailTemplate",
279
- :folder => "email"
280
- },
281
- :entitlement_template => {
282
- :name => "EntitlementTemplate",
283
- :folder => "entitlementTemplates"
284
- },
285
- :field_set => {
286
- :name => "FieldSet",
287
- :folder => "objects"
288
- },
289
- :home_page_component => {
290
- :name => "HomePageComponent",
291
- :folder => "homePageComponents"
292
- },
293
- :layout => {
294
- :name => "Layout",
295
- :folder => "layouts"
296
- },
297
- :letterhead => {
298
- :name => "Letterhead",
299
- :folder => "letterhead"
300
- },
301
- :list_view => {
302
- :name => "ListView",
303
- :folder => "objects"
304
- },
305
- :named_filter => {
306
- :name => "NamedFilter",
307
- :folder => "objects"
308
- },
309
- :permission_set => {
310
- :name => "PermissionSet",
311
- :folder => "permissionsets"
312
- },
313
- :portal => {
314
- :name => "Portal",
315
- :folder => "portals"
316
- },
317
- :profile => {
318
- :name => "Profile",
319
- :folder => "profiles"
320
- },
321
- :record_type => {
322
- :name => "RecordType",
323
- :folder => "objects"
324
- },
325
- :remote_site_setting => {
326
- :name => "RemoteSiteSetting",
327
- :folder => "remoteSiteSettings"
328
- },
329
- :report => {
330
- :name => "Report",
331
- :folder => "reports"
332
- },
333
- :report_type => {
334
- :name => "ReportType",
335
- :folder => "reportTypes"
336
- },
337
- :scontroler => {
338
- :name => "Scontroler",
339
- :folder => "scontrols"
340
- },
341
- :sharing_reason => {
342
- :name => "SharingReason",
343
- :folder => "objects"
344
- },
345
- :sharing_recalculation => {
346
- :name => "SharingRecalculation",
347
- :folder => "objects"
348
- },
349
- :static_resource => {
350
- :name => "StaticResource",
351
- :folder => "staticResources"
352
- },
353
- :translations => {
354
- :name => "Translations",
355
- :folder => "translations"
356
- },
357
- :validation_rule => {
358
- :name => "ValidationRule",
359
- :folder => "objects"
360
- },
361
- :weblink => {
362
- :name => "Weblink",
363
- :folder => "objects"
364
- },
365
- :workflow => {
366
- :name => "Workflow",
367
- :folder => "workflows"
368
- }
369
- }
370
198
  end
371
199
  end
@@ -0,0 +1,214 @@
1
+ module Metaforce
2
+ METADATA_TYPES = {
3
+ :action_override => {
4
+ :name => "ActionOverride",
5
+ :folder => "objects",
6
+ :plural => :action_overrides
7
+ },
8
+ :analytics_snapshot => {
9
+ :name => "AnalyticsSnapshot",
10
+ :folder => "analyticsnapshots",
11
+ :plural => :analytics_snapshots
12
+ },
13
+ :apex_class => {
14
+ :name => "ApexClass",
15
+ :folder => "classes",
16
+ :plural => :apex_classes
17
+ },
18
+ :article_type => {
19
+ :name => "ArticleType",
20
+ :folder => "objects",
21
+ :plural => :article_types
22
+ },
23
+ :apex_component => {
24
+ :name => "ApexComponent",
25
+ :folder => "components",
26
+ :plural => :apex_components
27
+ },
28
+ :apex_page => {
29
+ :name => "ApexPage",
30
+ :folder => "pages",
31
+ :plural => :apex_pages
32
+ },
33
+ :apex_trigger => {
34
+ :name => "ApexTrigger",
35
+ :folder => "triggers",
36
+ :plural => :apex_triggers
37
+ },
38
+ :business_process => {
39
+ :name => "BusinessProcess",
40
+ :folder => "objects",
41
+ :plural => :business_processes
42
+ },
43
+ :custom_application => {
44
+ :name => "CustomApplication",
45
+ :folder => "applications",
46
+ :plural => :custom_applications
47
+ },
48
+ :custom_field => {
49
+ :name => "CustomField",
50
+ :folder => "objects",
51
+ :plural => :custom_fields
52
+ },
53
+ :custom_labels => {
54
+ :name => "CustomLabels",
55
+ :folder => "labels",
56
+ :plural => :custom_labels
57
+ },
58
+ :custom_object => {
59
+ :name => "CustomObject",
60
+ :folder => "objects",
61
+ :plural => :custom_objects
62
+ },
63
+ :custom_object_translation => {
64
+ :name => "CustomObjectTranslation",
65
+ :folder => "objectTranslations",
66
+ :plural => :custom_object_translations
67
+ },
68
+ :custom_page_web_link => {
69
+ :name => "CustomPageWebLink",
70
+ :folder => "weblinks",
71
+ :plural => :custom_page_web_links
72
+ },
73
+ :custom_site => {
74
+ :name => "CustomSite",
75
+ :folder => "sites",
76
+ :plural => :custom_sites
77
+ },
78
+ :custom_tab => {
79
+ :name => "CustomTab",
80
+ :folder => "tabs",
81
+ :plural => :custom_tabs
82
+ },
83
+ :dashboard => {
84
+ :name => "Dashboard",
85
+ :folder => "dashboards",
86
+ :plural => :dashboards
87
+ },
88
+ :data_category_group => {
89
+ :name => "DataCategoryGroup",
90
+ :folder => "datacategorygroups",
91
+ :plural => :data_category_groups
92
+ },
93
+ :document => {
94
+ :name => "Document",
95
+ :folder => "document",
96
+ :plural => :documents
97
+ },
98
+ :email_template => {
99
+ :name => "EmailTemplate",
100
+ :folder => "email",
101
+ :plural => :email_templates
102
+ },
103
+ :entitlement_template => {
104
+ :name => "EntitlementTemplate",
105
+ :folder => "entitlementTemplates",
106
+ :plural => :entitlement_templates
107
+ },
108
+ :field_set => {
109
+ :name => "FieldSet",
110
+ :folder => "objects",
111
+ :plural => :field_sets
112
+ },
113
+ :home_page_component => {
114
+ :name => "HomePageComponent",
115
+ :folder => "homePageComponents",
116
+ :plural => :home_page_components
117
+ },
118
+ :layout => {
119
+ :name => "Layout",
120
+ :folder => "layouts",
121
+ :plural => :layouts
122
+ },
123
+ :letterhead => {
124
+ :name => "Letterhead",
125
+ :folder => "letterhead",
126
+ :plural => :letterheads
127
+ },
128
+ :list_view => {
129
+ :name => "ListView",
130
+ :folder => "objects",
131
+ :plural => :list_views
132
+ },
133
+ :named_filter => {
134
+ :name => "NamedFilter",
135
+ :folder => "objects",
136
+ :plural => :named_filters
137
+ },
138
+ :permission_set => {
139
+ :name => "PermissionSet",
140
+ :folder => "permissionsets",
141
+ :plural => :permission_sets
142
+ },
143
+ :portal => {
144
+ :name => "Portal",
145
+ :folder => "portals",
146
+ :plural => :portals
147
+ },
148
+ :profile => {
149
+ :name => "Profile",
150
+ :folder => "profiles",
151
+ :plural => :profiles
152
+ },
153
+ :record_type => {
154
+ :name => "RecordType",
155
+ :folder => "objects",
156
+ :plural => :record_types
157
+ },
158
+ :remote_site_setting => {
159
+ :name => "RemoteSiteSetting",
160
+ :folder => "remoteSiteSettings",
161
+ :plural => :remote_site_settings
162
+ },
163
+ :report => {
164
+ :name => "Report",
165
+ :folder => "reports",
166
+ :plural => :reports
167
+ },
168
+ :report_type => {
169
+ :name => "ReportType",
170
+ :folder => "reportTypes",
171
+ :plural => :report_types
172
+ },
173
+ :scontroler => {
174
+ :name => "Scontroler",
175
+ :folder => "scontrols",
176
+ :plural => :scontrolers
177
+ },
178
+ :sharing_reason => {
179
+ :name => "SharingReason",
180
+ :folder => "objects",
181
+ :plural => :sharing_reasons
182
+ },
183
+ :sharing_recalculation => {
184
+ :name => "SharingRecalculation",
185
+ :folder => "objects",
186
+ :plural => :sharing_recalculations
187
+ },
188
+ :static_resource => {
189
+ :name => "StaticResource",
190
+ :folder => "staticResources",
191
+ :plural => :static_resources
192
+ },
193
+ :translations => {
194
+ :name => "Translations",
195
+ :folder => "translations",
196
+ :plural => :translations
197
+ },
198
+ :validation_rule => {
199
+ :name => "ValidationRule",
200
+ :folder => "objects",
201
+ :plural => :validation_rules
202
+ },
203
+ :weblink => {
204
+ :name => "Weblink",
205
+ :folder => "objects",
206
+ :plural => :weblinks
207
+ },
208
+ :workflow => {
209
+ :name => "Workflow",
210
+ :folder => "workflows",
211
+ :plural => :workflows
212
+ }
213
+ }
214
+ end
@@ -1,3 +1,3 @@
1
1
  module Metaforce
2
- VERSION = "0.3.0.alpha"
2
+ VERSION = "0.3.1"
3
3
  end
@@ -12,13 +12,17 @@ describe Metaforce::Metadata::Client do
12
12
  end
13
13
 
14
14
  describe ".list" do
15
- context "when given valid information" do
16
15
 
17
- it "returns an array" do
18
- savon.expects(:list_metadata).with(:queries => [ :type => "ApexClass"]).returns(:objects)
19
- client.list(:type => "ApexClass").should be_an(Array)
20
- end
16
+ it "returns an array" do
17
+ savon.expects(:list_metadata).with(:queries => [ :type => "ApexClass"]).returns(:objects)
18
+ client.list(:type => "ApexClass").should be_an(Array)
19
+ end
21
20
 
21
+ end
22
+
23
+ it "should respond to dynamically defined list methods" do
24
+ Metaforce::METADATA_TYPES.each do |type, value|
25
+ client.respond_to?("list_#{value[:plural]}").should eq(true)
22
26
  end
23
27
  end
24
28
 
@@ -30,6 +34,30 @@ describe Metaforce::Metadata::Client do
30
34
  client.describe.should be_a(Hash)
31
35
  end
32
36
 
37
+ it "caches the response" do
38
+ savon.expects(:describe_metadata).returns(:success)
39
+ client.describe.should be_a(Hash)
40
+ expect { client.describe }.to_not raise_error
41
+ end
42
+
43
+ end
44
+ end
45
+
46
+ describe ".describe!" do
47
+ context "when given valid information" do
48
+
49
+ it "returns a hash" do
50
+ savon.expects(:describe_metadata).returns(:success)
51
+ client.describe!.should be_a(Hash)
52
+ end
53
+
54
+ it "doesn't cache the response" do
55
+ savon.expects(:describe_metadata).returns(:success)
56
+ client.describe!.should be_a(Hash)
57
+ savon.expects(:describe_metadata).returns(:success)
58
+ expect { client.describe! }.to_not raise_error
59
+ end
60
+
33
61
  end
34
62
  end
35
63
 
metadata CHANGED
@@ -1,19 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metaforce
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0.alpha
5
- prerelease: 6
4
+ version: 0.3.1
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Eric J. Holmes
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-30 00:00:00.000000000 Z
12
+ date: 2012-02-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
16
- requirement: &3632840 !ruby/object:Gem::Requirement
16
+ requirement: &9206270 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.5.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *3632840
24
+ version_requirements: *9206270
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: savon
27
- requirement: &3631640 !ruby/object:Gem::Requirement
27
+ requirement: &9187580 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 0.9.7
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *3631640
35
+ version_requirements: *9187580
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rubyzip
38
- requirement: &3630690 !ruby/object:Gem::Requirement
38
+ requirement: &9170720 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 0.9.5
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *3630690
46
+ version_requirements: *9170720
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rake
49
- requirement: &3629920 !ruby/object:Gem::Requirement
49
+ requirement: &9164330 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *3629920
57
+ version_requirements: *9164330
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rspec
60
- requirement: &3629280 !ruby/object:Gem::Requirement
60
+ requirement: &9145350 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *3629280
68
+ version_requirements: *9145350
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: mocha
71
- requirement: &3627890 !ruby/object:Gem::Requirement
71
+ requirement: &9142060 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *3627890
79
+ version_requirements: *9142060
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: savon_spec
82
- requirement: &3625600 !ruby/object:Gem::Requirement
82
+ requirement: &9115390 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ~>
@@ -87,7 +87,7 @@ dependencies:
87
87
  version: 0.1.6
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *3625600
90
+ version_requirements: *9115390
91
91
  description: A Ruby gem for interacting with the Salesforce Metadata API
92
92
  email:
93
93
  - eric@ejholmes.net
@@ -109,6 +109,7 @@ files:
109
109
  - lib/metaforce/config.rb
110
110
  - lib/metaforce/dsl.rb
111
111
  - lib/metaforce/manifest.rb
112
+ - lib/metaforce/types.rb
112
113
  - lib/metaforce/version.rb
113
114
  - metaforce.gemspec
114
115
  - spec/.gitignore
@@ -151,9 +152,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
151
152
  required_rubygems_version: !ruby/object:Gem::Requirement
152
153
  none: false
153
154
  requirements:
154
- - - ! '>'
155
+ - - ! '>='
155
156
  - !ruby/object:Gem::Version
156
- version: 1.3.1
157
+ version: '0'
157
158
  requirements: []
158
159
  rubyforge_project: metaforce
159
160
  rubygems_version: 1.8.15