Class: RightAws::ActiveSdb::Base

Inherits:
Object
  • Object
show all
Extended by:
ActiveSdbConnect
Defined in:
lib/sdb/active_sdb.rb

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ActiveSdbConnect

establish_connection

Constructor Details

#initialize(attrs = {}) ⇒ Base

Create new Item instance. attrs is a hash: { attribute1 => values1, ..., attributeN => valuesN }.

item = Client.new('name' => 'Jon', 'toys' => ['girls', 'beer', 'pub'])
puts item.inspect   #=> #<Client:0xb77a2698 @new_record=true, @attributes={"name"=>["Jon"], "toys"=>["girls", "beer", "pub"]}>
item.save           #=> {"name"=>["Jon"], "id"=>"c03edb7e-e45c-11dc-bede-001bfc466dd7", "toys"=>["girls", "beer", "pub"]}
puts item.inspect   #=> #<Client:0xb77a2698 @new_record=false, @attributes={"name"=>["Jon"], "id"=>"c03edb7e-e45c-11dc-bede-001bfc466dd7", "toys"=>["girls", "beer", "pub"]}>


699
700
701
702
# File 'lib/sdb/active_sdb.rb', line 699

def initialize(attrs={})
  @attributes = uniq_values(attrs)
  @new_record = true
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_sym, *args) ⇒ Object

support accessing attribute values via method call



1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
# File 'lib/sdb/active_sdb.rb', line 1010

def method_missing(method_sym, *args)
  method_name = method_sym.to_s
  setter = method_name[-1,1] == '='
  method_name.chop! if setter

  if @attributes.has_key?(method_name) || self.class.column?(method_name)
    setter ? self[method_name] = args.first : self[method_name]
  else
    super
  end
end

Class Attribute Details

.next_tokenObject

next_token value returned by last find: is useful to continue finding



209
210
211
# File 'lib/sdb/active_sdb.rb', line 209

def next_token
  @next_token
end

Instance Attribute Details

#attributesObject

Returns a hash of all the attributes.

puts item.attributes.inspect #=> {"name"=>["Cat"], "id"=>"2937601a-e45d-11dc-a75f-001bfc466dd7", "toys"=>["Jons socks", "clew", "mice"]}


686
687
688
# File 'lib/sdb/active_sdb.rb', line 686

def attributes
  @attributes.dup
end

#idObject

Returns an item id. Same as: item or item.attributes



689
690
691
# File 'lib/sdb/active_sdb.rb', line 689

def id
  @attributes['id']
end

Class Method Details

.column?(col_name) ⇒ Boolean

Returns:

  • (Boolean)


305
306
307
# File 'lib/sdb/active_sdb.rb', line 305

def column?(col_name)
  columns.include?(col_name)
end

.columns(&block) ⇒ Object



299
300
301
302
303
# File 'lib/sdb/active_sdb.rb', line 299

def columns(&block)
  @columns ||= ColumnSet.new
  @columns.instance_eval(&block) if block
  @columns
end

.connectionObject

Returns a RightAws::SdbInterface object

class A < RightAws::ActiveSdb::Base
end

class B < RightAws::ActiveSdb::Base
end

class C < RightAws::ActiveSdb::Base
end

RightAws::ActiveSdb.establish_connection 'key_id_1', 'secret_key_1'

C.establish_connection 'key_id_2', 'secret_key_2'

# A and B uses the default connection, C - uses its own 
puts A.connection  #=> #<RightAws::SdbInterface:0xb76d6d7c>
puts B.connection  #=> #<RightAws::SdbInterface:0xb76d6d7c>
puts C.connection  #=> #<RightAws::SdbInterface:0xb76d6ca0>


231
232
233
# File 'lib/sdb/active_sdb.rb', line 231

def connection
  @connection || ActiveSdb::connection
end

.create(attributes = {}) ⇒ Object

Create and save new Item instance. Attributes is a hash: { attribute1 => values1, ..., attributeN => valuesN }.

item = Client.create('name' => 'Cat', 'toys' => ['Jons socks', 'mice', 'clew']) 
puts item.inspect   #=> #<Client:0xb77a0a78 @new_record=false, @attributes={"name"=>["Cat"], "id"=>"2937601a-e45d-11dc-a75f-001bfc466dd7", "toys"=>["Jons socks", "mice", "clew"]}>


710
711
712
713
714
# File 'lib/sdb/active_sdb.rb', line 710

def self.create(attributes={})
  item = self.new(attributes)
  item.save
  item
end

.create_domainObject

Create domain at SDB. Raises no errors if the domain already exists.

class Client < RightAws::ActiveSdb::Base
end
Client.create_domain  #=> {:request_id=>"6fc652a0-0000-41d5-91f4-3ed390a3d3b2", :box_usage=>"0.0055590278"}


284
285
286
# File 'lib/sdb/active_sdb.rb', line 284

def create_domain
  connection.create_domain(domain)
end

.delete_domainObject

Remove domain from SDB. Raises no errors if the domain does not exist.

class Client < RightAws::ActiveSdb::Base
end
Client.delete_domain  #=> {:request_id=>"e14d90d3-0000-4898-9995-0de28cdda270", :box_usage=>"0.0055590278"}


295
296
297
# File 'lib/sdb/active_sdb.rb', line 295

def delete_domain
  connection.delete_domain(domain)
end

.deserialize(attribute, value) ⇒ Object



318
319
320
321
# File 'lib/sdb/active_sdb.rb', line 318

def deserialize(attribute, value)
  s = serialization_for_type(type_of(attribute))
  s ? s.deserialize(value) : value
end

.domainObject

Current domain name.

# if 'ActiveSupport' is not loaded then class name converted to downcase
class Client < RightAws::ActiveSdb::Base
end
puts Client.domain  #=> 'client'

# if 'ActiveSupport' is loaded then class name being tableized
require 'activesupport'
class Client < RightAws::ActiveSdb::Base
end
puts Client.domain  #=> 'clients'

# Explicit domain name definition
class Client < RightAws::ActiveSdb::Base
  set_domain_name :foreign_clients
end
puts Client.domain  #=> 'foreign_clients'


256
257
258
259
260
261
262
263
264
265
# File 'lib/sdb/active_sdb.rb', line 256

def domain
  unless @domain
    if defined? ActiveSupport::CoreExtensions::String::Inflections
      @domain = name.tableize
    else
      @domain = name.downcase
    end
  end
  @domain
end

.find(*args) ⇒ Object

Perform a find request.

Single record:

Client.find(:first)
Client.find(:first, :conditions=> [ "['name'=?] intersection ['wife'=?]", "Jon", "Sandy"])

Bunch of records:

Client.find(:all)
Client.find(:all, :limit => 10)
Client.find(:all, :conditions=> [ "['name'=?] intersection ['girlfriend'=?]", "Jon", "Judy"])
Client.find(:all, :conditions=> [ "['name'=?]", "Sandy"], :limit => 3)

Records by ids:

Client.find('1')
Client.find('1234987b4583475347523948')
Client.find('1','2','3','4', :conditions=> [ "['toys'=?]", "beer"])

Find helpers: RightAws::ActiveSdb::Base.find_by_... and RightAws::ActiveSdb::Base.find_all_by_...

Client.find_by_name('Matias Rust')
Client.find_by_name_and_city('Putin','Moscow')
Client.find_by_name_and_city_and_post('Medvedev','Moscow','president')

Client.find_all_by_author('G.Bush jr')
Client.find_all_by_age_and_gender_and_ethnicity('34','male','russian')
Client.find_all_by_gender_and_country('male', 'Russia', :auto_load => true, :order => 'name desc')

Returned records have to be reloaded to access their attributes.

item = Client.find_by_name('Cat')  #=> #<Client:0xb77d0d40 @attributes={"id"=>"2937601a-e45d-11dc-a75f-001bfc466dd7"}, @new_record=false>
item.reload                        #=> #<Client:0xb77d0d40 @attributes={"id"=>"2937601a-e45d-11dc-a75f-001bfc466dd7", "name"=>["Cat"], "toys"=>["Jons socks", "clew", "mice"]}, @new_record=false>

Continue listing:

# initial listing
Client.find(:all, :limit => 10)
# continue listing
begin
  Client.find(:all, :limit => 10, :next_token => Client.next_token)
end while Client.next_token

Sort oder:
  Client.find(:all, :order => 'gender')
  Client.find(:all, :order => 'name desc')

Attributes auto load (be carefull - this may take lot of time for a huge bunch of records):
  Client.find(:first)                      #=> #<Client:0xb77d0d40 @attributes={"id"=>"2937601a-e45d-11dc-a75f-001bfc466dd7"}, @new_record=false>
  Client.find(:first, :auto_load => true)  #=> #<Client:0xb77d0d40 @attributes={"id"=>"2937601a-e45d-11dc-a75f-001bfc466dd7", "name"=>["Cat"], "toys"=>["Jons socks", "clew", "mice"]}, @new_record=false>

see docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/index.html?UsingQuery.html



376
377
378
379
380
381
382
383
# File 'lib/sdb/active_sdb.rb', line 376

def find(*args)
  options = args.last.is_a?(Hash) ? args.pop : {}
  case args.first
    when :all   then find_every    options
    when :first then find_initial  options
    else             find_from_ids args, options
  end
end

.generate_idObject

:nodoc:



443
444
445
446
447
448
449
# File 'lib/sdb/active_sdb.rb', line 443

def generate_id # :nodoc:
  if UUID::VERSION::STRING < '2.0.0'
    UUID.timestamp_create().to_s
  else
    UUIDTools::UUID.timestamp_create().to_s
  end
end

.select(*args) ⇒ Object

Perform a SQL-like select request.

Single record:

Client.select(:first)
Client.select(:first, :conditions=> [ "name=? AND wife=?", "Jon", "Sandy"])
Client.select(:first, :conditions=> { :name=>"Jon", :wife=>"Sandy" }, :select => :girfriends)

Bunch of records:

Client.select(:all)
Client.select(:all, :limit => 10)
Client.select(:all, :conditions=> [ "name=? AND 'girlfriend'=?", "Jon", "Judy"])
Client.select(:all, :conditions=> { :name=>"Sandy" }, :limit => 3)

Records by ids:

Client.select('1')
Client.select('1234987b4583475347523948')
Client.select('1','2','3','4', :conditions=> ["toys=?", "beer"])

Find helpers: RightAws::ActiveSdb::Base.select_by_... and RightAws::ActiveSdb::Base.select_all_by_...

Client.select_by_name('Matias Rust')
Client.select_by_name_and_city('Putin','Moscow')
Client.select_by_name_and_city_and_post('Medvedev','Moscow','president')

Client.select_all_by_author('G.Bush jr')
Client.select_all_by_age_and_gender_and_ethnicity('34','male','russian')
Client.select_all_by_gender_and_country('male', 'Russia', :order => 'name')

Continue listing:

# initial listing
Client.select(:all, :limit => 10)
# continue listing
begin
  Client.select(:all, :limit => 10, :next_token => Client.next_token)
end while Client.next_token

Sort oder:
If :order=>'attribute' option is specified then result response (ordered by 'attribute') will contain only items where attribute is defined (is not null).

  Client.select(:all)                         # returns all records
  Client.select(:all, :order => 'gender')     # returns all records ordered by gender where gender attribute exists
  Client.select(:all, :order => 'name desc')  # returns all records ordered by name in desc order where name attribute exists

see docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/index.html?UsingSelect.html



434
435
436
437
438
439
440
441
# File 'lib/sdb/active_sdb.rb', line 434

def select(*args)
  options = args.last.is_a?(Hash) ? args.pop : {}
  case args.first
    when :all   then sql_select(options)
    when :first then sql_select(options.merge(:limit => 1)).first
    else             select_from_ids args, options
  end
end

.serialize(attribute, value) ⇒ Object



313
314
315
316
# File 'lib/sdb/active_sdb.rb', line 313

def serialize(attribute, value)
  s = serialization_for_type(type_of(attribute))
  s ? s.serialize(value) : value.to_s
end

.set_domain_name(domain) ⇒ Object

Change the default domain name to user defined.

class Client < RightAws::ActiveSdb::Base
  set_domain_name :foreign_clients
end


273
274
275
# File 'lib/sdb/active_sdb.rb', line 273

def set_domain_name(domain)
  @domain = domain.to_s
end

.type_of(col_name) ⇒ Object



309
310
311
# File 'lib/sdb/active_sdb.rb', line 309

def type_of(col_name)
  columns.type_of(col_name)
end

Instance Method Details

#[](attribute) ⇒ Object

Returns the values of the attribute identified by attribute.

puts item['Cat'].inspect  #=> ["Jons socks", "clew", "mice"]


769
770
771
772
# File 'lib/sdb/active_sdb.rb', line 769

def [](attribute)
  raw = @attributes[attribute.to_s]
  self.class.column?(attribute) && raw ? self.class.deserialize(attribute, raw.first) : raw
end

#[]=(attribute, values) ⇒ Object

Updates the attribute identified by attribute with the specified values.

puts item['Cat'].inspect  #=> ["Jons socks", "clew", "mice"]
item['Cat'] = ["Whiskas", "chicken"]
puts item['Cat'].inspect  #=> ["Whiskas", "chicken"]


780
781
782
783
784
785
786
787
788
789
790
# File 'lib/sdb/active_sdb.rb', line 780

def []=(attribute, values)
  attribute = attribute.to_s
  @attributes[attribute] = case
  when attribute == 'id'
    values.to_s
  when self.class.column?(attribute)
    self.class.serialize(attribute, values)
  else
    Array(values).uniq
  end
end

#columnsObject



752
753
754
# File 'lib/sdb/active_sdb.rb', line 752

def columns
  self.class.columns
end

#connectionObject



756
757
758
# File 'lib/sdb/active_sdb.rb', line 756

def connection
  self.class.connection
end

#deleteObject

Delete the Item entirely from SDB.

sandy = Client.find_by_name 'Sandy' 
sandy.reload
sandy.inspect       #=> #<Client:0xb7761d28 @new_record=false, @attributes={"name"=>["Sandy"], "id"=>"b2832ce2-e461-11dc-b13c-001bfc466dd7", "toys"=>["boys", "kids", "patchwork"}>
puts sandy.delete
sandy.reload      
puts sandy.inspect  #=> #<Client:0xb7761d28 @attributes={}, @new_record=false>


990
991
992
993
# File 'lib/sdb/active_sdb.rb', line 990

def delete
  raise_on_id_absence
  connection.delete_attributes(domain, id)
end

#delete_attributes(*attrs_list) ⇒ Object

Removes specified attributes from the item. attrs_list is an array or comma separated list of attributes names. Returns the list of deleted attributes.

sandy = Client.find_by_name 'Sandy' 
sandy.reload
puts sandy.inspect                   #=> #<Client:0xb7761d28 @new_record=false, @attributes={"name"=>["Sandy"], "id"=>"b2832ce2-e461-11dc-b13c-001bfc466dd7", "toys"=>["boys", "kids", "patchwork"}>
puts sandy.delete_attributes('toys') #=> ['toys']
puts sandy.inspect                   #=> #<Client:0xb7761d28 @new_record=false, @attributes={"name"=>["Sandy"], "id"=>"b2832ce2-e461-11dc-b13c-001bfc466dd7"}>


970
971
972
973
974
975
976
977
978
979
# File 'lib/sdb/active_sdb.rb', line 970

def delete_attributes(*attrs_list)
  raise_on_id_absence
  attrs_list = attrs_list.flatten.map{ |attribute| attribute.to_s }
  attrs_list.delete('id')
  unless attrs_list.blank?
    connection.delete_attributes(domain, id, attrs_list)
    attrs_list.each { |attribute| @attributes.delete(attribute) }
  end
  attrs_list
end

#delete_values(attrs) ⇒ Object

Remove specified values from corresponding attributes. attrs is a hash: { attribute1 => values1, ..., attributeN => valuesN }.

sandy = Client.find_by_name 'Sandy' 
sandy.reload
puts sandy.inspect                                #=> #<Client:0xb77b48fc @new_record=false, @attributes={"name"=>["Sandy"], "id"=>"b2832ce2-e461-11dc-b13c-001bfc466dd7", "toys"=>["boys", "kids", "patchwork"]}>
puts sandy.delete_values('toys' => 'patchwork')   #=> { 'toys' => ['patchwork'] }
puts sandy.inspect                                #=> #<Client:0xb77b48fc @new_record=false, @attributes={"name"=>["Sandy"], "id"=>"b2832ce2-e461-11dc-b13c-001bfc466dd7", "toys"=>["boys", "kids"]}>


941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
# File 'lib/sdb/active_sdb.rb', line 941

def delete_values(attrs)
  raise_on_id_absence
  attrs = uniq_values(attrs)
  attrs.delete('id')
  unless attrs.blank?
    connection.delete_attributes(domain, id, attrs)
    attrs.each do |attribute, values|
      # remove the values from the attribute
      if @attributes[attribute]
        @attributes[attribute] -= values
      else
        # if the attribute is unknown remove it from a resulting list of fixed attributes
        attrs.delete(attribute)
      end
    end
  end
  attrs
end

#domainObject

Item domain name.



761
762
763
# File 'lib/sdb/active_sdb.rb', line 761

def domain
  self.class.domain
end

#mark_as_oldObject

:nodoc:



1005
1006
1007
# File 'lib/sdb/active_sdb.rb', line 1005

def mark_as_old  # :nodoc:
  @new_record = false
end

#new_record?Boolean

Returns true if this object hasn???t been saved yet.

Returns:

  • (Boolean)


1001
1002
1003
# File 'lib/sdb/active_sdb.rb', line 1001

def new_record?
  @new_record
end

#putObject

Stores in-memory attributes to SDB. Adds the attributes values to already stored at SDB. Returns a hash of stored attributes.

sandy = Client.new(:name => 'Sandy') #=> #<Client:0xb775a7a8 @attributes={"name"=>["Sandy"]}, @new_record=true>
sandy['toys'] = 'boys'
sandy.put
sandy['toys'] = 'patchwork'
sandy.put
sandy['toys'] = 'kids'
sandy.put
puts sandy.attributes.inspect        #=> {"name"=>["Sandy"], "id"=>"b2832ce2-e461-11dc-b13c-001bfc466dd7", "toys"=>["kids"]}
sandy.reload                         #=> {"name"=>["Sandy"], "id"=>"b2832ce2-e461-11dc-b13c-001bfc466dd7", "toys"=>["boys", "kids", "patchwork"]}

compare to save method



853
854
855
856
857
858
859
860
861
862
# File 'lib/sdb/active_sdb.rb', line 853

def put
  @attributes = uniq_values(@attributes)
  prepare_for_update
  attrs = @attributes.dup
  attrs.delete('id')
  connection.put_attributes(domain, id, attrs) unless attrs.blank?
  connection.put_attributes(domain, id, { 'id' => id }, :replace)
  mark_as_old
  @attributes
end

#put_attributes(attrs) ⇒ Object

Stores specified attributes. attrs is a hash: { attribute1 => values1, ..., attributeN => valuesN }. Returns a hash of saved attributes.

see to put method



869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
# File 'lib/sdb/active_sdb.rb', line 869

def put_attributes(attrs)
  attrs = uniq_values(attrs)
  prepare_for_update
  # if 'id' is present in attrs hash:
  # replace internal 'id' attribute and remove it from the attributes to be sent
  @attributes['id'] = attrs['id'] unless attrs['id'].blank?
  attrs.delete('id')
  # add new values to all attributes from list
  connection.put_attributes(domain, id, attrs) unless attrs.blank?
  connection.put_attributes(domain, id, { 'id' => id }, :replace)
  attrs.each do |attribute, values|
    @attributes[attribute] ||= []
    @attributes[attribute] += values
    @attributes[attribute].uniq!
  end
  mark_as_old
  attributes
end

#reloadObject

Reload attributes from SDB. Replaces in-memory attributes.

item = Client.find_by_name('Cat')  #=> #<Client:0xb77d0d40 @attributes={"id"=>"2937601a-e45d-11dc-a75f-001bfc466dd7"}, @new_record=false>
item.reload                        #=> #<Client:0xb77d0d40 @attributes={"id"=>"2937601a-e45d-11dc-a75f-001bfc466dd7", "name"=>["Cat"], "toys"=>["Jons socks", "clew", "mice"]}, @new_record=false>


797
798
799
800
801
802
803
804
805
806
807
808
# File 'lib/sdb/active_sdb.rb', line 797

def reload
  raise_on_id_absence
  old_id = id
  attrs = connection.get_attributes(domain, id)[:attributes]
  @attributes = {}
  unless attrs.blank?
    attrs.each { |attribute, values| @attributes[attribute] = values }
    @attributes['id'] = old_id
  end
  mark_as_old
  @attributes
end

#reload_attributes(*attrs_list) ⇒ Object

Reload a set of attributes from SDB. Adds the loaded list to in-memory data. attrs_list is an array or comma separated list of attributes names. Returns a hash of loaded attributes.

This is not the best method to get a bunch of attributes because a web service call is being performed for every attribute.

item = Client.find_by_name('Cat')
item.reload_attributes('toys', 'name')   #=> {"name"=>["Cat"], "toys"=>["Jons socks", "clew", "mice"]}


820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
# File 'lib/sdb/active_sdb.rb', line 820

def reload_attributes(*attrs_list)
  raise_on_id_absence
  attrs_list = attrs_list.flatten.map{ |attribute| attribute.to_s }
  attrs_list.delete('id')
  result = {}
  attrs_list.flatten.uniq.each do |attribute|
    attribute = attribute.to_s
    values = connection.get_attributes(domain, id, attribute)[:attributes][attribute]
    unless values.blank?
      @attributes[attribute] = result[attribute] = values
    else
      @attributes.delete(attribute)
    end
  end
  mark_as_old
  result
end

#saveObject

Store in-memory attributes to SDB. Replaces the attributes values already stored at SDB by in-memory data. Returns a hash of stored attributes.

sandy = Client.new(:name => 'Sandy')  #=> #<Client:0xb775a7a8 @attributes={"name"=>["Sandy"]}, @new_record=true>
sandy['toys'] = 'boys'
sandy.put
sandy['toys'] = 'patchwork'
sandy.put
sandy['toys'] = 'kids'
sandy.put
puts sandy.attributes.inspect         #=> {"name"=>["Sandy"], "id"=>"b2832ce2-e461-11dc-b13c-001bfc466dd7", "toys"=>["kids"]}
sandy.reload                          #=> {"name"=>["Sandy"], "id"=>"b2832ce2-e461-11dc-b13c-001bfc466dd7", "toys"=>["kids"]}

compare to put method



903
904
905
906
907
908
909
# File 'lib/sdb/active_sdb.rb', line 903

def save
  @attributes = uniq_values(@attributes)
  prepare_for_update
  connection.put_attributes(domain, id, @attributes, :replace)
  mark_as_old
  @attributes
end

#save_attributes(attrs) ⇒ Object

Replaces the attributes at SDB by the given values. Attrs is a hash: { attribute1 => values1, ..., attributeN => valuesN }. The other in-memory attributes are not being saved. Returns a hash of stored attributes.

see save method



917
918
919
920
921
922
923
924
925
926
927
928
929
930
# File 'lib/sdb/active_sdb.rb', line 917

def save_attributes(attrs)
  prepare_for_update
  attrs = uniq_values(attrs)
  # if 'id' is present in attrs hash then replace internal 'id' attribute
  unless attrs['id'].blank?
    @attributes['id'] = attrs['id']
  else
    attrs['id'] = id
  end
  connection.put_attributes(domain, id, attrs, :replace) unless attrs.blank?
  attrs.each { |attribute, values| attrs[attribute] = values }
  mark_as_old
  attrs
end

#to_sObject

Item ID



996
997
998
# File 'lib/sdb/active_sdb.rb', line 996

def to_s
  @id
end