Class: Databasedotcom::Sobject::Sobject

Inherits:
Object
  • Object
show all
Extended by:
ActiveModel::Naming
Defined in:
lib/databasedotcom/sobject/sobject.rb

Overview

Parent class of dynamically created sobject types. Interacts with Force.com through a Client object that is passed in during materialization.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attrs = {}) ⇒ Sobject

Returns a new Sobject. The default values for all attributes are set based on its description.



9
10
11
12
13
14
15
# File 'lib/databasedotcom/sobject/sobject.rb', line 9

def initialize(attrs = {})
  super
  self.class.description["fields"].each do |field|
    self.send("#{field["name"]}=", field["defaultValueFormula"])
  end
  self.attributes=(attrs)
end

Class Method Details

.allObject

Returns all records of type self as instances.

client.materialize("Car")
Car.all    #=>   [#<Car @Id="1", ...>, #<Car @Id="2", ...>, #<Car @Id="3", ...>, ...]


177
178
179
# File 'lib/databasedotcom/sobject/sobject.rb', line 177

def self.all
  self.client.query("SELECT #{self.field_list} FROM #{self.sobject_name}")
end

.attributesObject

Returns an Array of attribute names that this Sobject has.

client.materialize("Car")
Car.attributes               #=> ["Id", "Name", "Color", "Year"]


122
123
124
# File 'lib/databasedotcom/sobject/sobject.rb', line 122

def self.attributes
  self.description["fields"].collect { |f| f["name"] }
end

.coerce_params(params) ⇒ Object

Coerce values submitted from a Rails form to the values expected by the database returns a new hash with updated values



264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/databasedotcom/sobject/sobject.rb', line 264

def self.coerce_params(params)
  params.each do |attr, value|
    case self.field_type(attr)
      when "boolean"
        params[attr] = value.is_a?(String) ? value.to_i != 0 : value
      when "currency", "percent", "double"
        params[attr] = value.to_f
      when "date"
        params[attr] = Date.parse(value) rescue Date.today
      when "datetime"
        params[attr] = DateTime.parse(value) rescue DateTime.now
    end
  end
end

.create(object_attributes) ⇒ Object

Delegates to Client.create with arguments object_attributes and self



258
259
260
# File 'lib/databasedotcom/sobject/sobject.rb', line 258

def self.create(object_attributes)
  self.client.create(self, object_attributes)
end

.delete(record_id) ⇒ Object

Delegates to Client.delete with arguments record_id and self



212
213
214
# File 'lib/databasedotcom/sobject/sobject.rb', line 212

def self.delete(record_id)
  self.client.delete(self.sobject_name, record_id)
end

.field_type(attr_name) ⇒ Object

Returns the Force.com type of the attribute attr_name. Raises ArgumentError if attribute does not exist.

client.materialize("Car")
Car.field_type("Color")    #=> "string"


146
147
148
# File 'lib/databasedotcom/sobject/sobject.rb', line 146

def self.field_type(attr_name)
  self.type_map_attr(attr_name, :type)
end

.find(record_id) ⇒ Object

Delegates to Client.find with arguments record_id and self

client.materialize("Car")
Car.find("rid")    #=>   #<Car @Id="rid", ...>


169
170
171
# File 'lib/databasedotcom/sobject/sobject.rb', line 169

def self.find(record_id)
  self.client.find(self, record_id)
end

.first(where_expr = nil) ⇒ Object

Find the first record. If the where_expr argument is present, it must be the WHERE part of a SOQL query



195
196
197
198
# File 'lib/databasedotcom/sobject/sobject.rb', line 195

def self.first(where_expr=nil)
  where = where_expr ? "WHERE #{where_expr} " : ""
  self.client.query("SELECT #{self.field_list} FROM #{self.sobject_name} #{where}ORDER BY Id ASC LIMIT 1").first
end

.label_for(attr_name) ⇒ Object

Returns the label for the attribute attr_name. Raises ArgumentError if attribute does not exist.



151
152
153
# File 'lib/databasedotcom/sobject/sobject.rb', line 151

def self.label_for(attr_name)
  self.type_map_attr(attr_name, :label)
end

.last(where_expr = nil) ⇒ Object

Find the last record. If the where_expr argument is present, it must be the WHERE part of a SOQL query



201
202
203
204
# File 'lib/databasedotcom/sobject/sobject.rb', line 201

def self.last(where_expr=nil)
  where = where_expr ? "WHERE #{where_expr} " : ""
  self.client.query("SELECT #{self.field_list} FROM #{self.sobject_name} #{where}ORDER BY Id DESC LIMIT 1").first
end

.materialize(sobject_name) ⇒ Object

Materializes the dynamically created Sobject class by adding all attribute accessors for each field as described in the description of the object on Force.com



127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/databasedotcom/sobject/sobject.rb', line 127

def self.materialize(sobject_name)
  self.cattr_accessor :description
  self.cattr_accessor :type_map
  self.cattr_accessor :sobject_name

  self.sobject_name = sobject_name
  self.description = self.client.describe_sobject(self.sobject_name)
  self.type_map = {}
  self.description["fields"].each do |field|
    name = field["name"]
    attr_accessor name.to_sym
    self.type_map[name] = {:type => field["type"], :label => field["label"], :picklist_values => field["picklistValues"], :updateable? => field["updateable"]}
  end
end

.method_missing(method_name, *args, &block) ⇒ Object

Sobject objects support dynamic finders similar to ActiveRecord.

client.materialize("Car")
Car.find_by_Color("Blue")
Car.find_all_by_Year("2011")
Car.find_by_Color_and_Year("Blue", "2011")
Car.find_or_create_by_Year("2011")
Car.find_or_initialize_by_Name("Foo")


224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/databasedotcom/sobject/sobject.rb', line 224

def self.method_missing(method_name, *args, &block)
  if method_name.to_s =~ /^find_(or_create_|or_initialize_)?by_(.+)$/ || method_name.to_s =~ /^find_(all_)by_(.+)$/
    named_attrs = $2.split('_and_')
    attrs_and_values_for_find = []
    hash_args = args.length == 1 && args[0].is_a?(Hash)
    attrs_and_values_for_write = hash_args ? args[0] : {}

    named_attrs.each_with_index do |attr, index|
      value = hash_args ? args[0][attr] : args[index]
      attrs_and_values_for_find << "#{attr} = '#{value}'"
      attrs_and_values_for_write[attr] = value unless hash_args
    end

    limit_clause = method_name.to_s.include?('_all_by_') ? "" : " LIMIT 1"

    results = self.client.query("SELECT #{self.field_list} FROM #{self.sobject_name} WHERE #{attrs_and_values_for_find.join(' AND ')}#{limit_clause}")
    results = limit_clause == "" ? results : results.first rescue nil

    if results.nil?
      if method_name.to_s =~ /^find_or_create_by_(.+)$/
        results = self.client.create(self, attrs_and_values_for_write)
      elsif method_name.to_s =~ /^find_or_initialize_by_(.+)$/
        results = self.new
        attrs_and_values_for_write.each { |attr, val| results.send("#{attr}=", val) }
      end
    end

    results
  else
    super
  end
end

.picklist_values(attr_name) ⇒ Object

Returns the possible picklist options for the attribute attr_name. If attr_name is not of type picklist or multipicklist, [] is returned. Raises ArgumentError if attribute does not exist.



156
157
158
# File 'lib/databasedotcom/sobject/sobject.rb', line 156

def self.picklist_values(attr_name)
  self.type_map_attr(attr_name, :picklist_values)
end

.query(where_expr) ⇒ Object

Returns a collection of instances of self that match the conditional where_expr, which is the WHERE part of a SOQL query.

client.materialize("Car")
Car.query("Color = 'Blue'")    #=>   [#<Car @Id="1", @Color="Blue", ...>, #<Car @Id="5", @Color="Blue", ...>, ...]


185
186
187
# File 'lib/databasedotcom/sobject/sobject.rb', line 185

def self.query(where_expr)
  self.client.query("SELECT #{self.field_list} FROM #{self.sobject_name} WHERE #{where_expr}")
end

.search(sosl_expr) ⇒ Object

Delegates to Client.search



190
191
192
# File 'lib/databasedotcom/sobject/sobject.rb', line 190

def self.search(sosl_expr)
  self.client.search(sosl_expr)
end

.updateable?(attr_name) ⇒ Boolean

Returns true if the attribute attr_name can be updated. Raises ArgumentError if attribute does not exist.

Returns:

  • (Boolean)


161
162
163
# File 'lib/databasedotcom/sobject/sobject.rb', line 161

def self.updateable?(attr_name)
  self.type_map_attr(attr_name, :updateable?)
end

.upsert(field, value, attrs) ⇒ Object

Delegates to Client.upsert with arguments self, field, values, and attrs



207
208
209
# File 'lib/databasedotcom/sobject/sobject.rb', line 207

def self.upsert(field, value, attrs)
  self.client.upsert(self.sobject_name, field, value, attrs)
end

Instance Method Details

#[](attr_name) ⇒ Object



109
110
111
# File 'lib/databasedotcom/sobject/sobject.rb', line 109

def [](attr_name)
  self.send(attr_name) rescue nil
end

#[]=(attr_name, value) ⇒ Object

Raises:

  • (ArgumentError)


113
114
115
116
# File 'lib/databasedotcom/sobject/sobject.rb', line 113

def []=(attr_name, value)
  raise ArgumentError.new("No attribute named #{attr_name}") unless self.class.attributes.include?(attr_name)
  self.send("#{attr_name}=", value)
end

#attributes=(attrs) ⇒ Object



17
18
19
20
21
# File 'lib/databasedotcom/sobject/sobject.rb', line 17

def attributes=(attrs)
  attrs.each do |key, value|
    self.send("#{key}=", value)
  end
end

#deleteObject

Deletes the corresponding record from the Force.com database. Returns self.

client.materialize("Car")
c = Car.find_by_Color("Yellow")
c.delete


94
95
96
97
98
# File 'lib/databasedotcom/sobject/sobject.rb', line 94

def delete
  if self.client.delete(self.class, self.Id)
    self
  end
end

#new_record?Boolean

Returns true if this record has not been persisted in the Force.com database.

Returns:

  • (Boolean)


29
30
31
# File 'lib/databasedotcom/sobject/sobject.rb', line 29

def new_record?
  !self.persisted?
end

#persisted?Boolean

Returns true if the object has been persisted in the Force.com database.

Returns:

  • (Boolean)


24
25
26
# File 'lib/databasedotcom/sobject/sobject.rb', line 24

def persisted?
  !self.Id.nil?
end

#reloadObject

Reloads the record from the Force.com database. Returns the reloaded record.

client.materialize("Car")
c = Car.find_by_Color("Yellow")
c.reload


105
106
107
# File 'lib/databasedotcom/sobject/sobject.rb', line 105

def reload
  self.class.find(self.Id)
end

#saveObject

Updates the corresponding record on Force.com with the attributes of self.

client.materialize("Car")
c = Car.find_by_Color("Yellow")
c.Color = "Green"
c.save


78
79
80
81
82
83
84
85
86
87
# File 'lib/databasedotcom/sobject/sobject.rb', line 78

def save
  attr_hash = {}
  self.class.description["fields"].select { |f| f["updateable"] }.collect { |f| f["name"] }.each { |attr| attr_hash[attr] = self.send(attr) }

  if self.Id.nil?
    self.client.create(self.class, attr_hash)
  else
    self.client.update(self.class, self.Id, attr_hash)
  end
end

#to_keyObject

Returns a unique object id for self.



39
40
41
# File 'lib/databasedotcom/sobject/sobject.rb', line 39

def to_key
  [object_id]
end

#to_modelObject

Returns self.



34
35
36
# File 'lib/databasedotcom/sobject/sobject.rb', line 34

def to_model
  self
end

#to_paramObject

Returns the Force.com Id for this instance.



44
45
46
# File 'lib/databasedotcom/sobject/sobject.rb', line 44

def to_param
  self.Id
end

#update_attribute(attr_name, attr_value) ⇒ Object

Updates the corresponding record on Force.com by setting the attribute attr_name to attr_value.

client.materialize("Car")
c = Car.new
c.update_attribute("Color", "Blue")


53
54
55
# File 'lib/databasedotcom/sobject/sobject.rb', line 53

def update_attribute(attr_name, attr_value)
  update_attributes(attr_name => attr_value)
end

#update_attributes(new_attrs) ⇒ Object

Updates the corresponding record on Force.com with the attributes specified by the new_attrs hash.

client.materialize("Car")
c = Car.new
c.update_attributes {"Color" => "Blue", "Year" => "2012"}


62
63
64
65
66
67
68
69
70
# File 'lib/databasedotcom/sobject/sobject.rb', line 62

def update_attributes(new_attrs)
  if self.client.update(self.class, self.Id, new_attrs)
    new_attrs = new_attrs.is_a?(Hash) ? new_attrs : JSON.parse(new_attrs)
    new_attrs.each do |attr, value|
      self.send("#{attr}=", value)
    end
  end
  self
end