dm-salesforce 0.9.12 → 0.10.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.markdown +33 -17
 - data/Rakefile +8 -7
 - data/lib/dm-salesforce.rb +19 -10
 - data/lib/dm-salesforce/adapter.rb +91 -130
 - data/lib/dm-salesforce/connection.rb +9 -16
 - data/lib/dm-salesforce/connection/errors.rb +7 -1
 - data/lib/dm-salesforce/resource.rb +8 -0
 - data/lib/dm-salesforce/soap_wrapper.rb +25 -20
 - data/lib/dm-salesforce/sql.rb +74 -46
 - data/lib/dm-salesforce/types.rb +14 -0
 - data/lib/dm-salesforce/types/boolean.rb +23 -0
 - data/lib/dm-salesforce/types/float.rb +8 -0
 - data/lib/dm-salesforce/types/integer.rb +12 -0
 - data/lib/dm-salesforce/types/serial.rb +14 -0
 - data/lib/dm-salesforce/version.rb +2 -2
 - metadata +19 -13
 - data/lib/dm-salesforce/extensions.rb +0 -45
 
    
        data/README.markdown
    CHANGED
    
    | 
         @@ -1,12 +1,20 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            dm-salesforce
         
     | 
| 
       2 
2 
     | 
    
         
             
            =============
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
     | 
    
         
            -
            A gem that provides a Salesforce Adapter for DataMapper.
         
     | 
| 
      
 4 
     | 
    
         
            +
            A gem that provides a Salesforce Adapter for DataMapper 0.10.x.
         
     | 
| 
      
 5 
     | 
    
         
            +
            There are older versions of dm-salesforce specifically for 0.9.x.
         
     | 
| 
       5 
6 
     | 
    
         | 
| 
       6 
     | 
    
         
            -
            The wsdl is converted into Ruby classes  
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
      
 7 
     | 
    
         
            +
            The wsdl is automatically converted into Ruby classes upon the first
         
     | 
| 
      
 8 
     | 
    
         
            +
            invocation of the dm-salesforce adapter.  The classes in turn get
         
     | 
| 
      
 9 
     | 
    
         
            +
            cached locally in one of the following locations, in order of
         
     | 
| 
      
 10 
     | 
    
         
            +
            precedence:
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                :repositories:salesforce:apidir (see included database.yml-example)
         
     | 
| 
      
 13 
     | 
    
         
            +
                ENV["SALESFORCE_DIR"]
         
     | 
| 
      
 14 
     | 
    
         
            +
                ~/.salesforce/
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            It just works if you have the wsdl, directions for getting going are
         
     | 
| 
      
 17 
     | 
    
         
            +
            outlined below.
         
     | 
| 
       10 
18 
     | 
    
         | 
| 
       11 
19 
     | 
    
         
             
            An example of using the adapter:
         
     | 
| 
       12 
20 
     | 
    
         | 
| 
         @@ -17,12 +25,20 @@ An example of using the adapter: 
     | 
|
| 
       17 
25 
     | 
    
         
             
                    :salesforce
         
     | 
| 
       18 
26 
     | 
    
         
             
                  end
         
     | 
| 
       19 
27 
     | 
    
         | 
| 
      
 28 
     | 
    
         
            +
                  # One way to define which properties are SalesForce-style.
         
     | 
| 
       20 
29 
     | 
    
         
             
                  def self.salesforce_id_properties
         
     | 
| 
       21 
30 
     | 
    
         
             
                    :id
         
     | 
| 
       22 
31 
     | 
    
         
             
                  end
         
     | 
| 
       23 
32 
     | 
    
         | 
| 
       24 
     | 
    
         
            -
                  property :id, 
     | 
| 
       25 
     | 
    
         
            -
                  property :name, 
     | 
| 
      
 33 
     | 
    
         
            +
                  property :id,          String, :key => true
         
     | 
| 
      
 34 
     | 
    
         
            +
                  property :name,        String
         
     | 
| 
      
 35 
     | 
    
         
            +
                  property :description, String
         
     | 
| 
      
 36 
     | 
    
         
            +
                  property :fax,         String
         
     | 
| 
      
 37 
     | 
    
         
            +
                  property :phone,       String
         
     | 
| 
      
 38 
     | 
    
         
            +
                  property :type,        String
         
     | 
| 
      
 39 
     | 
    
         
            +
                  property :website,     String
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  has 0..n, :contacts
         
     | 
| 
       26 
42 
     | 
    
         
             
                end
         
     | 
| 
       27 
43 
     | 
    
         | 
| 
       28 
44 
     | 
    
         
             
                class Contact
         
     | 
| 
         @@ -32,15 +48,12 @@ An example of using the adapter: 
     | 
|
| 
       32 
48 
     | 
    
         
             
                    :salesforce
         
     | 
| 
       33 
49 
     | 
    
         
             
                  end
         
     | 
| 
       34 
50 
     | 
    
         | 
| 
       35 
     | 
    
         
            -
                   
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
                  end
         
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
                  property :id,    String, :serial => true
         
     | 
| 
      
 51 
     | 
    
         
            +
                  # Alternatively, specify the :salesforce_id option.
         
     | 
| 
      
 52 
     | 
    
         
            +
                  property :id,         String, :serial => true, :salesforce_id => true
         
     | 
| 
       40 
53 
     | 
    
         
             
                  property :first_name, String
         
     | 
| 
       41 
     | 
    
         
            -
                  property :last_name, 
     | 
| 
       42 
     | 
    
         
            -
                  property :email, 
     | 
| 
       43 
     | 
    
         
            -
                  property :account_id, String
         
     | 
| 
      
 54 
     | 
    
         
            +
                  property :last_name,  String
         
     | 
| 
      
 55 
     | 
    
         
            +
                  property :email,      String
         
     | 
| 
      
 56 
     | 
    
         
            +
                  property :account_id, String, :salesforce_id => true
         
     | 
| 
       44 
57 
     | 
    
         | 
| 
       45 
58 
     | 
    
         
             
                  belongs_to :account
         
     | 
| 
       46 
59 
     | 
    
         
             
                end
         
     | 
| 
         @@ -48,7 +61,6 @@ An example of using the adapter: 
     | 
|
| 
       48 
61 
     | 
    
         | 
| 
       49 
62 
     | 
    
         
             
            To get a test environment going with the free development tools you'll need to follow these steps.
         
     | 
| 
       50 
63 
     | 
    
         | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
64 
     | 
    
         
             
            * Get a developer account from http://force.salesforce.com
         
     | 
| 
       53 
65 
     | 
    
         
             
            * Hit up https://login.salesforce.com, and login with the password they provided in your signup email
         
     | 
| 
       54 
66 
     | 
    
         
             
            * Remember the password they force you to reset
         
     | 
| 
         @@ -68,12 +80,16 @@ To get a test environment going with the free development tools you'll need to f 
     | 
|
| 
       68 
80 
     | 
    
         
             
                    VALID_SELF_SERVICE_USER = DataMapperSalesforce::UserDetails.new("quentin@example.com", "foo")
         
     | 
| 
       69 
81 
     | 
    
         
             
            * Run 'bin/irb' and you should have access to the Account and Contact models
         
     | 
| 
       70 
82 
     | 
    
         | 
| 
       71 
     | 
    
         
            -
            Special Thanks to  
     | 
| 
      
 83 
     | 
    
         
            +
            Special Thanks to those who helped
         
     | 
| 
       72 
84 
     | 
    
         
             
            ==================================================
         
     | 
| 
      
 85 
     | 
    
         
            +
            * Yehuda Katz
         
     | 
| 
       73 
86 
     | 
    
         
             
            * Corey Donohoe
         
     | 
| 
      
 87 
     | 
    
         
            +
            * Tim Carey-Smith
         
     | 
| 
       74 
88 
     | 
    
         
             
            * Andy Delcambre
         
     | 
| 
       75 
89 
     | 
    
         
             
            * Ben Burkert
         
     | 
| 
       76 
90 
     | 
    
         
             
            * Larry Diehl
         
     | 
| 
      
 91 
     | 
    
         
            +
            * Jordan Ritter
         
     | 
| 
      
 92 
     | 
    
         
            +
            * Martin Emde
         
     | 
| 
       77 
93 
     | 
    
         | 
| 
       78 
94 
     | 
    
         
             
            [setup]: http://img.skitch.com/20090204-gaxdfxbi1emfita5dax48ids4m.jpg "Click on Setup"
         
     | 
| 
       79 
95 
     | 
    
         
             
            [getwsdl]: http://img.skitch.com/20090204-nhurnuxwf5g3ufnjk2xkfjc5n4.jpg "Expand and Save"
         
     | 
    
        data/Rakefile
    CHANGED
    
    | 
         @@ -4,15 +4,16 @@ require 'rubygems/specification' 
     | 
|
| 
       4 
4 
     | 
    
         
             
            require 'bundler'
         
     | 
| 
       5 
5 
     | 
    
         
             
            require 'date'
         
     | 
| 
       6 
6 
     | 
    
         
             
            require 'pp'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'tmpdir'
         
     | 
| 
       7 
8 
     | 
    
         | 
| 
       8 
9 
     | 
    
         
             
            Bundler.require_env
         
     | 
| 
       9 
10 
     | 
    
         
             
            require File.dirname(__FILE__) + '/lib/dm-salesforce'
         
     | 
| 
       10 
11 
     | 
    
         | 
| 
       11 
12 
     | 
    
         
             
            GEM = "dm-salesforce"
         
     | 
| 
       12 
     | 
    
         
            -
            GEM_VERSION =  
     | 
| 
       13 
     | 
    
         
            -
            AUTHORS = ["Yehuda Katz", 'Tim Carey-Smith']
         
     | 
| 
       14 
     | 
    
         
            -
            EMAIL = " 
     | 
| 
       15 
     | 
    
         
            -
            HOMEPAGE = "http:// 
     | 
| 
      
 13 
     | 
    
         
            +
            GEM_VERSION = DataMapper::Salesforce::VERSION
         
     | 
| 
      
 14 
     | 
    
         
            +
            AUTHORS = ["Yehuda Katz", 'Tim Carey-Smith', 'Corey Donohoe']
         
     | 
| 
      
 15 
     | 
    
         
            +
            EMAIL = "ninja@engineyard.com"
         
     | 
| 
      
 16 
     | 
    
         
            +
            HOMEPAGE = "http://github.com/halorgium/dm-salesforce"
         
     | 
| 
       16 
17 
     | 
    
         
             
            SUMMARY = "A DataMapper adapter to the Salesforce API"
         
     | 
| 
       17 
18 
     | 
    
         | 
| 
       18 
19 
     | 
    
         
             
            @spec = Gem::Specification.new do |s|
         
     | 
| 
         @@ -43,7 +44,7 @@ end 
     | 
|
| 
       43 
44 
     | 
    
         | 
| 
       44 
45 
     | 
    
         
             
            desc "install the gem locally"
         
     | 
| 
       45 
46 
     | 
    
         
             
            task :install => [:package] do
         
     | 
| 
       46 
     | 
    
         
            -
              sh %{ 
     | 
| 
      
 47 
     | 
    
         
            +
              sh %{gem install pkg/#{GEM}-#{GEM_VERSION} --no-ri --no-rdoc}
         
     | 
| 
       47 
48 
     | 
    
         
             
            end
         
     | 
| 
       48 
49 
     | 
    
         | 
| 
       49 
50 
     | 
    
         
             
            task :default => 'spec'
         
     | 
| 
         @@ -53,9 +54,9 @@ desc "Run specs" 
     | 
|
| 
       53 
54 
     | 
    
         
             
            Spec::Rake::SpecTask.new(:spec) do |t|
         
     | 
| 
       54 
55 
     | 
    
         
             
              t.spec_opts << %w(-fs --color) << %w(-O spec/spec.opts)
         
     | 
| 
       55 
56 
     | 
    
         
             
              t.spec_opts << '--loadby' << 'random'
         
     | 
| 
       56 
     | 
    
         
            -
              t.spec_files =  
     | 
| 
      
 57 
     | 
    
         
            +
              t.spec_files = Dir["spec/**/*_spec.rb"]
         
     | 
| 
       57 
58 
     | 
    
         
             
              t.rcov = ENV.has_key?('NO_RCOV') ? ENV['NO_RCOV'] != 'true' : true
         
     | 
| 
       58 
     | 
    
         
            -
              t.rcov_opts << '--exclude' <<  
     | 
| 
      
 59 
     | 
    
         
            +
              t.rcov_opts << '--exclude' << "~/.salesforce,gems,vendor,/var/folders,spec,config,tmp"
         
     | 
| 
       59 
60 
     | 
    
         
             
              t.rcov_opts << '--text-summary'
         
     | 
| 
       60 
61 
     | 
    
         
             
              t.rcov_opts << '--sort' << 'coverage' << '--sort-reverse'
         
     | 
| 
       61 
62 
     | 
    
         
             
            end
         
     | 
    
        data/lib/dm-salesforce.rb
    CHANGED
    
    | 
         @@ -1,15 +1,24 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
      
 1 
     | 
    
         
            +
            require "fileutils"
         
     | 
| 
       3 
2 
     | 
    
         
             
            require 'dm-core'
         
     | 
| 
       4 
3 
     | 
    
         
             
            require 'dm-validations'
         
     | 
| 
       5 
     | 
    
         
            -
            require ' 
     | 
| 
       6 
     | 
    
         
            -
            require ' 
     | 
| 
       7 
     | 
    
         
            -
            require  
     | 
| 
       8 
     | 
    
         
            -
            require 'dm-salesforce/connection'
         
     | 
| 
       9 
     | 
    
         
            -
            require 'dm-salesforce/version'
         
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
            DataMapper::Adapters::SalesforceAdapter = DataMapperSalesforce::Adapter
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'soap/wsdlDriver'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'soap/header/simplehandler'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require "rexml/element"
         
     | 
| 
       12 
7 
     | 
    
         | 
| 
       13 
     | 
    
         
            -
            module  
     | 
| 
      
 8 
     | 
    
         
            +
            module DataMapper::Salesforce
         
     | 
| 
       14 
9 
     | 
    
         
             
              UserDetails = Struct.new(:username, :password)
         
     | 
| 
       15 
10 
     | 
    
         
             
            end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            dir = File.expand_path(File.join(File.dirname(__FILE__), 'dm-salesforce'))
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            require dir / :resource
         
     | 
| 
      
 15 
     | 
    
         
            +
            require dir / :connection
         
     | 
| 
      
 16 
     | 
    
         
            +
            require dir / :connection / :errors
         
     | 
| 
      
 17 
     | 
    
         
            +
            require dir / :soap_wrapper
         
     | 
| 
      
 18 
     | 
    
         
            +
            require dir / :sql
         
     | 
| 
      
 19 
     | 
    
         
            +
            require dir / :types
         
     | 
| 
      
 20 
     | 
    
         
            +
            require dir / :version
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            require dir / :adapter
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            DataMapper::Adapters::SalesforceAdapter = DataMapper::Salesforce::Adapter
         
     | 
| 
         @@ -1,5 +1,7 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module  
     | 
| 
      
 1 
     | 
    
         
            +
            module DataMapper::Salesforce
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Adapter < DataMapper::Adapters::AbstractAdapter
         
     | 
| 
      
 3 
     | 
    
         
            +
                include SQL
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
       3 
5 
     | 
    
         
             
                def initialize(name, uri_or_options)
         
     | 
| 
       4 
6 
     | 
    
         
             
                  super
         
     | 
| 
       5 
7 
     | 
    
         
             
                  @resource_naming_convention = proc do |value|
         
     | 
| 
         @@ -15,185 +17,144 @@ module DataMapperSalesforce 
     | 
|
| 
       15 
17 
     | 
    
         
             
                  end
         
     | 
| 
       16 
18 
     | 
    
         
             
                end
         
     | 
| 
       17 
19 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
                def normalize_uri(uri_or_options)
         
     | 
| 
       19 
     | 
    
         
            -
                  if uri_or_options.kind_of?(Addressable::URI)
         
     | 
| 
       20 
     | 
    
         
            -
                    return uri_or_options
         
     | 
| 
       21 
     | 
    
         
            -
                  end
         
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
                  if uri_or_options.kind_of?(String)
         
     | 
| 
       24 
     | 
    
         
            -
                    uri_or_options = Addressable::URI.parse(uri_or_options)
         
     | 
| 
       25 
     | 
    
         
            -
                  end
         
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
                  adapter  = uri_or_options.delete(:adapter).to_s
         
     | 
| 
       28 
     | 
    
         
            -
                  user     = uri_or_options.delete(:username)
         
     | 
| 
       29 
     | 
    
         
            -
                  password = uri_or_options.delete(:password)
         
     | 
| 
       30 
     | 
    
         
            -
                  host     = uri_or_options.delete(:host) || "."
         
     | 
| 
       31 
     | 
    
         
            -
                  path     = uri_or_options.delete(:path)
         
     | 
| 
       32 
     | 
    
         
            -
                  query    = uri_or_options.to_a.map { |pair| pair * '=' } * '&'
         
     | 
| 
       33 
     | 
    
         
            -
                  query    = nil if query == ''
         
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
                  return Addressable::URI.new({:adapter => adapter, :user => user, :password => password, :host => host, :path => path, :query => query})
         
     | 
| 
       36 
     | 
    
         
            -
                end
         
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
20 
     | 
    
         
             
                def connection
         
     | 
| 
       39 
     | 
    
         
            -
                  @connection ||= Connection.new( 
     | 
| 
       40 
     | 
    
         
            -
                end
         
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
                def read_many(query)
         
     | 
| 
       43 
     | 
    
         
            -
                  ::DataMapper::Collection.new(query) do |set|
         
     | 
| 
       44 
     | 
    
         
            -
                    read(query) do |result|
         
     | 
| 
       45 
     | 
    
         
            -
                      set.load(result)
         
     | 
| 
       46 
     | 
    
         
            -
                    end
         
     | 
| 
       47 
     | 
    
         
            -
                  end
         
     | 
| 
       48 
     | 
    
         
            -
                end
         
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
                def read_one(query)
         
     | 
| 
       51 
     | 
    
         
            -
                  read(query) do |result|
         
     | 
| 
       52 
     | 
    
         
            -
                    return query.model.load(result, query)
         
     | 
| 
       53 
     | 
    
         
            -
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @connection ||= Connection.new(options["username"], options["password"], options["path"], options["apidir"])
         
     | 
| 
       54 
22 
     | 
    
         
             
                end
         
     | 
| 
       55 
23 
     | 
    
         | 
| 
       56 
24 
     | 
    
         
             
                def create(resources)
         
     | 
| 
       57 
25 
     | 
    
         
             
                  arr = resources.map do |resource|
         
     | 
| 
       58 
     | 
    
         
            -
                     
     | 
| 
      
 26 
     | 
    
         
            +
                    make_salesforce_obj(resource, resource.dirty_attributes)
         
     | 
| 
       59 
27 
     | 
    
         
             
                  end
         
     | 
| 
       60 
28 
     | 
    
         | 
| 
       61 
29 
     | 
    
         
             
                  result = connection.create(arr)
         
     | 
| 
       62 
30 
     | 
    
         
             
                  result.each_with_index do |record, i|
         
     | 
| 
       63 
31 
     | 
    
         
             
                    resource = resources[i]
         
     | 
| 
       64 
     | 
    
         
            -
                    id_field = resource.class.key 
     | 
| 
       65 
     | 
    
         
            -
                    if id_field
         
     | 
| 
      
 32 
     | 
    
         
            +
                    if id_field = resource.class.key.find {|p| p.serial?}
         
     | 
| 
       66 
33 
     | 
    
         
             
                      normalized_value = normalize_id_value(resource.class, id_field, record.id)
         
     | 
| 
       67 
34 
     | 
    
         
             
                      id_field.set!(resource, normalized_value)
         
     | 
| 
       68 
35 
     | 
    
         
             
                    end
         
     | 
| 
       69 
36 
     | 
    
         
             
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
       70 
38 
     | 
    
         
             
                  result.size
         
     | 
| 
       71 
     | 
    
         
            -
             
     | 
| 
       72 
     | 
    
         
            -
             
     | 
| 
       73 
     | 
    
         
            -
                  e 
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                rescue Connection::SOAPError => e
         
     | 
| 
      
 41 
     | 
    
         
            +
                  handle_server_outage(e)
         
     | 
| 
       74 
42 
     | 
    
         
             
                end
         
     | 
| 
       75 
43 
     | 
    
         | 
| 
       76 
     | 
    
         
            -
                def update(attributes,  
     | 
| 
       77 
     | 
    
         
            -
                   
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
       79 
     | 
    
         
            -
             
     | 
| 
       80 
     | 
    
         
            -
                    read_many(query).map do |obj|
         
     | 
| 
       81 
     | 
    
         
            -
                      obj = make_salesforce_obj(query, attributes, x.key)
         
     | 
| 
       82 
     | 
    
         
            -
                    end
         
     | 
| 
       83 
     | 
    
         
            -
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
                def update(attributes, collection)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  query = collection.query
         
     | 
| 
      
 46 
     | 
    
         
            +
                  arr   = collection.map { |obj| make_salesforce_obj(query, attributes) }
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
       84 
48 
     | 
    
         
             
                  connection.update(arr).size
         
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
       86 
     | 
    
         
            -
             
     | 
| 
       87 
     | 
    
         
            -
                  e 
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                rescue Connection::SOAPError => e
         
     | 
| 
      
 51 
     | 
    
         
            +
                  handle_server_outage(e)
         
     | 
| 
       88 
52 
     | 
    
         
             
                end
         
     | 
| 
       89 
53 
     | 
    
         | 
| 
       90 
     | 
    
         
            -
                def delete( 
     | 
| 
       91 
     | 
    
         
            -
                   
     | 
| 
       92 
     | 
    
         
            -
             
     | 
| 
       93 
     | 
    
         
            -
                  else
         
     | 
| 
       94 
     | 
    
         
            -
                    query.read_many.map {|r| r.key}
         
     | 
| 
       95 
     | 
    
         
            -
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
                def delete(collection)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  query = collection.query
         
     | 
| 
      
 56 
     | 
    
         
            +
                  keys  = collection.map { |r| r.key }.flatten.uniq
         
     | 
| 
       96 
57 
     | 
    
         | 
| 
       97 
58 
     | 
    
         
             
                  connection.delete(keys).size
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                rescue Connection::SOAPError => e
         
     | 
| 
      
 61 
     | 
    
         
            +
                  handle_server_outage(e)
         
     | 
| 
       98 
62 
     | 
    
         
             
                end
         
     | 
| 
       99 
63 
     | 
    
         | 
| 
       100 
     | 
    
         
            -
                def  
     | 
| 
       101 
     | 
    
         
            -
                   
     | 
| 
       102 
     | 
    
         
            -
                     
     | 
| 
      
 64 
     | 
    
         
            +
                def handle_server_outage(error)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  if error.server_unavailable?
         
     | 
| 
      
 66 
     | 
    
         
            +
                    raise Connection::ServerUnavailable, "The salesforce server is currently unavailable"
         
     | 
| 
      
 67 
     | 
    
         
            +
                  else
         
     | 
| 
      
 68 
     | 
    
         
            +
                    raise error
         
     | 
| 
      
 69 
     | 
    
         
            +
                  end
         
     | 
| 
      
 70 
     | 
    
         
            +
                end
         
     | 
| 
       103 
71 
     | 
    
         | 
| 
       104 
     | 
    
         
            -
             
     | 
| 
       105 
     | 
    
         
            -
             
     | 
| 
       106 
     | 
    
         
            -
             
     | 
| 
       107 
     | 
    
         
            -
             
     | 
| 
       108 
     | 
    
         
            -
             
     | 
| 
       109 
     | 
    
         
            -
             
     | 
| 
       110 
     | 
    
         
            -
             
     | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
       113 
     | 
    
         
            -
             
     | 
| 
       114 
     | 
    
         
            -
             
     | 
| 
       115 
     | 
    
         
            -
             
     | 
| 
       116 
     | 
    
         
            -
             
     | 
| 
       117 
     | 
    
         
            -
             
     | 
| 
       118 
     | 
    
         
            -
             
     | 
| 
       119 
     | 
    
         
            -
             
     | 
| 
       120 
     | 
    
         
            -
             
     | 
| 
       121 
     | 
    
         
            -
             
     | 
| 
       122 
     | 
    
         
            -
             
     | 
| 
       123 
     | 
    
         
            -
                      when "SERVER_UNAVAILABLE"
         
     | 
| 
       124 
     | 
    
         
            -
                        raise Connection::ServerUnavailable, "The salesforce server is currently unavailable"
         
     | 
| 
       125 
     | 
    
         
            -
                      else
         
     | 
| 
       126 
     | 
    
         
            -
                        raise Connection::UnknownStatusCode, "Got an unknown statusCode: #{error.statusCode.inspect}"
         
     | 
| 
       127 
     | 
    
         
            -
                      end
         
     | 
| 
      
 72 
     | 
    
         
            +
                # Reading responses back from SELECTS:
         
     | 
| 
      
 73 
     | 
    
         
            +
                #   In the typical case, response.size reflects the # of records returned.
         
     | 
| 
      
 74 
     | 
    
         
            +
                #   In the aggregation case, response.size reflects the count.
         
     | 
| 
      
 75 
     | 
    
         
            +
                #
         
     | 
| 
      
 76 
     | 
    
         
            +
                # Interpretation of this field requires knowledge of whether we
         
     | 
| 
      
 77 
     | 
    
         
            +
                # are expecting an aggregate result, thus the response is
         
     | 
| 
      
 78 
     | 
    
         
            +
                # processed differently depending on invocation.
         
     | 
| 
      
 79 
     | 
    
         
            +
                def read(query)
         
     | 
| 
      
 80 
     | 
    
         
            +
                  properties = query.fields
         
     | 
| 
      
 81 
     | 
    
         
            +
                  repository = query.repository
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                  response = execute_query(query)
         
     | 
| 
      
 84 
     | 
    
         
            +
                  return [] unless response.records
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                  rows = response.records.inject([]) do |results, record|
         
     | 
| 
      
 87 
     | 
    
         
            +
                    results << properties.inject({}) do |result, property|
         
     | 
| 
      
 88 
     | 
    
         
            +
                      meth = connection.field_name_for(property.model.storage_name(repository.name), property.field)
         
     | 
| 
      
 89 
     | 
    
         
            +
                      result[property] = normalize_id_value(query.model, property, record.send(meth))
         
     | 
| 
      
 90 
     | 
    
         
            +
                      result
         
     | 
| 
       128 
91 
     | 
    
         
             
                    end
         
     | 
| 
       129 
92 
     | 
    
         
             
                  end
         
     | 
| 
       130 
     | 
    
         
            -
                end
         
     | 
| 
       131 
93 
     | 
    
         | 
| 
       132 
     | 
    
         
            -
             
     | 
| 
       133 
     | 
    
         
            -
                def destroy_model_storage(*args)
         
     | 
| 
       134 
     | 
    
         
            -
                  true
         
     | 
| 
      
 94 
     | 
    
         
            +
                  query.model.load(rows, query)
         
     | 
| 
       135 
95 
     | 
    
         
             
                end
         
     | 
| 
       136 
96 
     | 
    
         | 
| 
       137 
     | 
    
         
            -
                #  
     | 
| 
       138 
     | 
    
         
            -
                 
     | 
| 
       139 
     | 
    
         
            -
             
     | 
| 
       140 
     | 
    
         
            -
                 
     | 
| 
      
 97 
     | 
    
         
            +
                # http://www.salesforce.com/us/developer/docs/api90/Content/sforce_api_calls_soql.htm
         
     | 
| 
      
 98 
     | 
    
         
            +
                # SOQL doesn't support anything but count(), so we catch it here
         
     | 
| 
      
 99 
     | 
    
         
            +
                # and interpret the result.
         
     | 
| 
      
 100 
     | 
    
         
            +
                def aggregate(query)
         
     | 
| 
      
 101 
     | 
    
         
            +
                  query.fields.each do |f|
         
     | 
| 
      
 102 
     | 
    
         
            +
                    unless f.target == :all && f.operator == :count
         
     | 
| 
      
 103 
     | 
    
         
            +
                      raise ArgumentError, %{Aggregate function #{f.operator} not supported in SOQL}
         
     | 
| 
      
 104 
     | 
    
         
            +
                    end
         
     | 
| 
      
 105 
     | 
    
         
            +
                  end
         
     | 
| 
       141 
106 
     | 
    
         | 
| 
       142 
     | 
    
         
            -
             
     | 
| 
       143 
     | 
    
         
            -
                def create_model_storage(*args)
         
     | 
| 
       144 
     | 
    
         
            -
                  true
         
     | 
| 
      
 107 
     | 
    
         
            +
                  [ execute_query(query).size ]
         
     | 
| 
       145 
108 
     | 
    
         
             
                end
         
     | 
| 
       146 
109 
     | 
    
         | 
| 
       147 
110 
     | 
    
         
             
                private
         
     | 
| 
       148 
     | 
    
         
            -
                def  
     | 
| 
      
 111 
     | 
    
         
            +
                def execute_query(query)
         
     | 
| 
       149 
112 
     | 
    
         
             
                  repository = query.repository
         
     | 
| 
       150 
     | 
    
         
            -
                   
     | 
| 
       151 
     | 
    
         
            -
             
     | 
| 
       152 
     | 
    
         
            -
                   
     | 
| 
      
 113 
     | 
    
         
            +
                  conditions = query.conditions.map {|c| from_condition(c, repository)}.compact.join(") AND (")
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
                  fields = query.fields.map do |f|
         
     | 
| 
      
 116 
     | 
    
         
            +
                    case f
         
     | 
| 
      
 117 
     | 
    
         
            +
                      when DataMapper::Property
         
     | 
| 
      
 118 
     | 
    
         
            +
                        f.field
         
     | 
| 
      
 119 
     | 
    
         
            +
                      when DataMapper::Query::Operator
         
     | 
| 
      
 120 
     | 
    
         
            +
                        %{#{f.operator}()}
         
     | 
| 
      
 121 
     | 
    
         
            +
                      else
         
     | 
| 
      
 122 
     | 
    
         
            +
                        raise ArgumentError, "Unknown query field #{f.class}: #{f.inspect}"
         
     | 
| 
      
 123 
     | 
    
         
            +
                    end
         
     | 
| 
      
 124 
     | 
    
         
            +
                  end.join(", ")
         
     | 
| 
       153 
125 
     | 
    
         | 
| 
       154 
     | 
    
         
            -
                  sql = "SELECT #{ 
     | 
| 
      
 126 
     | 
    
         
            +
                  sql = "SELECT #{fields} from #{query.model.storage_name(repository.name)}"
         
     | 
| 
       155 
127 
     | 
    
         
             
                  sql << " WHERE (#{conditions})" unless conditions.empty?
         
     | 
| 
       156 
     | 
    
         
            -
                  sql << " ORDER BY #{ 
     | 
| 
      
 128 
     | 
    
         
            +
                  sql << " ORDER BY #{order(query.order[0])}" unless query.order.empty?
         
     | 
| 
       157 
129 
     | 
    
         
             
                  sql << " LIMIT #{query.limit}" if query.limit
         
     | 
| 
       158 
130 
     | 
    
         | 
| 
       159 
     | 
    
         
            -
                  DataMapper.logger.debug sql
         
     | 
| 
      
 131 
     | 
    
         
            +
                  DataMapper.logger.debug sql if DataMapper.logger
         
     | 
| 
       160 
132 
     | 
    
         | 
| 
       161 
     | 
    
         
            -
                   
     | 
| 
      
 133 
     | 
    
         
            +
                  connection.query(sql)
         
     | 
| 
      
 134 
     | 
    
         
            +
                end
         
     | 
| 
       162 
135 
     | 
    
         | 
| 
       163 
     | 
    
         
            -
             
     | 
| 
      
 136 
     | 
    
         
            +
                def make_salesforce_obj(from, with_attrs)
         
     | 
| 
      
 137 
     | 
    
         
            +
                  klass_name = from.model.storage_name(from.repository.name)
         
     | 
| 
      
 138 
     | 
    
         
            +
                  values     = {}
         
     | 
| 
       164 
139 
     | 
    
         | 
| 
       165 
     | 
    
         
            -
                   
     | 
| 
       166 
     | 
    
         
            -
             
     | 
| 
       167 
     | 
    
         
            -
                     
     | 
| 
       168 
     | 
    
         
            -
             
     | 
| 
       169 
     | 
    
         
            -
                      accum[idx] = normalize_id_value(query.model, property, record.send(meth))
         
     | 
| 
       170 
     | 
    
         
            -
                    end
         
     | 
| 
       171 
     | 
    
         
            -
                    yield accum
         
     | 
| 
      
 140 
     | 
    
         
            +
                  # FIXME: query.conditions is potentially a tree now
         
     | 
| 
      
 141 
     | 
    
         
            +
                  if from.is_a?(::DataMapper::Query)
         
     | 
| 
      
 142 
     | 
    
         
            +
                    key_value    = from.conditions.find { |c| c.subject.key? }.value
         
     | 
| 
      
 143 
     | 
    
         
            +
                    values["id"] = normalize_id_value(from.model, from.model.properties[:id], key_value)
         
     | 
| 
       172 
144 
     | 
    
         
             
                  end
         
     | 
| 
       173 
     | 
    
         
            -
                end
         
     | 
| 
       174 
145 
     | 
    
         | 
| 
       175 
     | 
    
         
            -
             
     | 
| 
       176 
     | 
    
         
            -
             
     | 
| 
       177 
     | 
    
         
            -
             
     | 
| 
       178 
     | 
    
         
            -
                  if key
         
     | 
| 
       179 
     | 
    
         
            -
                    key_value = query.conditions.find {|op,prop,val| prop.key?}.last
         
     | 
| 
       180 
     | 
    
         
            -
                    values["id"] = normalize_id_value(query.model, query.model.properties[:id], key_value)
         
     | 
| 
      
 146 
     | 
    
         
            +
                  with_attrs.each do |property, value|
         
     | 
| 
      
 147 
     | 
    
         
            +
                    next if property.serial? || property.key? and value.nil?
         
     | 
| 
      
 148 
     | 
    
         
            +
                    values[property.field] = normalize_id_value(from.model, property, value)
         
     | 
| 
       181 
149 
     | 
    
         
             
                  end
         
     | 
| 
       182 
150 
     | 
    
         | 
| 
       183 
     | 
    
         
            -
                  attrs.each do |property,value|
         
     | 
| 
       184 
     | 
    
         
            -
                    normalized_value = normalize_id_value(query.model, property, value)
         
     | 
| 
       185 
     | 
    
         
            -
                    values[property.field(query.repository.name)] = normalized_value
         
     | 
| 
       186 
     | 
    
         
            -
                  end
         
     | 
| 
       187 
151 
     | 
    
         
             
                  connection.make_object(klass_name, values)
         
     | 
| 
       188 
152 
     | 
    
         
             
                end
         
     | 
| 
       189 
153 
     | 
    
         | 
| 
       190 
154 
     | 
    
         
             
                def normalize_id_value(klass, property, value)
         
     | 
| 
       191 
     | 
    
         
            -
                  return  
     | 
| 
       192 
     | 
    
         
            -
                   
     | 
| 
       193 
     | 
    
         
            -
             
     | 
| 
       194 
     | 
    
         
            -
                    return value[0..14] if properties.include?(property.name)
         
     | 
| 
       195 
     | 
    
         
            -
                  end
         
     | 
| 
       196 
     | 
    
         
            -
                  value
         
     | 
| 
      
 155 
     | 
    
         
            +
                  return nil unless value
         
     | 
| 
      
 156 
     | 
    
         
            +
                  properties = Array(klass.send(:salesforce_id_properties)).map { |p| p.to_sym } rescue []
         
     | 
| 
      
 157 
     | 
    
         
            +
                  return properties.include?(property.name) ? value[0..14] : value
         
     | 
| 
       197 
158 
     | 
    
         
             
                end
         
     | 
| 
       198 
159 
     | 
    
         
             
              end
         
     | 
| 
       199 
160 
     | 
    
         
             
            end
         
     | 
| 
         @@ -1,9 +1,4 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
       2 
     | 
    
         
            -
            require 'soap/header/simplehandler'
         
     | 
| 
       3 
     | 
    
         
            -
            require "rexml/element"
         
     | 
| 
       4 
     | 
    
         
            -
            require 'dm-salesforce/soap_wrapper'
         
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
            module DataMapperSalesforce
         
     | 
| 
      
 1 
     | 
    
         
            +
            module DataMapper::Salesforce
         
     | 
| 
       7 
2 
     | 
    
         
             
              class Connection
         
     | 
| 
       8 
3 
     | 
    
         
             
                class HeaderHandler < SOAP::Header::SimpleHandler
         
     | 
| 
       9 
4 
     | 
    
         
             
                  def initialize(tag, value)
         
     | 
| 
         @@ -16,7 +11,7 @@ module DataMapperSalesforce 
     | 
|
| 
       16 
11 
     | 
    
         
             
                  end
         
     | 
| 
       17 
12 
     | 
    
         
             
                end
         
     | 
| 
       18 
13 
     | 
    
         | 
| 
       19 
     | 
    
         
            -
                def initialize(username, password, wsdl_path, organization_id = nil)
         
     | 
| 
      
 14 
     | 
    
         
            +
                def initialize(username, password, wsdl_path, api_dir, organization_id = nil)
         
     | 
| 
       20 
15 
     | 
    
         
             
                  @wrapper = SoapWrapper.new("SalesforceAPI", "Soap", wsdl_path, api_dir)
         
     | 
| 
       21 
16 
     | 
    
         
             
                  @username, @password, @organization_id = URI.unescape(username), password, organization_id
         
     | 
| 
       22 
17 
     | 
    
         
             
                  login
         
     | 
| 
         @@ -27,14 +22,17 @@ module DataMapperSalesforce 
     | 
|
| 
       27 
22 
     | 
    
         
             
                  @wrapper.wsdl_path
         
     | 
| 
       28 
23 
     | 
    
         
             
                end
         
     | 
| 
       29 
24 
     | 
    
         | 
| 
      
 25 
     | 
    
         
            +
                def api_dir
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @wrapper.api_dir
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
       30 
29 
     | 
    
         
             
                def organization_id
         
     | 
| 
       31 
30 
     | 
    
         
             
                  @user_details && @user_details.organizationId
         
     | 
| 
       32 
31 
     | 
    
         
             
                end
         
     | 
| 
       33 
32 
     | 
    
         | 
| 
       34 
33 
     | 
    
         
             
                def make_object(klass_name, values)
         
     | 
| 
       35 
     | 
    
         
            -
                   
     | 
| 
       36 
     | 
    
         
            -
                   
     | 
| 
       37 
     | 
    
         
            -
                  values.each do |property,value|
         
     | 
| 
      
 34 
     | 
    
         
            +
                  obj = SalesforceAPI.const_get(klass_name).new
         
     | 
| 
      
 35 
     | 
    
         
            +
                  values.each do |property, value|
         
     | 
| 
       38 
36 
     | 
    
         
             
                    field = field_name_for(klass_name, property)
         
     | 
| 
       39 
37 
     | 
    
         
             
                    if value.nil? or value == ""
         
     | 
| 
       40 
38 
     | 
    
         
             
                      obj.fieldsToNull.push(field)
         
     | 
| 
         @@ -81,9 +79,6 @@ module DataMapperSalesforce 
     | 
|
| 
       81 
79 
     | 
    
         
             
                end
         
     | 
| 
       82 
80 
     | 
    
         | 
| 
       83 
81 
     | 
    
         
             
                private
         
     | 
| 
       84 
     | 
    
         
            -
                def api_dir
         
     | 
| 
       85 
     | 
    
         
            -
                  ENV["SALESFORCE_DIR"] || "#{ENV["HOME"]}/.salesforce"
         
     | 
| 
       86 
     | 
    
         
            -
                end
         
     | 
| 
       87 
82 
     | 
    
         | 
| 
       88 
83 
     | 
    
         
             
                def driver
         
     | 
| 
       89 
84 
     | 
    
         
             
                  @wrapper.driver
         
     | 
| 
         @@ -98,7 +93,7 @@ module DataMapperSalesforce 
     | 
|
| 
       98 
93 
     | 
    
         
             
                  begin
         
     | 
| 
       99 
94 
     | 
    
         
             
                    result = driver.login(:username => @username, :password => @password).result
         
     | 
| 
       100 
95 
     | 
    
         
             
                  rescue SOAP::FaultError => error
         
     | 
| 
       101 
     | 
    
         
            -
                    if error.faultcode.to_obj == "sf:INVALID_LOGIN"
         
     | 
| 
      
 96 
     | 
    
         
            +
                    if error.faultcode.to_obj == "sf:INVALID_LOGIN" || error.faultcode.to_obj == "INVALID_LOGIN"
         
     | 
| 
       102 
97 
     | 
    
         
             
                      raise LoginFailed, "Could not login to Salesforce; #{error.faultstring.text}"
         
     | 
| 
       103 
98 
     | 
    
         
             
                    else
         
     | 
| 
       104 
99 
     | 
    
         
             
                      raise
         
     | 
| 
         @@ -141,5 +136,3 @@ module DataMapperSalesforce 
     | 
|
| 
       141 
136 
     | 
    
         
             
                end
         
     | 
| 
       142 
137 
     | 
    
         
             
              end
         
     | 
| 
       143 
138 
     | 
    
         
             
            end
         
     | 
| 
       144 
     | 
    
         
            -
             
     | 
| 
       145 
     | 
    
         
            -
            require 'dm-salesforce/connection/errors'
         
     | 
| 
         @@ -1,4 +1,4 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module  
     | 
| 
      
 1 
     | 
    
         
            +
            module DataMapper::Salesforce
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Connection
         
     | 
| 
       3 
3 
     | 
    
         
             
                class Error             < StandardError; end
         
     | 
| 
       4 
4 
     | 
    
         
             
                class FieldNotFound     < Error; end
         
     | 
| 
         @@ -35,6 +35,12 @@ module DataMapperSalesforce 
     | 
|
| 
       35 
35 
     | 
    
         
             
                  def message_for_record(record)
         
     | 
| 
       36 
36 
     | 
    
         
             
                    record.errors.map {|e| "#{e.statusCode}: #{e.message}"}.join(", ")
         
     | 
| 
       37 
37 
     | 
    
         
             
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  def server_unavailable?
         
     | 
| 
      
 40 
     | 
    
         
            +
                    failed_records.any? do |record|
         
     | 
| 
      
 41 
     | 
    
         
            +
                      record.errors.any? {|e| e.statusCode == "SERVER_UNAVAILABLE"}
         
     | 
| 
      
 42 
     | 
    
         
            +
                    end
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
       38 
44 
     | 
    
         
             
                end
         
     | 
| 
       39 
45 
     | 
    
         
             
                class CreateError    < SOAPError; end
         
     | 
| 
       40 
46 
     | 
    
         
             
                class QueryError     < SOAPError; end
         
     | 
| 
         @@ -1,15 +1,14 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            module DataMapperSalesforce
         
     | 
| 
      
 1 
     | 
    
         
            +
            module DataMapper::Salesforce
         
     | 
| 
       4 
2 
     | 
    
         
             
              class SoapWrapper
         
     | 
| 
       5 
3 
     | 
    
         
             
                class ClassesFailedToGenerate < StandardError; end
         
     | 
| 
       6 
4 
     | 
    
         | 
| 
      
 5 
     | 
    
         
            +
                attr_reader :module_name, :driver_name, :wsdl_path, :api_dir
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
       7 
7 
     | 
    
         
             
                def initialize(module_name, driver_name, wsdl_path, api_dir)
         
     | 
| 
       8 
8 
     | 
    
         
             
                  @module_name, @driver_name, @wsdl_path, @api_dir = module_name, driver_name, File.expand_path(wsdl_path), File.expand_path(api_dir)
         
     | 
| 
       9 
9 
     | 
    
         
             
                  generate_soap_classes
         
     | 
| 
       10 
10 
     | 
    
         
             
                  driver
         
     | 
| 
       11 
11 
     | 
    
         
             
                end
         
     | 
| 
       12 
     | 
    
         
            -
                attr_reader :module_name, :driver_name, :wsdl_path, :api_dir
         
     | 
| 
       13 
12 
     | 
    
         | 
| 
       14 
13 
     | 
    
         
             
                def driver
         
     | 
| 
       15 
14 
     | 
    
         
             
                  @driver ||= Object.const_get(module_name).const_get(driver_name).new
         
     | 
| 
         @@ -24,31 +23,37 @@ module DataMapperSalesforce 
     | 
|
| 
       24 
23 
     | 
    
         
             
                    FileUtils.mkdir_p wsdl_api_dir
         
     | 
| 
       25 
24 
     | 
    
         
             
                  end
         
     | 
| 
       26 
25 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
                  unless files_exist?
         
     | 
| 
       28 
     | 
    
         
            -
                    soap4r = Gem.loaded_specs['soap4r']
         
     | 
| 
       29 
     | 
    
         
            -
                    wsdl2ruby = File.expand_path(File.join(soap4r.full_gem_path, soap4r.bindir, "wsdl2ruby.rb"))
         
     | 
| 
       30 
     | 
    
         
            -
                    Dir.chdir(wsdl_api_dir) do
         
     | 
| 
       31 
     | 
    
         
            -
                      old_args = ARGV.dup
         
     | 
| 
       32 
     | 
    
         
            -
                      ARGV.replace %W(--wsdl #{wsdl_path} --module_path #{module_name} --classdef #{module_name} --type client)
         
     | 
| 
       33 
     | 
    
         
            -
                      load wsdl2ruby
         
     | 
| 
       34 
     | 
    
         
            -
                      ARGV.replace old_args
         
     | 
| 
       35 
     | 
    
         
            -
                      (Dir["*.rb"] - files).each do |filename|
         
     | 
| 
       36 
     | 
    
         
            -
                        FileUtils.rm(filename)
         
     | 
| 
       37 
     | 
    
         
            -
                      end
         
     | 
| 
       38 
     | 
    
         
            -
                    end
         
     | 
| 
       39 
     | 
    
         
            -
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
                  generate_files unless files_exist?
         
     | 
| 
       40 
27 
     | 
    
         | 
| 
       41 
28 
     | 
    
         
             
                  $:.push wsdl_api_dir
         
     | 
| 
       42 
29 
     | 
    
         
             
                  require "#{module_name}Driver"
         
     | 
| 
       43 
30 
     | 
    
         
             
                  $:.delete wsdl_api_dir
         
     | 
| 
       44 
31 
     | 
    
         
             
                end
         
     | 
| 
       45 
32 
     | 
    
         | 
| 
       46 
     | 
    
         
            -
                 
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
      
 33 
     | 
    
         
            +
                # Good candidate for shipping out into a Rakefile.
         
     | 
| 
      
 34 
     | 
    
         
            +
                def generate_files
         
     | 
| 
      
 35 
     | 
    
         
            +
                  require 'wsdl/soap/wsdl2ruby'
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  wsdl2ruby          = WSDL::SOAP::WSDL2Ruby.new
         
     | 
| 
      
 38 
     | 
    
         
            +
                  wsdl2ruby.logger   = $LOG if $LOG
         
     | 
| 
      
 39 
     | 
    
         
            +
                  wsdl2ruby.location = wsdl_path
         
     | 
| 
      
 40 
     | 
    
         
            +
                  wsdl2ruby.basedir  = wsdl_api_dir
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  wsdl2ruby.opt.merge!({
         
     | 
| 
      
 43 
     | 
    
         
            +
                    'classdef'         => module_name,
         
     | 
| 
      
 44 
     | 
    
         
            +
                    'module_path'      => module_name,
         
     | 
| 
      
 45 
     | 
    
         
            +
                    'mapping_registry' => nil,
         
     | 
| 
      
 46 
     | 
    
         
            +
                    'driver'           => nil,
         
     | 
| 
      
 47 
     | 
    
         
            +
                    'client_skelton'   => nil,
         
     | 
| 
      
 48 
     | 
    
         
            +
                  })
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                  wsdl2ruby.run
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  raise ClassesFailedToGenerate unless files_exist?
         
     | 
| 
       48 
53 
     | 
    
         
             
                end
         
     | 
| 
       49 
54 
     | 
    
         | 
| 
       50 
55 
     | 
    
         
             
                def files_exist?
         
     | 
| 
       51 
     | 
    
         
            -
                   
     | 
| 
      
 56 
     | 
    
         
            +
                  ["#{module_name}.rb", "#{module_name}MappingRegistry.rb", "#{module_name}Driver.rb"].all? do |name|
         
     | 
| 
       52 
57 
     | 
    
         
             
                    File.exist?("#{wsdl_api_dir}/#{name}")
         
     | 
| 
       53 
58 
     | 
    
         
             
                  end
         
     | 
| 
       54 
59 
     | 
    
         
             
                end
         
     | 
    
        data/lib/dm-salesforce/sql.rb
    CHANGED
    
    | 
         @@ -1,59 +1,87 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module  
     | 
| 
      
 1 
     | 
    
         
            +
            module DataMapper::Salesforce
         
     | 
| 
       2 
2 
     | 
    
         
             
              module SQL
         
     | 
| 
       3 
     | 
    
         
            -
                 
     | 
| 
       4 
     | 
    
         
            -
                   
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
                      else raise "CAN HAS CRASH?"
         
     | 
| 
       16 
     | 
    
         
            -
                    end
         
     | 
| 
       17 
     | 
    
         
            -
                    case prop
         
     | 
| 
       18 
     | 
    
         
            -
                    when DataMapper::Property
         
     | 
| 
       19 
     | 
    
         
            -
                      "#{prop.field} #{operator}"
         
     | 
| 
       20 
     | 
    
         
            -
                    when DataMapper::Query::Path
         
     | 
| 
       21 
     | 
    
         
            -
                      rels = prop.relationships
         
     | 
| 
       22 
     | 
    
         
            -
                      names = rels.map {|r| storage_name(r, repository) }.join(".")
         
     | 
| 
       23 
     | 
    
         
            -
                      "#{names}.#{prop.field} #{operator}"
         
     | 
| 
       24 
     | 
    
         
            -
                    end
         
     | 
| 
       25 
     | 
    
         
            -
                  end
         
     | 
| 
      
 3 
     | 
    
         
            +
                def from_condition(condition, repository)
         
     | 
| 
      
 4 
     | 
    
         
            +
                  slug = condition.class.slug
         
     | 
| 
      
 5 
     | 
    
         
            +
                  condition = case condition
         
     | 
| 
      
 6 
     | 
    
         
            +
                              when DataMapper::Query::Conditions::AbstractOperation then condition.operands.first
         
     | 
| 
      
 7 
     | 
    
         
            +
                              when DataMapper::Query::Conditions::AbstractComparison
         
     | 
| 
      
 8 
     | 
    
         
            +
                                if condition.subject.kind_of?(DataMapper::Associations::Relationship)
         
     | 
| 
      
 9 
     | 
    
         
            +
                                  foreign_key_conditions(condition)
         
     | 
| 
      
 10 
     | 
    
         
            +
                                else
         
     | 
| 
      
 11 
     | 
    
         
            +
                                  condition
         
     | 
| 
      
 12 
     | 
    
         
            +
                                end
         
     | 
| 
      
 13 
     | 
    
         
            +
                              else raise("Unkown condition type #{condition.class}: #{condition.inspect}")
         
     | 
| 
      
 14 
     | 
    
         
            +
                              end
         
     | 
| 
       26 
15 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
                   
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
      
 16 
     | 
    
         
            +
                  value = condition.value
         
     | 
| 
      
 17 
     | 
    
         
            +
                  prop = condition.subject
         
     | 
| 
      
 18 
     | 
    
         
            +
                  operator = case slug
         
     | 
| 
      
 19 
     | 
    
         
            +
                             when String then operator
         
     | 
| 
      
 20 
     | 
    
         
            +
                             when :eql, :in then equality_operator(value)
         
     | 
| 
      
 21 
     | 
    
         
            +
                             when :not      then inequality_operator(value)
         
     | 
| 
      
 22 
     | 
    
         
            +
                             when :like     then "LIKE #{quote_value(value)}"
         
     | 
| 
      
 23 
     | 
    
         
            +
                             when :gt       then "> #{quote_value(value)}"
         
     | 
| 
      
 24 
     | 
    
         
            +
                             when :gte      then ">= #{quote_value(value)}"
         
     | 
| 
      
 25 
     | 
    
         
            +
                             when :lt       then "< #{quote_value(value)}"
         
     | 
| 
      
 26 
     | 
    
         
            +
                             when :lte      then "<= #{quote_value(value)}"
         
     | 
| 
      
 27 
     | 
    
         
            +
                             else raise "CAN HAS CRASH?"
         
     | 
| 
      
 28 
     | 
    
         
            +
                             end
         
     | 
| 
      
 29 
     | 
    
         
            +
                  case prop
         
     | 
| 
      
 30 
     | 
    
         
            +
                  when DataMapper::Property
         
     | 
| 
      
 31 
     | 
    
         
            +
                    "#{prop.field} #{operator}"
         
     | 
| 
      
 32 
     | 
    
         
            +
                  when DataMapper::Query::Path
         
     | 
| 
      
 33 
     | 
    
         
            +
                    rels = prop.relationships
         
     | 
| 
      
 34 
     | 
    
         
            +
                    names = rels.map {|r| storage_name(r, repository) }.join(".")
         
     | 
| 
      
 35 
     | 
    
         
            +
                    "#{names}.#{prop.field} #{operator}"
         
     | 
| 
       29 
36 
     | 
    
         
             
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
       30 
38 
     | 
    
         | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
      
 39 
     | 
    
         
            +
                def foreign_key_conditions(condition)
         
     | 
| 
      
 40 
     | 
    
         
            +
                  subject = case condition.subject
         
     | 
| 
      
 41 
     | 
    
         
            +
                    when DataMapper::Associations::ManyToOne::Relationship
         
     | 
| 
      
 42 
     | 
    
         
            +
                      condition.subject.child_key.first
         
     | 
| 
      
 43 
     | 
    
         
            +
                    else
         
     | 
| 
      
 44 
     | 
    
         
            +
                      condition.subject.parent_key.first
         
     | 
| 
      
 45 
     | 
    
         
            +
                    end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  case condition.value
         
     | 
| 
      
 48 
     | 
    
         
            +
                  when Array, DataMapper::Collection
         
     | 
| 
      
 49 
     | 
    
         
            +
                    value = condition.send(:expected).flatten
         
     | 
| 
      
 50 
     | 
    
         
            +
                    DataMapper::Query::Conditions::InclusionComparison.new(subject, value)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  else
         
     | 
| 
      
 52 
     | 
    
         
            +
                    value = condition.send(:expected)
         
     | 
| 
      
 53 
     | 
    
         
            +
                    DataMapper::Query::Conditions::EqualToComparison.new(subject, value)
         
     | 
| 
       33 
54 
     | 
    
         
             
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
       34 
56 
     | 
    
         | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
                   
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
      
 57 
     | 
    
         
            +
                def storage_name(rel, repository)
         
     | 
| 
      
 58 
     | 
    
         
            +
                  rel.parent_model.storage_name(repository.name)
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                def order(direction)
         
     | 
| 
      
 62 
     | 
    
         
            +
                  "#{direction.target.field} #{direction.operator.to_s.upcase}"
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                def equality_operator(value)
         
     | 
| 
      
 66 
     | 
    
         
            +
                  case value
         
     | 
| 
      
 67 
     | 
    
         
            +
                  when Array then "IN #{quote_value(value)}"
         
     | 
| 
      
 68 
     | 
    
         
            +
                  else "= #{quote_value(value)}"
         
     | 
| 
       41 
69 
     | 
    
         
             
                  end
         
     | 
| 
      
 70 
     | 
    
         
            +
                end
         
     | 
| 
       42 
71 
     | 
    
         | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
                    end
         
     | 
| 
      
 72 
     | 
    
         
            +
                def inequality_operator(value)
         
     | 
| 
      
 73 
     | 
    
         
            +
                  case value
         
     | 
| 
      
 74 
     | 
    
         
            +
                  when Array then "NOT IN #{quote_value(value)}"
         
     | 
| 
      
 75 
     | 
    
         
            +
                  else "!= #{quote_value(value)}"
         
     | 
| 
       48 
76 
     | 
    
         
             
                  end
         
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
       49 
78 
     | 
    
         | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
     | 
    
         
            -
                    end
         
     | 
| 
      
 79 
     | 
    
         
            +
                def quote_value(value)
         
     | 
| 
      
 80 
     | 
    
         
            +
                  case value
         
     | 
| 
      
 81 
     | 
    
         
            +
                  when Array then "(#{value.map {|v| quote_value(v)}.join(", ")})"
         
     | 
| 
      
 82 
     | 
    
         
            +
                  when NilClass then "NULL"
         
     | 
| 
      
 83 
     | 
    
         
            +
                  when String then "'#{value.gsub(/'/, "\\'").gsub(/\\/, %{\\\\})}'"
         
     | 
| 
      
 84 
     | 
    
         
            +
                  else "#{value}"
         
     | 
| 
       57 
85 
     | 
    
         
             
                  end
         
     | 
| 
       58 
86 
     | 
    
         
             
                end
         
     | 
| 
       59 
87 
     | 
    
         
             
              end
         
     | 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module DataMapper::Salesforce
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Type < ::DataMapper::Type
         
     | 
| 
      
 3 
     | 
    
         
            +
              end
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              module Types
         
     | 
| 
      
 6 
     | 
    
         
            +
              end
         
     | 
| 
      
 7 
     | 
    
         
            +
            end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            dir = File.expand_path(File.dirname(__FILE__) / :types)
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            require dir / :serial
         
     | 
| 
      
 12 
     | 
    
         
            +
            require dir / :boolean
         
     | 
| 
      
 13 
     | 
    
         
            +
            require dir / :integer
         
     | 
| 
      
 14 
     | 
    
         
            +
            require dir / :float
         
     | 
| 
         @@ -0,0 +1,23 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module DataMapper::Salesforce
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Types
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Boolean < Type
         
     | 
| 
      
 4 
     | 
    
         
            +
                  primitive String
         
     | 
| 
      
 5 
     | 
    
         
            +
                  default false
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  def self.dump(value, property)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    case value
         
     | 
| 
      
 9 
     | 
    
         
            +
                    when nil, false then '0'
         
     | 
| 
      
 10 
     | 
    
         
            +
                    else value
         
     | 
| 
      
 11 
     | 
    
         
            +
                    end
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def self.load(value, property)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    case value
         
     | 
| 
      
 16 
     | 
    
         
            +
                    when TrueClass    then value
         
     | 
| 
      
 17 
     | 
    
         
            +
                    when '1', 'true'  then true
         
     | 
| 
      
 18 
     | 
    
         
            +
                    else false
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,3 +1,3 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module  
     | 
| 
       2 
     | 
    
         
            -
              VERSION = "0. 
     | 
| 
      
 1 
     | 
    
         
            +
            module DataMapper::Salesforce
         
     | 
| 
      
 2 
     | 
    
         
            +
              VERSION = "0.10.1"
         
     | 
| 
       3 
3 
     | 
    
         
             
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,16 +1,17 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification 
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: dm-salesforce
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version 
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.10.1
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors: 
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Yehuda Katz
         
     | 
| 
       8 
8 
     | 
    
         
             
            - Tim Carey-Smith
         
     | 
| 
      
 9 
     | 
    
         
            +
            - Corey Donohoe
         
     | 
| 
       9 
10 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       10 
11 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       11 
12 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       12 
13 
     | 
    
         | 
| 
       13 
     | 
    
         
            -
            date: 2009- 
     | 
| 
      
 14 
     | 
    
         
            +
            date: 2009-12-17 00:00:00 -08:00
         
     | 
| 
       14 
15 
     | 
    
         
             
            default_executable: 
         
     | 
| 
       15 
16 
     | 
    
         
             
            dependencies: 
         
     | 
| 
       16 
17 
     | 
    
         
             
            - !ruby/object:Gem::Dependency 
         
     | 
| 
         @@ -41,7 +42,7 @@ dependencies: 
     | 
|
| 
       41 
42 
     | 
    
         
             
                requirements: 
         
     | 
| 
       42 
43 
     | 
    
         
             
                - - ~>
         
     | 
| 
       43 
44 
     | 
    
         
             
                  - !ruby/object:Gem::Version 
         
     | 
| 
       44 
     | 
    
         
            -
                    version: 0. 
     | 
| 
      
 45 
     | 
    
         
            +
                    version: 0.10.1
         
     | 
| 
       45 
46 
     | 
    
         
             
                version: 
         
     | 
| 
       46 
47 
     | 
    
         
             
            - !ruby/object:Gem::Dependency 
         
     | 
| 
       47 
48 
     | 
    
         
             
              name: dm-validations
         
     | 
| 
         @@ -51,40 +52,40 @@ dependencies: 
     | 
|
| 
       51 
52 
     | 
    
         
             
                requirements: 
         
     | 
| 
       52 
53 
     | 
    
         
             
                - - ~>
         
     | 
| 
       53 
54 
     | 
    
         
             
                  - !ruby/object:Gem::Version 
         
     | 
| 
       54 
     | 
    
         
            -
                    version: 0. 
     | 
| 
      
 55 
     | 
    
         
            +
                    version: 0.10.1
         
     | 
| 
       55 
56 
     | 
    
         
             
                version: 
         
     | 
| 
       56 
57 
     | 
    
         
             
            - !ruby/object:Gem::Dependency 
         
     | 
| 
       57 
     | 
    
         
            -
              name:  
     | 
| 
      
 58 
     | 
    
         
            +
              name: dm-types
         
     | 
| 
       58 
59 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       59 
60 
     | 
    
         
             
              version_requirement: 
         
     | 
| 
       60 
61 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement 
         
     | 
| 
       61 
62 
     | 
    
         
             
                requirements: 
         
     | 
| 
       62 
63 
     | 
    
         
             
                - - ~>
         
     | 
| 
       63 
64 
     | 
    
         
             
                  - !ruby/object:Gem::Version 
         
     | 
| 
       64 
     | 
    
         
            -
                    version:  
     | 
| 
      
 65 
     | 
    
         
            +
                    version: 0.10.1
         
     | 
| 
       65 
66 
     | 
    
         
             
                version: 
         
     | 
| 
       66 
67 
     | 
    
         
             
            - !ruby/object:Gem::Dependency 
         
     | 
| 
       67 
     | 
    
         
            -
              name:  
     | 
| 
      
 68 
     | 
    
         
            +
              name: do_sqlite3
         
     | 
| 
       68 
69 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       69 
70 
     | 
    
         
             
              version_requirement: 
         
     | 
| 
       70 
71 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement 
         
     | 
| 
       71 
72 
     | 
    
         
             
                requirements: 
         
     | 
| 
       72 
73 
     | 
    
         
             
                - - ~>
         
     | 
| 
       73 
74 
     | 
    
         
             
                  - !ruby/object:Gem::Version 
         
     | 
| 
       74 
     | 
    
         
            -
                    version: 0. 
     | 
| 
      
 75 
     | 
    
         
            +
                    version: 0.10.0
         
     | 
| 
       75 
76 
     | 
    
         
             
                version: 
         
     | 
| 
       76 
77 
     | 
    
         
             
            - !ruby/object:Gem::Dependency 
         
     | 
| 
       77 
     | 
    
         
            -
              name:  
     | 
| 
      
 78 
     | 
    
         
            +
              name: soap4r
         
     | 
| 
       78 
79 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       79 
80 
     | 
    
         
             
              version_requirement: 
         
     | 
| 
       80 
81 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement 
         
     | 
| 
       81 
82 
     | 
    
         
             
                requirements: 
         
     | 
| 
       82 
83 
     | 
    
         
             
                - - ~>
         
     | 
| 
       83 
84 
     | 
    
         
             
                  - !ruby/object:Gem::Version 
         
     | 
| 
       84 
     | 
    
         
            -
                    version:  
     | 
| 
      
 85 
     | 
    
         
            +
                    version: 1.5.8
         
     | 
| 
       85 
86 
     | 
    
         
             
                version: 
         
     | 
| 
       86 
87 
     | 
    
         
             
            description: A DataMapper adapter to the Salesforce API
         
     | 
| 
       87 
     | 
    
         
            -
            email:  
     | 
| 
      
 88 
     | 
    
         
            +
            email: ninja@engineyard.com
         
     | 
| 
       88 
89 
     | 
    
         
             
            executables: []
         
     | 
| 
       89 
90 
     | 
    
         | 
| 
       90 
91 
     | 
    
         
             
            extensions: []
         
     | 
| 
         @@ -99,13 +100,18 @@ files: 
     | 
|
| 
       99 
100 
     | 
    
         
             
            - lib/dm-salesforce/adapter.rb
         
     | 
| 
       100 
101 
     | 
    
         
             
            - lib/dm-salesforce/connection/errors.rb
         
     | 
| 
       101 
102 
     | 
    
         
             
            - lib/dm-salesforce/connection.rb
         
     | 
| 
       102 
     | 
    
         
            -
            - lib/dm-salesforce/ 
     | 
| 
      
 103 
     | 
    
         
            +
            - lib/dm-salesforce/resource.rb
         
     | 
| 
       103 
104 
     | 
    
         
             
            - lib/dm-salesforce/soap_wrapper.rb
         
     | 
| 
       104 
105 
     | 
    
         
             
            - lib/dm-salesforce/sql.rb
         
     | 
| 
      
 106 
     | 
    
         
            +
            - lib/dm-salesforce/types/boolean.rb
         
     | 
| 
      
 107 
     | 
    
         
            +
            - lib/dm-salesforce/types/float.rb
         
     | 
| 
      
 108 
     | 
    
         
            +
            - lib/dm-salesforce/types/integer.rb
         
     | 
| 
      
 109 
     | 
    
         
            +
            - lib/dm-salesforce/types/serial.rb
         
     | 
| 
      
 110 
     | 
    
         
            +
            - lib/dm-salesforce/types.rb
         
     | 
| 
       105 
111 
     | 
    
         
             
            - lib/dm-salesforce/version.rb
         
     | 
| 
       106 
112 
     | 
    
         
             
            - lib/dm-salesforce.rb
         
     | 
| 
       107 
113 
     | 
    
         
             
            has_rdoc: true
         
     | 
| 
       108 
     | 
    
         
            -
            homepage: http:// 
     | 
| 
      
 114 
     | 
    
         
            +
            homepage: http://github.com/halorgium/dm-salesforce
         
     | 
| 
       109 
115 
     | 
    
         
             
            licenses: []
         
     | 
| 
       110 
116 
     | 
    
         | 
| 
       111 
117 
     | 
    
         
             
            post_install_message: 
         
     | 
| 
         @@ -1,45 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module DataMapperSalesforce
         
     | 
| 
       2 
     | 
    
         
            -
              module SalesforceExtensions
         
     | 
| 
       3 
     | 
    
         
            -
                def self.included(mod)
         
     | 
| 
       4 
     | 
    
         
            -
                  mod.extend(ClassMethods)
         
     | 
| 
       5 
     | 
    
         
            -
                end
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
                module ClassMethods
         
     | 
| 
       8 
     | 
    
         
            -
                  def properties_with_salesforce_validation
         
     | 
| 
       9 
     | 
    
         
            -
                    @properties_with_salesforce_validation ||= []
         
     | 
| 
       10 
     | 
    
         
            -
                  end
         
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
                  def add_salesforce_validation_for(property)
         
     | 
| 
       13 
     | 
    
         
            -
                    unless properties_with_salesforce_validation.include?(property)
         
     | 
| 
       14 
     | 
    
         
            -
                      validates_with_block property.name do
         
     | 
| 
       15 
     | 
    
         
            -
                        if message = salesforce_errors[property]
         
     | 
| 
       16 
     | 
    
         
            -
                          [false, message]
         
     | 
| 
       17 
     | 
    
         
            -
                        else
         
     | 
| 
       18 
     | 
    
         
            -
                          true
         
     | 
| 
       19 
     | 
    
         
            -
                        end
         
     | 
| 
       20 
     | 
    
         
            -
                      end
         
     | 
| 
       21 
     | 
    
         
            -
                    end
         
     | 
| 
       22 
     | 
    
         
            -
                    properties_with_salesforce_validation << property
         
     | 
| 
       23 
     | 
    
         
            -
                  end
         
     | 
| 
       24 
     | 
    
         
            -
                end
         
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
                def add_salesforce_error_for(field, message)
         
     | 
| 
       27 
     | 
    
         
            -
                  if property = property_for_salesforce_field(field)
         
     | 
| 
       28 
     | 
    
         
            -
                    self.class.add_salesforce_validation_for(property)
         
     | 
| 
       29 
     | 
    
         
            -
                    salesforce_errors[property] = message
         
     | 
| 
       30 
     | 
    
         
            -
                  else
         
     | 
| 
       31 
     | 
    
         
            -
                    raise "Field not found"
         
     | 
| 
       32 
     | 
    
         
            -
                  end
         
     | 
| 
       33 
     | 
    
         
            -
                end
         
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
                def property_for_salesforce_field(name)
         
     | 
| 
       36 
     | 
    
         
            -
                  self.class.properties.find do |p|
         
     | 
| 
       37 
     | 
    
         
            -
                    p.field.downcase == name.downcase
         
     | 
| 
       38 
     | 
    
         
            -
                  end
         
     | 
| 
       39 
     | 
    
         
            -
                end
         
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
                def salesforce_errors
         
     | 
| 
       42 
     | 
    
         
            -
                  @salesforce_errors ||= {}
         
     | 
| 
       43 
     | 
    
         
            -
                end
         
     | 
| 
       44 
     | 
    
         
            -
              end
         
     | 
| 
       45 
     | 
    
         
            -
            end
         
     |