Class: SalesforceAdapter
- Inherits:
-
DataMapper::Adapters::AbstractAdapter
- Object
- DataMapper::Adapters::AbstractAdapter
- SalesforceAdapter
- 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/version.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
Defined Under Namespace
Modules: Property, Resource, SQL Classes: Connection, SoapWrapper
Constant Summary collapse
- Inflector =
::DataMapper::Inflector
- VERSION =
"1.0.2"
Instance Method Summary collapse
-
#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.
- #connection ⇒ Object
-
#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.
- #delete(collection) ⇒ Object
- #handle_server_outage(error) ⇒ Object
-
#initialize(name, uri_or_options) ⇒ SalesforceAdapter
constructor
A new instance of SalesforceAdapter.
-
#read(query) ⇒ Object
Reading responses back from SELECTS: In the typical case, response.size reflects the # of records returned.
- #update(attributes, collection) ⇒ Object
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.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# File 'lib/dm-salesforce-adapter/adapter.rb', line 5 def initialize(name, ) super @resource_naming_convention = proc do |value| klass = 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.
111 112 113 114 115 116 117 118 119 |
# File 'lib/dm-salesforce-adapter/adapter.rb', line 111 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 |
#connection ⇒ Object
20 21 22 |
# File 'lib/dm-salesforce-adapter/adapter.rb', line 20 def connection @connection ||= Connection.new(["username"], ["password"], ["path"], ["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.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/dm-salesforce-adapter/adapter.rb', line 35 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
65 66 67 68 69 70 71 72 73 |
# File 'lib/dm-salesforce-adapter/adapter.rb', line 65 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
75 76 77 78 79 80 81 |
# File 'lib/dm-salesforce-adapter/adapter.rb', line 75 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).
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/dm-salesforce-adapter/adapter.rb', line 90 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 |
#update(attributes, collection) ⇒ Object
55 56 57 58 59 60 61 62 63 |
# File 'lib/dm-salesforce-adapter/adapter.rb', line 55 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 |