Skip to content
This repository
Browse code

Properly handle reading properties that are relationships

  • Loading branch information...
commit 1c38b8653a6fbd59f5a5a23a37e5f06f85c0ef69 1 parent e72d737
Larry Diehl authored
1  lib/dm-salesforce.rb
@@ -2,7 +2,6 @@
2 2
 
3 3
 require 'dm-core'
4 4
 require 'dm-validations'
5  
-require 'dm-salesforce/sql'
6 5
 require 'dm-salesforce/extensions'
7 6
 require 'dm-salesforce/adapter'
8 7
 require 'dm-salesforce/connection'
73  lib/dm-salesforce/adapter.rb
@@ -65,7 +65,7 @@ def update(attributes, collection)
65 65
         [ make_salesforce_obj(query, attributes, key_condition) ]
66 66
       else
67 67
         read_many(query).map do |obj|
68  
-          obj = make_salesforce_obj(query, attributes, x.key)
  68
+          obj = make_salesforce_obj(query, attributes, obj.key)
69 69
         end
70 70
       end
71 71
       connection.update(arr).size
@@ -136,11 +136,11 @@ def read(query)
136 136
       repository = query.repository
137 137
       properties = query.fields
138 138
       properties_with_indexes = Hash[*properties.zip((0...properties.size).to_a).flatten]
139  
-      conditions = query.conditions.map {|c| SQL.from_condition(c, repository)}.compact.join(") AND (")
  139
+      conditions = query.conditions.map {|c| from_condition(c, repository)}.compact.join(") AND (")
140 140
 
141 141
       sql = "SELECT #{query.fields.map {|f| f.field}.join(", ")} from #{query.model.storage_name(repository.name)}"
142 142
       sql << " WHERE (#{conditions})" unless conditions.empty?
143  
-      sql << " ORDER BY #{SQL.order(query.order[0])}" unless query.order.empty?
  143
+      sql << " ORDER BY #{order(query.order[0])}" unless query.order.empty?
144 144
       sql << " LIMIT #{query.limit}" if query.limit
145 145
 
146 146
       DataMapper.logger.debug sql
@@ -191,5 +191,72 @@ def normalize_id_value(klass, property, value)
191 191
       end
192 192
       value
193 193
     end
  194
+
  195
+    def from_condition(condition, repository)
  196
+      slug = condition.class.slug
  197
+      condition = case condition
  198
+                  when DataMapper::Query::Conditions::AbstractOperation then condition.operands.first
  199
+                  when DataMapper::Query::Conditions::AbstractComparison
  200
+                    if condition.subject.kind_of?(DataMapper::Associations::Relationship)
  201
+                      foreign_key_conditions(condition)
  202
+                    else
  203
+                      condition
  204
+                    end
  205
+                  else raise("Unkown condition type #{condition.class}: #{condition.inspect}")
  206
+                  end
  207
+
  208
+      value = condition.value
  209
+      prop = condition.subject
  210
+      operator = case slug
  211
+                 when String then operator
  212
+                 when :eql, :in then equality_operator(value)
  213
+                 when :not      then inequality_operator(value)
  214
+                 when :like     then "LIKE #{quote_value(value)}"
  215
+                 when :gt       then "> #{quote_value(value)}"
  216
+                 when :gte      then ">= #{quote_value(value)}"
  217
+                 when :lt       then "< #{quote_value(value)}"
  218
+                 when :lte      then "<= #{quote_value(value)}"
  219
+                 else raise "CAN HAS CRASH?"
  220
+                 end
  221
+      case prop
  222
+      when DataMapper::Property
  223
+        "#{prop.field} #{operator}"
  224
+      when DataMapper::Query::Path
  225
+        rels = prop.relationships
  226
+        names = rels.map {|r| storage_name(r, repository) }.join(".")
  227
+        "#{names}.#{prop.field} #{operator}"
  228
+      end
  229
+    end
  230
+
  231
+    def storage_name(rel, repository)
  232
+      rel.parent_model.storage_name(repository.name)
  233
+    end
  234
+
  235
+    def order(direction)
  236
+      "#{direction.target.field} #{direction.operator.to_s.upcase}"
  237
+    end
  238
+
  239
+    def equality_operator(value)
  240
+      case value
  241
+      when Array then "IN #{quote_value(value)}"
  242
+      else "= #{quote_value(value)}"
  243
+      end
  244
+    end
  245
+
  246
+    def inequality_operator(value)
  247
+      case value
  248
+      when Array then "NOT IN #{quote_value(value)}"
  249
+      else "!= #{quote_value(value)}"
  250
+      end
  251
+    end
  252
+
  253
+    def quote_value(value)
  254
+      case value
  255
+      when Array then "(#{value.map {|v| quote_value(v)}.join(", ")})"
  256
+      when NilClass then "NULL"
  257
+      when String then "'#{value.gsub(/'/, "\\'").gsub(/\\/, %{\\\\})}'"
  258
+      else "#{value}"
  259
+      end
  260
+    end
194 261
   end
195 262
 end
68  lib/dm-salesforce/sql.rb
... ...
@@ -1,68 +0,0 @@
1  
-module DataMapperSalesforce
2  
-  module SQL
3  
-    class << self
4  
-      def from_condition(condition, repository)
5  
-        slug = condition.class.slug
6  
-        condition = case condition
7  
-          when DataMapper::Query::Conditions::AbstractOperation then condition.operands.first
8  
-          when DataMapper::Query::Conditions::AbstractComparison then condition
9  
-          else raise("Unkown condition type #{condition.class}: #{condition.inspect}")
10  
-          end
11  
-
12  
-        value = condition.value
13  
-        prop = condition.subject
14  
-        operator = case slug
15  
-          when String then operator
16  
-          when :eql, :in then equality_operator(value)
17  
-          when :not      then inequality_operator(value)
18  
-          when :like     then "LIKE #{quote_value(value)}"
19  
-          when :gt       then "> #{quote_value(value)}"
20  
-          when :gte      then ">= #{quote_value(value)}"
21  
-          when :lt       then "< #{quote_value(value)}"
22  
-          when :lte      then "<= #{quote_value(value)}"
23  
-          else raise "CAN HAS CRASH?"
24  
-        end
25  
-        case prop
26  
-        when DataMapper::Property
27  
-          "#{prop.field} #{operator}"
28  
-        when DataMapper::Query::Path
29  
-          rels = prop.relationships
30  
-          names = rels.map {|r| storage_name(r, repository) }.join(".")
31  
-          "#{names}.#{prop.field} #{operator}"
32  
-        end
33  
-      end
34  
-
35  
-      def storage_name(rel, repository)
36  
-        rel.parent_model.storage_name(repository.name)
37  
-      end
38  
-
39  
-      def order(direction)
40  
-        "#{direction.target.field} #{direction.operator.to_s.upcase}"
41  
-      end
42  
-
43  
-      private
44  
-      def equality_operator(value)
45  
-        case value
46  
-        when Array then "IN #{quote_value(value)}"
47  
-        else "= #{quote_value(value)}"
48  
-        end
49  
-      end
50  
-
51  
-      def inequality_operator(value)
52  
-        case value
53  
-        when Array then "NOT IN #{quote_value(value)}"
54  
-        else "!= #{quote_value(value)}"
55  
-        end
56  
-      end
57  
-
58  
-      def quote_value(value)
59  
-        case value
60  
-        when Array then "(#{value.map {|v| quote_value(v)}.join(", ")})"
61  
-        when NilClass then "NULL"
62  
-        when String then "'#{value.gsub(/'/, "\\'").gsub(/\\/, %{\\\\})}'"
63  
-        else "#{value}"
64  
-        end
65  
-      end
66  
-    end
67  
-  end
68  
-end
2  spec/fixtures/account.rb
@@ -11,4 +11,6 @@ def self.salesforce_id_properties
11 11
 
12 12
   property :id, String, :serial => true
13 13
   property :name, String
  14
+
  15
+  has n, :contacts
14 16
 end
4  spec/models/contact_spec.rb
@@ -96,8 +96,8 @@
96 96
   describe "when an account is specified" do
97 97
     it "correctly connects the account when its relationship object is specified" do
98 98
       a = Account.create(:name => "Puma Shoes Unlimited")
99  
-      c = Contact.create(:first_name => 'Per', :last_name => 'Son', :email => "person@company.com", :account => a)
100  
-      c.reload.account.should == a
  99
+      c = Contact.get  Contact.create(:first_name => 'Per', :last_name => 'Son', :email => "person@company.com", :account => a).id
  100
+      c.account.should == a
101 101
     end
102 102
 
103 103
     it "correctly connects the account when its foreign key is specified" do

0 notes on commit 1c38b86

Please sign in to comment.
Something went wrong with that request. Please try again.