Class: Salesforce::Base

Inherits:
Object
  • Object
show all
Includes:
Salesforce::Bulk::Operations
Defined in:
lib/salesforce/base.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attrs = {}) ⇒ Base

Returns a new instance of Base.



8
9
10
11
# File 'lib/salesforce/base.rb', line 8

def initialize(attrs = {})
  self.class.columns
  assign_attributes(attrs)
end

Class Method Details

.allObject



101
# File 'lib/salesforce/base.rb', line 101

def self.all; find_all; end

.clear_cached_columns!Object



133
134
135
# File 'lib/salesforce/base.rb', line 133

def self.clear_cached_columns!
  self.cached_columns = nil
end

.columnsObject



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/salesforce/base.rb', line 25

def self.columns
  self.cached_columns ||= begin
    cols = Columns.new(table_name)
    cols.all.each do |col| 
      attr_reader col.name
      
      define_method "#{col.original_name}=" do |value|
        instance_variable_set(:"@#{col.name}", Column.typecast(col.type, value))
      end
    end

    cols.editable.each do |col|
      define_method "#{col.name}=" do |value|
        if (new_record? && col.createable?) || (!new_record? && col.updateable?)
          instance_variable_set(:"@#{col.name}", Column.typecast(col.type, value))
        else
          raise ArgumentError.new("#{self.class.table_name}##{col.name} is not editable.")
        end
      end
    end
    cols
  end
end

.connection(method, *args) ⇒ Object



216
217
218
219
# File 'lib/salesforce/base.rb', line 216

def self.connection(method, *args)
  columns
  Connection.send method, *args
end

.find(*args) ⇒ Object

Finders



80
81
82
83
84
85
86
# File 'lib/salesforce/base.rb', line 80

def self.find(*args)
  if args.first == :all
    find_all(*args)
  else 
    find_by_id(*args)
  end
end

.find_all(*args) ⇒ Object



94
95
96
97
98
99
# File 'lib/salesforce/base.rb', line 94

def self.find_all(*args)
  with_invalid_column_handling do 
    options = args.extract_options!
    connection(:soql, query_string(options)).map { |result| to_object(result) }
  end
end

.find_by_column(column, value) ⇒ Object



103
104
105
# File 'lib/salesforce/base.rb', line 103

def self.find_by_column(column, value)
  connection(:soql, "#{select_clause} FROM #{table_name} WHERE #{column.original_name}=#{Column.to_soql_value(value)}").map { |result| to_object(result) }
end

.find_by_id(object_id) ⇒ Object



88
89
90
91
92
# File 'lib/salesforce/base.rb', line 88

def self.find_by_id(object_id)
  with_invalid_column_handling do
    to_object(connection(:find_object_by_id, table_name, object_id, columns.soql_selector))
  end
end

.method_missing(method_name, *args) ⇒ Object



221
222
223
224
225
226
227
# File 'lib/salesforce/base.rb', line 221

def self.method_missing(method_name, *args)
  if method_name.to_s =~ /^find_by_([_a-zA-Z]\w*)$/ && column = columns.find { |column| column.name.to_s == $1 }
    self.find_by_column(column, *args)
  else
    super
  end
end

.query_string(options) ⇒ Object



182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/salesforce/base.rb', line 182

def self.query_string(options)
  str = [].tap do |string|
    string << "SELECT #{selector(options[:select])} FROM #{table_name}"
    string << "WHERE #{soql_clause(options[:conditions])}" if options[:conditions]
    string << "LIMIT #{soql_clause(options[:limit])}" if options[:limit]
    string << "WITH #{soql_clause(options[:with])}" if options[:with]
    string << "GROUP BY #{soql_clause(options[:group_by])}" if options[:group_by]
    string << "HAVING #{soql_clause(options[:having])}" if options[:having]
    string << "ORDER BY #{soql_clause(options[:order])}" if options[:order]
  end.join(' ')
  sanitized_soql(str, options)
end

.sanitized_soql(string, values = nil) ⇒ Object



200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/salesforce/base.rb', line 200

def self.sanitized_soql(string, values = nil)
  values ||= {}
  # Substitute columns
  columns.each do |col|
    string.gsub!(":#{col.name}", col.original_name)
  end
  
  # Substitute Values
  values.each do |key, value|
    next if [ :select, :conditions, :limit, :with, :group_by, :having, :order ].include?(key.to_sym)
    string.gsub!(":#{key}", Column.to_soql_value(value))
  end
  string
end

.select_clause(select = nil) ⇒ Object



172
173
174
# File 'lib/salesforce/base.rb', line 172

def self.select_clause(select = nil)
  "SELECT #{selector(select)}"
end

.select_values(options) ⇒ Object



107
108
109
110
111
112
113
114
115
116
# File 'lib/salesforce/base.rb', line 107

def self.select_values(options)
  connection(:soql, query_string(options)).map do |result|
    {}.tap do |hash|
      Array.wrap(options[:select] || columns.names).each do |col|
        column = columns.find_by_name(col)
        hash[col] = Column.typecast(column.type, result[column.original_name])
      end
    end
  end
end

.selector(select = nil) ⇒ Object



176
177
178
179
180
# File 'lib/salesforce/base.rb', line 176

def self.selector(select = nil)
  select ||= :all
  return columns.soql_selector if select == :all
  Array.wrap(select).map { |var| columns.find_by_name(var).original_name }.join(',')
end

.soql_clause(sub_clause) ⇒ Object



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

def self.soql_clause(sub_clause)
  return sub_clause if sub_clause.is_a?(String)
  Array.wrap(sub_clause).map { |col| columns.find_by_name(col).original_name }.join(',')
end

.table_nameObject



20
21
22
23
# File 'lib/salesforce/base.rb', line 20

def self.table_name
  return self.custom_table_name if self.custom_table_name
  name.demodulize + (self.custom_object ? "__c" : '')
end

.to_object(result) ⇒ Object



229
230
231
232
233
234
235
236
237
238
# File 'lib/salesforce/base.rb', line 229

def self.to_object(result)
  result.delete("attributes")
  new.tap do |record|
    result.each do |k, v|
      if record.respond_to?(:"#{k}=")
        record.send("#{k}=", v) 
      end
    end
  end
end

.with_invalid_column_handlingObject



118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/salesforce/base.rb', line 118

def self.with_invalid_column_handling
  _count = 0
  begin
    yield
  rescue InvalidRequest => e
    if e.error_code == 'INVALID_FIELD' && _count == 0
      clear_cached_columns!
      _count += 1
      retry
    else
      raise e
    end
  end
end

Instance Method Details

#assign_attributes(attrs) ⇒ Object



13
14
15
16
17
18
# File 'lib/salesforce/base.rb', line 13

def assign_attributes(attrs)
  attrs.delete("attributes")
  attrs.each do |k,v|
    send("#{k}=", v)
  end
end

#attributesObject

Attributes



51
52
53
54
55
56
# File 'lib/salesforce/base.rb', line 51

def attributes
  self.class.columns.names.inject(ActiveSupport::HashWithIndifferentAccess.new) do |hash,name|
    hash[name] = self.send(name)
    hash
  end
end

#attributes=(attrs) ⇒ Object



74
75
76
# File 'lib/salesforce/base.rb', line 74

def attributes=(attrs)
  assign_attributes(attrs)
end

#createObject



142
143
144
145
# File 'lib/salesforce/base.rb', line 142

def create
  raise_if_destroyed
  self.Id = self.class.connection(:create, self.class.table_name, createable_attributes)
end

#createable_attributesObject



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

def createable_attributes
  self.class.columns.createable.inject(ActiveSupport::HashWithIndifferentAccess.new) do |hash,col|
    value = self.send(col.name)
    hash[col.original_name] = value unless value.nil?
    hash
  end
end

#destroyObject



154
155
156
157
158
# File 'lib/salesforce/base.rb', line 154

def destroy
  raise_if_destroyed
  self.class.connection(:destroy, self.class.table_name, self.id) unless new_record?
  @destroyed = true
end

#destroyed?Boolean

Returns:

  • (Boolean)


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

def destroyed?
  @destroyed || false
end

#new_record?Boolean

Returns:

  • (Boolean)


168
169
170
# File 'lib/salesforce/base.rb', line 168

def new_record?
  self.id.blank?
end

#raise_if_destroyedObject

Raises:



164
165
166
# File 'lib/salesforce/base.rb', line 164

def raise_if_destroyed
  raise ObjectDestroyed.new if destroyed?
end

#save!Object



137
138
139
140
# File 'lib/salesforce/base.rb', line 137

def save!
  raise_if_destroyed
  new_record? ? create : update
end

#updateObject



147
148
149
150
151
152
# File 'lib/salesforce/base.rb', line 147

def update
  self.class.with_invalid_column_handling do 
    raise_if_destroyed
    self.class.connection(:update, self.class.table_name, self.id, updateable_attributes)
  end
end

#updateable_attributesObject



66
67
68
69
70
71
72
# File 'lib/salesforce/base.rb', line 66

def updateable_attributes
  self.class.columns.updateable.inject(ActiveSupport::HashWithIndifferentAccess.new) do |hash,col|
    value = self.send(col.name)
    hash[col.original_name] = value unless value.nil?
    hash
  end
end