active_zuora 1.5.2 → 2.0.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.
Files changed (78) hide show
  1. data/Gemfile +4 -0
  2. data/Gemfile.lock +57 -0
  3. data/README.md +155 -0
  4. data/Rakefile +6 -22
  5. data/TODO.md +2 -0
  6. data/active_zuora.gemspec +25 -68
  7. data/lib/active_zuora.rb +37 -6
  8. data/lib/active_zuora/amend.rb +43 -0
  9. data/lib/active_zuora/base.rb +73 -0
  10. data/lib/active_zuora/belongs_to_associations.rb +56 -0
  11. data/lib/active_zuora/connection.rb +41 -0
  12. data/lib/active_zuora/fields.rb +122 -0
  13. data/lib/active_zuora/fields/array_field_decorator.rb +28 -0
  14. data/lib/active_zuora/fields/boolean_field.rb +12 -0
  15. data/lib/active_zuora/fields/date_time_field.rb +19 -0
  16. data/lib/active_zuora/fields/decimal_field.rb +12 -0
  17. data/lib/active_zuora/fields/field.rb +76 -0
  18. data/lib/active_zuora/fields/integer_field.rb +11 -0
  19. data/lib/active_zuora/fields/object_field.rb +31 -0
  20. data/lib/active_zuora/fields/string_field.rb +11 -0
  21. data/lib/active_zuora/generate.rb +43 -0
  22. data/lib/active_zuora/generator.rb +220 -0
  23. data/lib/active_zuora/has_many_associations.rb +37 -0
  24. data/lib/active_zuora/has_many_proxy.rb +50 -0
  25. data/lib/active_zuora/persistence.rb +176 -0
  26. data/lib/active_zuora/relation.rb +253 -0
  27. data/lib/active_zuora/scoping.rb +50 -0
  28. data/lib/active_zuora/subscribe.rb +42 -0
  29. data/lib/active_zuora/version.rb +3 -0
  30. data/lib/active_zuora/z_object.rb +21 -0
  31. data/spec/belongs_to_associations_spec.rb +35 -0
  32. data/spec/has_many_integration_spec.rb +53 -0
  33. data/spec/spec_helper.rb +21 -0
  34. data/spec/subscribe_integration_spec.rb +218 -0
  35. data/spec/zobject_integration_spec.rb +104 -0
  36. data/wsdl/zuora.wsdl +1548 -0
  37. metadata +128 -72
  38. checksums.yaml +0 -7
  39. data/LICENSE +0 -202
  40. data/README.rdoc +0 -36
  41. data/VERSION +0 -1
  42. data/custom_fields.yml +0 -17
  43. data/lib/active_zuora/account.rb +0 -31
  44. data/lib/active_zuora/amendment.rb +0 -7
  45. data/lib/active_zuora/bill_run.rb +0 -4
  46. data/lib/active_zuora/contact.rb +0 -7
  47. data/lib/active_zuora/invoice.rb +0 -46
  48. data/lib/active_zuora/invoice_item.rb +0 -26
  49. data/lib/active_zuora/invoice_item_adjustment.rb +0 -4
  50. data/lib/active_zuora/invoice_payment.rb +0 -11
  51. data/lib/active_zuora/payment.rb +0 -18
  52. data/lib/active_zuora/payment_method.rb +0 -10
  53. data/lib/active_zuora/product.rb +0 -4
  54. data/lib/active_zuora/product_rate_plan.rb +0 -9
  55. data/lib/active_zuora/product_rate_plan_charge.rb +0 -11
  56. data/lib/active_zuora/product_rate_plan_charge_tier.rb +0 -7
  57. data/lib/active_zuora/product_rate_plan_charge_tier_data.rb +0 -4
  58. data/lib/active_zuora/rate_plan.rb +0 -16
  59. data/lib/active_zuora/rate_plan_charge.rb +0 -71
  60. data/lib/active_zuora/rate_plan_charge_data.rb +0 -4
  61. data/lib/active_zuora/rate_plan_charge_tier.rb +0 -4
  62. data/lib/active_zuora/rate_plan_data.rb +0 -4
  63. data/lib/active_zuora/refund.rb +0 -4
  64. data/lib/active_zuora/subscribe_options.rb +0 -4
  65. data/lib/active_zuora/subscribe_request.rb +0 -13
  66. data/lib/active_zuora/subscribe_with_existing_account_request.rb +0 -4
  67. data/lib/active_zuora/subscription.rb +0 -17
  68. data/lib/active_zuora/subscription_data.rb +0 -4
  69. data/lib/active_zuora/usage.rb +0 -4
  70. data/lib/active_zuora/zobject.rb +0 -154
  71. data/lib/soap/property +0 -1
  72. data/lib/zuora/ZUORA.rb +0 -1560
  73. data/lib/zuora/ZUORADriver.rb +0 -145
  74. data/lib/zuora/ZUORAMappingRegistry.rb +0 -1709
  75. data/lib/zuora/ZuoraServiceClient.rb +0 -124
  76. data/lib/zuora/api.rb +0 -18
  77. data/lib/zuora_client.rb +0 -191
  78. data/lib/zuora_interface.rb +0 -215
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+
@@ -0,0 +1,57 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ active_zuora (2.0.0)
5
+ activemodel (>= 3.0.0, < 4.0.0)
6
+ activesupport (>= 3.0.0, < 4.0.0)
7
+ savon (~> 0.9.9)
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ activemodel (3.2.3)
13
+ activesupport (= 3.2.3)
14
+ builder (~> 3.0.0)
15
+ activesupport (3.2.3)
16
+ i18n (~> 0.6)
17
+ multi_json (~> 1.0)
18
+ akami (1.0.0)
19
+ gyoku (>= 0.4.0)
20
+ builder (3.0.0)
21
+ diff-lcs (1.1.3)
22
+ gyoku (0.4.5)
23
+ builder (>= 2.1.2)
24
+ httpi (0.9.7)
25
+ rack
26
+ i18n (0.6.0)
27
+ multi_json (1.5.0)
28
+ nokogiri (1.5.2)
29
+ nori (1.1.0)
30
+ rack (1.4.1)
31
+ rake (0.8.7)
32
+ rspec (2.8.0)
33
+ rspec-core (~> 2.8.0)
34
+ rspec-expectations (~> 2.8.0)
35
+ rspec-mocks (~> 2.8.0)
36
+ rspec-core (2.8.0)
37
+ rspec-expectations (2.8.0)
38
+ diff-lcs (~> 1.1.2)
39
+ rspec-mocks (2.8.0)
40
+ savon (0.9.9)
41
+ akami (~> 1.0)
42
+ builder (>= 2.1.2)
43
+ gyoku (>= 0.4.0)
44
+ httpi (~> 0.9)
45
+ nokogiri (>= 1.4.0)
46
+ nori (~> 1.1)
47
+ wasabi (~> 2.1)
48
+ wasabi (2.1.1)
49
+ nokogiri (>= 1.4.0)
50
+
51
+ PLATFORMS
52
+ ruby
53
+
54
+ DEPENDENCIES
55
+ active_zuora!
56
+ rake (~> 0.8.7)
57
+ rspec (~> 2.8.0)
@@ -0,0 +1,155 @@
1
+ # active_zuora - Auto-Generated ActiveModel Interface for Zuora
2
+
3
+ [![TravisCI](https://secure.travis-ci.org/tstmedia/active_zuora.png "TravisCI")](http://travis-ci.org/tstmedia/active_zuora "Travis-CI ActiveZuora") [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/tstmedia/active_zuora)
4
+
5
+ Use Zuora's API like ActiveRecord. Auto-generate all the classes from the wsdl file, or easily declare your own.
6
+
7
+ ## Configuration
8
+
9
+ ActiveZuora.configure(
10
+ :username => 'user@example.com',
11
+ :password => 'password'
12
+ )
13
+
14
+ Enable SOAP logging to stderr or provide your own wsdl file.
15
+
16
+ ActiveZuora.configure(
17
+ :username => 'user@example.com',
18
+ :password => 'password',
19
+ :log => true,
20
+ :wsdl => 'path/to/zuora.wsdl'
21
+ )
22
+
23
+ ## Defining Classes
24
+
25
+ You can auto-generate all your Zuora classes from the wsdl file. It will generate all Z-Objects, like Account and Subscription, and Zuora Complex objects, such as SubscribeRequest.
26
+
27
+ ActiveZuora.generate_classes
28
+
29
+ By default, it will generate the classes inside the ActiveZuora module. But you can specify a different nesting if you'd like.
30
+
31
+ ActiveZuora.generate_classes :under => SomeOtherModule
32
+
33
+ Or, if you prefer, you can define your ZObjects or Complex Types manually.
34
+
35
+ class Account
36
+
37
+ include ActiveZuora::ZObject
38
+
39
+ field :name, :string
40
+ field :auto_pay, :boolean, :default => true
41
+ field :balance, :decimal
42
+ field :created_date, :datetime
43
+
44
+ has_many :subscriptions, :order => :name
45
+ has_many :active_subscriptions, :class_name => 'Subscription',
46
+ :conditions => { :status => 'Active' },
47
+ :order => [ :name, :desc ]
48
+ belongs_to :parent, :class_name => 'Account'
49
+ has_many :children, :class_name => 'Account', :foreign_key => :parent_id, :inverse_of => :parent
50
+
51
+ validates_presence_of :name
52
+
53
+ end
54
+
55
+ class SubscriptionData
56
+
57
+ include ActiveZuora::Base
58
+
59
+ field :subscription, :object
60
+ field :rate_plan_data, :object, :array => true
61
+
62
+ end
63
+
64
+ ## Saving, Updating, and Deleting
65
+
66
+ These familiar functions are available: save, create, and update_attributes, along with ! versions that raise exceptions upon failure.
67
+
68
+ account = ActiveZuora::Account.new :name => "Frank's Pest Control"
69
+ account.new_record?
70
+ account.save
71
+
72
+ account = ActiveZuora::Account.create! :name => "Frank's Pest Control"
73
+ account.update_attributes :auto_pay => false, :currency => "USD"
74
+
75
+ Changes are also tracked.
76
+
77
+ account = ActiveZuora::Account.new :name => "Frank's Pest Control"
78
+ account.changes # { :name => [nil, "Frank's Pest Control"] }
79
+ account.save!
80
+ account.changes # []
81
+
82
+ Errors are captured using ActiveModel::Validations, or from error messages received from the server.
83
+
84
+ account = ActiveZuora::Account.new
85
+ account.save # false
86
+ account.errors # { :base => ["Missing attribute: Name"] } # Returned from server.
87
+
88
+ Delete a record with #delete.
89
+
90
+ account.delete
91
+
92
+ ## Querying
93
+
94
+ ActiveZuora::Account.find(id)
95
+
96
+ ActiveZuora::Account.where(:name => "Frank's Pest Control").all
97
+
98
+ ActiveZuora::Account.where(:name => { :like => '%Pest Control' }).count
99
+
100
+ ActiveZuora::Account.where(:auto_pay => true).or(:balance => 0).all
101
+
102
+ ActiveZuora::Account.select(:id, :name).where(:created_date => { "<" => Date.yesterday })
103
+
104
+ There is no "order by" clause in the ZQL query language, but ActiveZuora's query system can post-sort results for you:
105
+
106
+ ActiveZuora::Account.where(:status => "Active").order(:name)
107
+
108
+ ActiveZuora::Account.where(:status => "Draft").order(:created_date, :desc)
109
+
110
+ By default, every Query object caches the results once you call an array-like method on it. However, if you know you'll have a very large result set and you just want to iterate through them without keeping them, you can use `find_each`.
111
+
112
+ ActiveZuora::Account.where(:status => "Active").find_each do |account|
113
+ ...
114
+ end
115
+
116
+ ## Scopes
117
+
118
+ ActiveZuora::Account.instance_eval do
119
+ scope :active, :status => "Active"
120
+ scope :draft, where(:status => "Draft")
121
+ scope :since, lambda { |datetime| where(:created_date => { ">=" => datetime }) }
122
+ end
123
+
124
+ ActiveZuora::Account.select(:id).draft.since(Date.new 2012).to_zql
125
+ # => "select Id from Account where Status = 'Draft' and CreatedDate >= '2012-01-01T00:00:00+08:00'"
126
+
127
+ Like ActiveRecord, you can also chain any class method on the ZObject, since named scopes are nothing more than class methods that return a Relation object.
128
+
129
+ ## Update or Delete Using Queries
130
+
131
+ You can update or delete multiple records at once. The following command issues two requests to the Zuora API server: the first to query for the records, and the second to update them all at once. The method returns the count of records that were successfully updated.
132
+
133
+ ActiveZuora::Account.where(:status => "Draft").update_all :status => "Active" # 56
134
+
135
+ You can also use a block to update your records, in case your updates depend on the records themselves.
136
+
137
+ ActiveZuora::Account.where(:status => "Draft").update_all do |account|
138
+ account.name += " (#{account.currency})"
139
+ end
140
+
141
+ You can also delete all records matching a query as well. The method returns the amount of records deleted.
142
+
143
+ ActiveZuora::Account.where(:status => "Draft").delete_all # 56
144
+
145
+ ## License
146
+
147
+ Active Zuora is released under the MIT license:
148
+
149
+ http://www.opensource.org/licenses/MIT
150
+
151
+ ## Support
152
+
153
+ Bug reports and feature requests can be filed as github issues here:
154
+
155
+ https://github.com/tstmedia/active_zuora/issues
data/Rakefile CHANGED
@@ -1,28 +1,12 @@
1
1
  require "bundler/gem_tasks"
2
2
  require 'bundler'
3
3
  Bundler.setup
4
- require 'rake'
5
- require 'test-unit'
4
+ require 'rspec/core/rake_task'
6
5
 
7
- require 'rake/testtask'
8
- Rake::TestTask.new(:test) do |test|
9
- test.libs << 'lib' << 'test'
10
- test.pattern = 'test/**/test_*.rb'
11
- test.verbose = true
12
- end
6
+ desc 'Default: run library specs.'
7
+ task :default => :spec
13
8
 
14
- begin
15
- require 'rcov/rcovtask'
16
- Rcov::RcovTask.new do |test|
17
- test.libs << 'test'
18
- test.pattern = 'test/**/test_*.rb'
19
- test.verbose = true
20
- end
21
- rescue LoadError
22
- task :rcov do
23
- abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
24
- end
9
+ desc "Run library specs"
10
+ RSpec::Core::RakeTask.new do |t|
11
+ t.pattern = ["./spec/**/*_spec.rb"]
25
12
  end
26
-
27
- task :default => :test
28
-
data/TODO.md ADDED
@@ -0,0 +1,2 @@
1
+ * add deeper customizations for more classes in generator
2
+ * add get_user_info and other operations
@@ -1,72 +1,29 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
1
  # -*- encoding: utf-8 -*-
5
- # stub: active_zuora 1.4.21 ruby lib
6
-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "active_zuora/version"
4
+ authors = {
5
+ "Ed Lebert" => "edlebert@gmail.com",
6
+ "Andy Fleener" => "andy.fleener@tstmedia.com",
7
+ }
7
8
  Gem::Specification.new do |s|
8
- s.name = "active_zuora"
9
- s.version = "1.5.2"
10
-
11
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
9
+ s.name = "active_zuora"
10
+ s.version = ActiveZuora::VERSION.to_s
11
+ s.platform = Gem::Platform::RUBY
12
+ s.authors = authors.keys
13
+ s.email = authors.values
14
+ s.homepage = "https://github.com/tstmedia/active_zuora"
15
+ s.summary = %q{ActiveZuora - Zuora API that looks and feels like ActiveRecord.}
16
+ s.description = %q{ActiveZuora - Zuora API based on ActiveModel and auto-generated from your zuora.wsdl.}
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
20
  s.require_paths = ["lib"]
13
- s.authors = ["Andy Fleener", "Ed Lebert", "Nate Greene"]
14
- s.date = "2015-04-10"
15
- s.description = "A client for Zuora API"
16
- s.email = "andy.fleener@tstmedia.com"
17
- s.extra_rdoc_files = [
18
- "LICENSE",
19
- "README.rdoc"
20
- ]
21
- s.files = [
22
- "Rakefile",
23
- "VERSION",
24
- "active_zuora.gemspec",
25
- "custom_fields.yml",
26
- "lib/active_zuora.rb",
27
- "lib/active_zuora/account.rb",
28
- "lib/active_zuora/amendment.rb",
29
- "lib/active_zuora/bill_run.rb",
30
- "lib/active_zuora/contact.rb",
31
- "lib/active_zuora/invoice.rb",
32
- "lib/active_zuora/invoice_item.rb",
33
- "lib/active_zuora/invoice_item_adjustment.rb",
34
- "lib/active_zuora/invoice_payment.rb",
35
- "lib/active_zuora/payment.rb",
36
- "lib/active_zuora/payment_method.rb",
37
- "lib/active_zuora/product.rb",
38
- "lib/active_zuora/product_rate_plan.rb",
39
- "lib/active_zuora/product_rate_plan_charge.rb",
40
- "lib/active_zuora/product_rate_plan_charge_tier.rb",
41
- "lib/active_zuora/product_rate_plan_charge_tier_data.rb",
42
- "lib/active_zuora/rate_plan.rb",
43
- "lib/active_zuora/rate_plan_charge.rb",
44
- "lib/active_zuora/rate_plan_charge_data.rb",
45
- "lib/active_zuora/rate_plan_charge_tier.rb",
46
- "lib/active_zuora/rate_plan_data.rb",
47
- "lib/active_zuora/refund.rb",
48
- "lib/active_zuora/subscribe_options.rb",
49
- "lib/active_zuora/subscribe_request.rb",
50
- "lib/active_zuora/subscribe_with_existing_account_request.rb",
51
- "lib/active_zuora/subscription.rb",
52
- "lib/active_zuora/subscription_data.rb",
53
- "lib/active_zuora/usage.rb",
54
- "lib/active_zuora/zobject.rb",
55
- "lib/soap/property",
56
- "lib/zuora/ZUORA.rb",
57
- "lib/zuora/ZUORADriver.rb",
58
- "lib/zuora/ZUORAMappingRegistry.rb",
59
- "lib/zuora/ZuoraServiceClient.rb",
60
- "lib/zuora/api.rb",
61
- "lib/zuora_client.rb",
62
- "lib/zuora_interface.rb"
63
- ]
64
- s.homepage = "http://github.com/tstmedia/active_zuora"
65
- s.requirements = ["none"]
66
- s.rubygems_version = "2.4.6"
67
- s.summary = "Active Zuora"
68
- s.add_dependency('soap4r-ng')
69
- s.add_development_dependency('rake')
70
- s.add_development_dependency('test-unit')
71
- end
21
+ s.extra_rdoc_files = [ "README.md" ]
72
22
 
23
+ s.add_runtime_dependency('savon', ["~> 0.9.9"])
24
+ s.add_runtime_dependency('activesupport', [">= 3.0.0", "< 4.0.0"])
25
+ s.add_runtime_dependency('activemodel', [">= 3.0.0", "< 4.0.0"])
26
+
27
+ s.add_development_dependency('rake', ["~> 0.8.7"])
28
+ s.add_development_dependency('rspec', ["~> 2.8.0"])
29
+ end
@@ -1,8 +1,39 @@
1
- require 'delegate'
2
- require 'zuora_client'
3
- require 'active_zuora/zobject.rb'
4
- Dir[File.join(File.dirname(__FILE__),"active_zuora","*.rb")].each do |file|
5
- require file
6
- end
1
+ require 'savon'
2
+ require 'active_model'
3
+ require 'active_support/all'
4
+
5
+ require 'active_zuora/connection'
6
+ require 'active_zuora/generator'
7
+ require 'active_zuora/fields'
8
+ require 'active_zuora/belongs_to_associations'
9
+ require 'active_zuora/base'
10
+ require 'active_zuora/relation'
11
+ require 'active_zuora/scoping'
12
+ require 'active_zuora/persistence'
13
+ require 'active_zuora/has_many_proxy'
14
+ require 'active_zuora/has_many_associations'
15
+ require 'active_zuora/z_object'
16
+ require 'active_zuora/subscribe'
17
+ require 'active_zuora/amend'
18
+ require 'active_zuora/generate'
19
+
20
+ module ActiveZuora
7
21
 
22
+ # Setup configuration. None of this sends a request.
23
+ def self.configure(configuration)
24
+ # Set some sensible defaults with the savon SOAP client.
25
+ Savon.configure do |config|
26
+ config.log = HTTPI.log = configuration[:log] || false
27
+ config.log_level = configuration[:log_level] || :info
28
+ config.raise_errors = true
29
+ end
30
+ # Create a default connection on Base
31
+ Base.connection = Connection.new(configuration)
32
+ end
8
33
 
34
+ def self.generate_classes(options={})
35
+ generator = Generator.new(Base.connection.soap_client.wsdl.parser, options)
36
+ generator.generate_classes
37
+ end
38
+
39
+ end
@@ -0,0 +1,43 @@
1
+ module ActiveZuora
2
+ module Amend
3
+
4
+ # This is meant to be included onto a AmendRequest class.
5
+ # Returns true/false on success.
6
+ # Result hash is stored in #result.
7
+ # If success, the ids will be set in the given amendments.
8
+ # If failure, errors will be present on object.
9
+
10
+ extend ActiveSupport::Concern
11
+
12
+ included do
13
+ include Base
14
+ attr_accessor :result
15
+ end
16
+
17
+ def amend
18
+ self.result = self.class.connection.request(:amend) do |soap|
19
+ soap.body do |xml|
20
+ build_xml(xml, soap,
21
+ :namespace => soap.namespace,
22
+ :element_name => :requests,
23
+ :force_type => true)
24
+ end
25
+ end[:amend_response][:results]
26
+ if result[:success]
27
+ [result[:amendment_ids]].flatten.compact.each_with_index do |id, i|
28
+ amendments[i].id = id
29
+ end
30
+ clear_changed_attributes
31
+ true
32
+ else
33
+ add_zuora_errors(result[:errors])
34
+ false
35
+ end
36
+ end
37
+
38
+ def amend!
39
+ raise "Could not amend: #{errors.full_messages.join ', '}" unless amend
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,73 @@
1
+ require 'bigdecimal'
2
+ require 'bigdecimal/util'
3
+
4
+ module ActiveZuora
5
+ module Base
6
+
7
+ extend ActiveSupport::Concern
8
+
9
+ # This is the default connection object to use for all Base classes.
10
+ # Each individual Base class can overwrite it.
11
+ class << self
12
+ attr_accessor :connection
13
+ end
14
+
15
+ included do
16
+ include Fields
17
+ include ActiveModel::Validations
18
+ include BelongsToAssociations
19
+ class << self
20
+ attr_accessor :namespace
21
+ attr_writer :zuora_object_name
22
+ attr_writer :connection
23
+ end
24
+ delegate :namespace, :zuora_object_name, :to => 'self.class'
25
+ end
26
+
27
+ def xml_field_names
28
+ # Which field names should be rendered during build_xml.
29
+ # Choose only field names that have been changed.
30
+ # Make sure the order in fields is maintained.
31
+ field_names & changed.map(&:to_sym)
32
+ end
33
+
34
+ def build_xml(xml, soap, options={})
35
+ namespace = options.delete(:namespace) || self.namespace
36
+ qualifier = soap.namespace_by_uri(namespace)
37
+ custom_element_name = options.delete(:element_name)
38
+ element_name = custom_element_name || zuora_object_name
39
+ attributes = options.delete(:force_type) ?
40
+ { "xsi:type" => "#{qualifier}:#{zuora_object_name}" } : {}
41
+ xml.tag!(qualifier, element_name.to_sym, attributes) do
42
+ xml_field_names.map { |field_name| get_field!(field_name) }.each do |field|
43
+ field.build_xml(xml, soap, send(field.name), options)
44
+ end
45
+ end
46
+ end
47
+
48
+ def add_zuora_errors(zuora_errors)
49
+ return if zuora_errors.blank?
50
+ zuora_errors = [zuora_errors] unless zuora_errors.is_a?(Array)
51
+ zuora_errors.each { |error| errors.add(:base, error[:message].capitalize) }
52
+ end
53
+
54
+ module ClassMethods
55
+
56
+ def zuora_object_name
57
+ @zuora_object_name ||= self.name.split("::").last
58
+ end
59
+
60
+ def connection
61
+ @connection || Base.connection
62
+ end
63
+
64
+ def nested_class_name(unnested_class_name)
65
+ # This helper method will take a class name, and nest it inside
66
+ # the same module/class as self.
67
+ (name.split("::")[0..-2] << unnested_class_name).join("::")
68
+ end
69
+
70
+ end
71
+
72
+ end
73
+ end