Class: Databasedotcom::Sobject::Sobject
- Inherits:
-
Object
- Object
- Databasedotcom::Sobject::Sobject
- 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
-
.all ⇒ Object
Returns all records of type self as instances.
-
.attributes ⇒ Object
Returns an Array of attribute names that this Sobject has.
-
.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.
-
.count ⇒ Object
Get the total number of records.
-
.create(object_attributes) ⇒ Object
Delegates to Client.create with arguments
object_attributes
and self. -
.createable?(attr_name) ⇒ Boolean
Returns true if the attribute
attr_name
can be created. -
.delete(record_id) ⇒ Object
Delegates to Client.delete with arguments
record_id
and self. -
.field_type(attr_name) ⇒ Object
Returns the Force.com type of the attribute
attr_name
. -
.find(record_id) ⇒ Object
Delegates to Client.find with arguments
record_id
and self. -
.first(where_expr = nil) ⇒ Object
Find the first record.
-
.label_for(attr_name) ⇒ Object
Returns the label for the attribute
attr_name
. -
.last(where_expr = nil) ⇒ Object
Find the last record.
-
.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.
-
.method_missing(method_name, *args, &block) ⇒ Object
Sobject objects support dynamic finders similar to ActiveRecord.
-
.picklist_values(attr_name) ⇒ Object
Returns the possible picklist options for the attribute
attr_name
. -
.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. -
.search(sosl_expr) ⇒ Object
Delegates to Client.search.
-
.updateable?(attr_name) ⇒ Boolean
Returns true if the attribute
attr_name
can be updated. -
.upsert(field, value, attrs) ⇒ Object
Delegates to Client.upsert with arguments self,
field
,values
, andattrs
.
Instance Method Summary collapse
- #==(other) ⇒ Object
-
#[](attr_name) ⇒ Object
Get a named attribute on this object.
-
#[]=(attr_name, value) ⇒ Object
Set a named attribute on this object.
-
#attributes ⇒ Object
Returns a hash representing the state of this object.
-
#attributes=(attrs) ⇒ Object
Set attributes of this object, from a hash, in bulk.
-
#delete ⇒ Object
Deletes the corresponding record from the Force.com database.
-
#initialize(attrs = {}) ⇒ Sobject
constructor
Returns a new Sobject.
-
#new_record? ⇒ Boolean
Returns true if this record has not been persisted in the Force.com database.
-
#persisted? ⇒ Boolean
Returns true if the object has been persisted in the Force.com database.
-
#reload ⇒ Object
Reloads the record from the Force.com database.
-
#save(options = {}) ⇒ Object
Updates the corresponding record on Force.com with the attributes of self.
-
#to_key ⇒ Object
Returns a unique object id for self.
-
#to_model ⇒ Object
Returns self.
-
#to_param ⇒ Object
Returns the Force.com Id for this instance.
-
#update_attribute(attr_name, attr_value) ⇒ Object
Updates the corresponding record on Force.com by setting the attribute
attr_name
toattr_value
. -
#update_attributes(new_attrs) ⇒ Object
Updates the corresponding record on Force.com with the attributes specified by the
new_attrs
hash.
Constructor Details
#initialize(attrs = {}) ⇒ Sobject
Returns a new Sobject. The default values for all attributes are set based on its description.
14 15 16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 14 def initialize(attrs = {}) super() self.class.description["fields"].each do |field| if field['type'] =~ /(picklist|multipicklist)/ && picklist_option = field['picklistValues'].find { |p| p['defaultValue'] } self.send("#{field["name"]}=", picklist_option["value"]) elsif field['type'] =~ /boolean/ self.send("#{field["name"]}=", field["defaultValue"]) else self.send("#{field["name"]}=", field["defaultValueFormula"]) end end self.attributes=(attrs) end |
Class Method Details
.all ⇒ Object
Returns all records of type self as instances.
client.materialize("Car")
Car.all #=> [#<Car @Id="1", ...>, #<Car @Id="2", ...>, #<Car @Id="3", ...>, ...]
225 226 227 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 225 def self.all self.client.query("SELECT #{self.field_list} FROM #{self.sobject_name}") end |
.attributes ⇒ Object
Returns an Array of attribute names that this Sobject has.
client.materialize("Car")
Car.attributes #=> ["Id", "Name", "Color", "Year"]
157 158 159 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 157 def self.attributes self.description["fields"].collect { |f| [f["name"], f["relationshipName"]] }.flatten.compact 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
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 318 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" value = value.gsub(/[^-0-9.0-9]/, '').to_f if value.respond_to?(:gsub) 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 |
.count ⇒ Object
Get the total number of records
265 266 267 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 265 def self.count self.client.query("SELECT COUNT() FROM #{self.sobject_name}").total_size end |
.create(object_attributes) ⇒ Object
Delegates to Client.create with arguments object_attributes
and self
312 313 314 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 312 def self.create(object_attributes) self.client.create(self, object_attributes) end |
.createable?(attr_name) ⇒ Boolean
Returns true if the attribute attr_name
can be created. Raises ArgumentError if attribute does not exist.
209 210 211 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 209 def self.createable?(attr_name) self.type_map_attr(attr_name, :createable?) end |
.delete(record_id) ⇒ Object
Delegates to Client.delete with arguments record_id
and self
260 261 262 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 260 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"
189 190 191 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 189 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", ...>
217 218 219 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 217 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
243 244 245 246 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 243 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.
194 195 196 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 194 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
249 250 251 252 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 249 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
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 162 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| # Register normal fields name = field["name"] register_field( field["name"], field ) # Register relationship fields. if( field["type"] == "reference" and field["relationshipName"] ) register_field( field["relationshipName"], field ) end 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")
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 277 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 condition = (args.last.is_a?(Hash) && args.size > 1) ? args.last[:cond] : "=" limit_clause = method_name.to_s.include?('_all_by_') ? "" : " LIMIT 1" results = self.client.query("SELECT #{self.field_list} FROM #{self.sobject_name} WHERE #{soql_conditions_for(attrs_and_values_for_find, condition)}#{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.
199 200 201 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 199 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", ...>, ...]
233 234 235 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 233 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
238 239 240 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 238 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.
204 205 206 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 204 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
255 256 257 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 255 def self.upsert(field, value, attrs) self.client.upsert(self.sobject_name, field, value, attrs) end |
Instance Method Details
#==(other) ⇒ Object
8 9 10 11 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 8 def ==(other) return false unless other.is_a?(self.class) self.Id == other.Id end |
#[](attr_name) ⇒ Object
Get a named attribute on this object
143 144 145 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 143 def [](attr_name) self.send(attr_name) rescue nil end |
#[]=(attr_name, value) ⇒ Object
Set a named attribute on this object
148 149 150 151 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 148 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 ⇒ Object
Returns a hash representing the state of this object
29 30 31 32 33 34 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 29 def attributes self.class.attributes.inject({}) do |hash, attr| hash[attr] = self.send(attr.to_sym) if self.respond_to?(attr.to_sym) hash end end |
#attributes=(attrs) ⇒ Object
Set attributes of this object, from a hash, in bulk
37 38 39 40 41 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 37 def attributes=(attrs) attrs.each do |key, value| self.send("#{key}=", value) end end |
#delete ⇒ Object
Deletes the corresponding record from the Force.com database. Returns self.
client.materialize("Car")
c = Car.find_by_Color("Yellow")
c.delete
126 127 128 129 130 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 126 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.
49 50 51 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 49 def new_record? !self.persisted? end |
#persisted? ⇒ Boolean
Returns true if the object has been persisted in the Force.com database.
44 45 46 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 44 def persisted? !self.Id.nil? end |
#reload ⇒ Object
Reloads the record from the Force.com database. Returns self.
client.materialize("Car")
c = Car.find_by_Color("Yellow")
c.reload
137 138 139 140 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 137 def reload self.attributes = self.class.find(self.Id).attributes self end |
#save(options = {}) ⇒ Object
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
options can contain the following keys:
exclusions # an array of field names (case sensitive) to exclude from save
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 102 def save(={}) attr_hash = {} selection_attr = self.Id.nil? ? "createable" : "updateable" self.class.description["fields"].select { |f| f[selection_attr] }.collect { |f| f["name"] }.each { |attr| attr_hash[attr] = self.send(attr) } # allow fields to be removed on a case by case basis as some data is not allowed to be saved # (e.g. Name field on Account with record type of Person Account) despite the API listing # some fields as editable if [:exclusions] and [:exclusions].respond_to?(:include?) then attr_hash.delete_if { |key, value| [:exclusions].include?(key.to_s) } end if self.Id.nil? self.Id = self.client.create(self.class, attr_hash).Id else self.client.update(self.class, self.Id, attr_hash) end end |
#to_key ⇒ Object
Returns a unique object id for self.
59 60 61 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 59 def to_key [object_id] end |
#to_model ⇒ Object
Returns self.
54 55 56 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 54 def to_model self end |
#to_param ⇒ Object
Returns the Force.com Id for this instance.
64 65 66 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 64 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")
73 74 75 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 73 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"}
82 83 84 85 86 87 88 89 90 |
# File 'lib/databasedotcom/sobject/sobject.rb', line 82 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 |