Class: DataMapper::Adapters::SalesforceAdapter

Inherits:
DataObjectsAdapter
  • Object
show all
Includes:
SQL
Defined in:
lib/dm-salesforce-adapter.rb,
lib/dm-salesforce-adapter/sql.rb,
lib/dm-salesforce-adapter/adapter.rb,
lib/dm-salesforce-adapter/property.rb,
lib/dm-salesforce-adapter/resource.rb,
lib/dm-salesforce-adapter/connection.rb,
lib/dm-salesforce-adapter/soap_wrapper.rb,
lib/dm-salesforce-adapter/property/serial.rb,
lib/dm-salesforce-adapter/property/boolean.rb,
lib/dm-salesforce-adapter/connection/errors.rb

Defined Under Namespace

Modules: Property, Resource, SQL Classes: Connection, SoapWrapper

Instance Method Summary collapse

Methods included from SQL

#comparison_operator, #comparison_statement, #conditions_statement, #equality_operator, #include_operator, #like_operator, #negate_operation, #order, #property_to_column_name, #quote_value, #storage_name

Constructor Details

#initialize(name, uri_or_options) ⇒ SalesforceAdapter

Returns a new instance of SalesforceAdapter.



22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/dm-salesforce-adapter/adapter.rb', line 22

def initialize(name, uri_or_options)
  super
  @resource_naming_convention = proc do |value|
    klass = DataMapper::Inflector.constantize(value)
    if klass.respond_to?(:salesforce_class)
      klass.salesforce_class
    else
      value.split("::").last
    end
  end
  @field_naming_convention = proc do |property|
    connection.field_name_for(property.model.storage_name(name), property.name.to_s)
  end
end

Instance Method Details

#aggregate(query) ⇒ Object

www.salesforce.com/us/developer/docs/api90/Content/sforce_api_calls_soql.htm SOQL doesn’t support anything but count(), so we catch it here and interpret the result. Requires ‘dm-aggregates’ to be loaded.



132
133
134
135
136
137
138
139
140
# File 'lib/dm-salesforce-adapter/adapter.rb', line 132

def aggregate(query)
  query.fields.each do |f|
    unless f.target == :all && f.operator == :count
      raise ArgumentError, %{Aggregate function #{f.operator} not supported in SOQL}
    end
  end

  [ execute_select(query).size ]
end

#connectionObject



41
42
43
# File 'lib/dm-salesforce-adapter/adapter.rb', line 41

def connection
  @connection ||= Connection.new(options["username"], options["password"], options["path"], options["apidir"])
end

#create(resources) ⇒ Object

FIXME: DM Adapters customarily throw exceptions when they experience errors, otherwise failed operations (e.g. Resource#save) still return true and thus confuse the caller.

Someone needs to make a decision about legacy support and the consequences of changing the behaviour from broken-but-typical to correct-but-maybe-unexpected. Maybe a config file option about whether to raise exceptions or for the user to always check Model#valid? + Model#salesforce_errors?

Needs to be applied to all CRUD operations.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/dm-salesforce-adapter/adapter.rb', line 56

def create(resources)
  arr = resources.map do |resource|
    make_salesforce_obj(resource, resource.dirty_attributes)
  end

  result = connection.create(arr)
  result.each_with_index do |record, i|
    resource = resources[i]
    if id_field = resource.class.key.find {|p| p.serial?}
      normalized_value = normalize_id_value(resource.class, id_field, record.id)
      id_field.set!(resource, normalized_value)
    end
  end

  result.size

rescue Connection::SOAPError => e
  handle_server_outage(e)
end

#delete(collection) ⇒ Object



86
87
88
89
90
91
92
93
94
# File 'lib/dm-salesforce-adapter/adapter.rb', line 86

def delete(collection)
  query = collection.query
  keys  = collection.map { |r| r.key }.flatten.uniq

  connection.delete(keys).size

rescue Connection::SOAPError => e
  handle_server_outage(e)
end

#handle_server_outage(error) ⇒ Object



96
97
98
99
100
101
102
# File 'lib/dm-salesforce-adapter/adapter.rb', line 96

def handle_server_outage(error)
  if error.server_unavailable?
    raise Connection::ServerUnavailable, "The salesforce server is currently unavailable"
  else
    raise error
  end
end

#read(query) ⇒ Object

Reading responses back from SELECTS:

In the typical case, response.size reflects the # of records returned.
In the aggregation case, response.size reflects the count.

Interpretation of this field requires knowledge of whether we are expecting an aggregate result, thus the response from execute_select() is processed differently depending on invocation (read vs. aggregate).



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/dm-salesforce-adapter/adapter.rb', line 111

def read(query)
  properties = query.fields
  repository = query.repository

  response = execute_select(query)
  return [] unless response.records

  rows = response.records.inject([]) do |results, record|
    results << properties.inject({}) do |result, property|
      meth = connection.field_name_for(property.model.storage_name(repository.name), property.field)
      result[property] = normalize_id_value(query.model, property, record.send(meth))
      result
    end
  end

  query.model.load(rows, query)
end

#schema_nameObject



37
38
39
# File 'lib/dm-salesforce-adapter/adapter.rb', line 37

def schema_name
  'salesforce'
end

#update(attributes, collection) ⇒ Object



76
77
78
79
80
81
82
83
84
# File 'lib/dm-salesforce-adapter/adapter.rb', line 76

def update(attributes, collection)
  query = collection.query
  arr   = collection.map { |obj| make_salesforce_obj(query, attributes) }

  connection.update(arr).size

rescue Connection::SOAPError => e
  handle_server_outage(e)
end