Class: Bronto::Base

Inherits:
Object show all
Defined in:
lib/bronto/base.rb

Direct Known Subclasses

Contact, Delivery, Field, List, Message, MessageFolder

Constant Summary collapse

@@api_key =
nil

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Base

Accepts a hash whose keys should be setters on the object.



153
154
155
156
157
# File 'lib/bronto/base.rb', line 153

def initialize(options = {})
  self.api_key = self.class.api_key
  self.errors = Errors.new
  options.each { |k,v| send("#{k}=", v) if respond_to?("#{k}=") }
end

Instance Attribute Details

#api_keyObject

Returns the value of attribute api_key.



10
11
12
# File 'lib/bronto/base.rb', line 10

def api_key
  @api_key
end

#errorsObject

Returns the value of attribute errors.



10
11
12
# File 'lib/bronto/base.rb', line 10

def errors
  @errors
end

#idObject

Returns the value of attribute id.



10
11
12
# File 'lib/bronto/base.rb', line 10

def id
  @id
end

Class Method Details

.api(api_key, refresh = false) ⇒ Object

Sets up the Savon SOAP client object, including sessionHeaders and returns the client.



46
47
48
49
50
51
52
53
54
55
56
# File 'lib/bronto/base.rb', line 46

def self.api(api_key, refresh = false)
  return @api unless refresh || session_expired || @api.nil?

  client = Savon.client(wsdl: 'https://api.bronto.com/v4?wsdl')
  resp = client.call(:login, message: { api_token: api_key })

  @api = Savon.client(wsdl: 'https://api.bronto.com/v4?wsdl', soap_header: {
                                                               "tns:sessionHeader" => { session_id: resp.body[:login_response][:return] }
                                                              },
                                                              read_timeout: 600) # Give Bronto up to 10 minutes to reply
end

.api_keyObject



19
20
21
# File 'lib/bronto/base.rb', line 19

def self.api_key
  @@api_key
end

.api_key=(api_key) ⇒ Object

Getter/Setter for global API Key.



15
16
17
# File 'lib/bronto/base.rb', line 15

def self.api_key=(api_key)
  @@api_key = api_key
end

.create(*objs) ⇒ Object

Tells the remote server to create the passed in collection of Bronto::Base objects. The object should implement ‘to_hash` to return a hash in the format expected by the SOAP API.

Returns the same collection of objects that was passed in. Objects whose creation succeeded will be assigned the ID returned from Bronto. The first element passed in can be a string containing the API key; if none passed, will fall back to the global key.



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/bronto/base.rb', line 97

def self.create(*objs)
  objs = objs.flatten
  api_key = objs.first.is_a?(String) ? objs.shift : self.api_key

  resp = request(:add, {plural_class_name => objs.map(&:to_hash)})

  objs.each { |o| o.errors.clear }

  Array.wrap(resp[:return][:results]).each_with_index do |result, i|
    if result[:is_error]
      objs[i].errors.add(result[:error_code], result[:error_string])
    else
      objs[i].id = result[:id]
    end
  end

  objs
end

.destroy(*objs) ⇒ Object

Destroys a collection of Bronto::Base objects on the remote server.

Returns the same collection of objects that was passed in. Objects whose destruction succeeded will have a nil ID.

The first element passed in can be a string containing the API key; if none passed, will fall back to the global key.



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/bronto/base.rb', line 135

def self.destroy(*objs)
  objs = objs.flatten
  api_key = objs.first.is_a?(String) ? objs.shift : self.api_key

  resp = request(:delete, {plural_class_name => objs.map { |o| { id: o.id }}})

  Array.wrap(resp[:return][:results]).each_with_index do |result, i|
    if result[:is_error]
      objs[i].errors.add(result[:error_code], result[:error_string])
    else
      objs[i].id = nil
    end
  end

  objs
end

.find(filter = Bronto::Filter.new, page_number = 1, api_key = nil) ⇒ Object

Finds objects matching the ‘filter` (a Bronto::Filter instance).



83
84
85
86
87
88
89
# File 'lib/bronto/base.rb', line 83

def self.find(filter = Bronto::Filter.new, page_number = 1, api_key = nil)
  api_key = api_key || self.api_key

  resp = request(:read, { filter: filter.to_hash, page_number: page_number })

  Array.wrap(resp[:return]).map { |hash| new(hash) }
end

.plural_class_nameObject

Simple helper method to convert class name to downcased pluralized version (e.g., Field -> fields).



24
25
26
# File 'lib/bronto/base.rb', line 24

def self.plural_class_name
  self.to_s.split("::").last.downcase.pluralize
end

.request(method, message = {}) ⇒ Object

The primary method used to interface with the SOAP API.

If a symbol is passed in, it is converted to “method_plural_class_name” (e.g., :read => read_lists). A string method is used as-is. The message is a hash and becomes the body of the SOAP request



33
34
35
36
37
38
39
40
41
42
43
# File 'lib/bronto/base.rb', line 33

def self.request(method, message = {})
  api_key = api_key || self.api_key

  method = "#{method}_#{plural_class_name}" if method.is_a? Symbol

  resp = api(api_key).call(method.to_sym, message: message)

  @last_used = Time.now

  resp.body["#{method}_response".to_sym]
end

.save(*objs) ⇒ Object

Saves a collection of Bronto::Base objects. Objects without IDs are considered new and are ‘create`d; objects with IDs are considered existing and are `update`d.



68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/bronto/base.rb', line 68

def self.save(*objs)
  objs = objs.flatten
  api_key = objs.first.is_a?(String) ? objs.shift : self.api_key

  updates = []
  creates = []

  objs.each { |o| (o.id.present? ? updates : creates) << o }

  update(updates) if updates.count > 0
  create(creates) if creates.count > 0
  objs
end

.session_expiredObject

returns true if a cached session identifier is missing or is too old



59
60
61
62
63
64
# File 'lib/bronto/base.rb', line 59

def self.session_expired
  return true if (@last_used == nil)
  return true if (Time.now.tv_sec - @last_used.tv_sec > SESSION_REUSE_SECONDS)

  false
end

.update(*objs) ⇒ Object

Updates a collection of Bronto::Base objects. The objects should exist on the remote server. The object should implement ‘to_hash` to return a hash in the format expected by the SOAP API. The first element passed in can be a string containing the API key; if none passed, will fall back to the global key.



119
120
121
122
123
124
125
126
127
# File 'lib/bronto/base.rb', line 119

def self.update(*objs)
  objs = objs.flatten
  api_key = objs.first.is_a?(String) ? objs.shift : self.api_key

  resp = request(:update, {plural_class_name => objs.map(&:to_hash)})

  objs.each { |o| o.errors.clear }
  objs
end

Instance Method Details

#createObject

Creates the object. See ‘Bronto::Base.create` for more info.



190
191
192
193
# File 'lib/bronto/base.rb', line 190

def create
  res = self.class.create(self.api_key, self)
  res.first
end

#destroyObject

Destroys the object. See ‘Bronto::Base.destroy` for more info.



201
202
203
# File 'lib/bronto/base.rb', line 201

def destroy
  self.class.destroy(self.api_key, self).first
end

#reloadObject



169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/bronto/base.rb', line 169

def reload
  return if self.id.blank?

  # The block below is evaluated in a weird scope so we need to capture self as _self for use inside the block.
  _self = self

  resp = request(:read, { filter: { id: _self.id } })

  resp[:return].each do |k, v|
    self.send("#{k}=", v) if self.respond_to? "#{k}="
  end

  nil
end

#request(method, message = {}) ⇒ Object

Convenience instance method that calls the class ‘request` method.



165
166
167
# File 'lib/bronto/base.rb', line 165

def request(method, message = {})
  self.class.request(method, message)
end

#saveObject

Saves the object. If the object has an ID, it is updated. Otherwise, it is created.



185
186
187
# File 'lib/bronto/base.rb', line 185

def save
  id.blank? ? create : update
end

#to_hashObject

‘to_hash` should be overridden to provide a hash whose structure matches the structure expected by the API.



160
161
162
# File 'lib/bronto/base.rb', line 160

def to_hash
  {}
end

#updateObject

Updates the object. See ‘Bronto::Base.update` for more info.



196
197
198
# File 'lib/bronto/base.rb', line 196

def update
  self.class.update(self.api_key, self).first
end