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"]}>


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

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



995
996
997
998
999
1000
1001
1002
1003
1004
1005
# File 'lib/sdb/active_sdb.rb', line 995

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



198
199
200
# File 'lib/sdb/active_sdb.rb', line 198

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"]}


671
672
673
# File 'lib/sdb/active_sdb.rb', line 671

def attributes
  @attributes
end

#idObject

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



674
675
676
# File 'lib/sdb/active_sdb.rb', line 674

def id
  @id
end

Class Method Details

.column?(col_name) ⇒ Boolean

Returns:

  • (Boolean)


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

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

.columns(&block) ⇒ Object



288
289
290
291
292
# File 'lib/sdb/active_sdb.rb', line 288

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>


220
221
222
# File 'lib/sdb/active_sdb.rb', line 220

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"]}>


695
696
697
698
699
# File 'lib/sdb/active_sdb.rb', line 695

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"}


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

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"}


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

def delete_domain
  connection.delete_domain(domain)
end

.deserialize(attribute, value) ⇒ Object



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

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'


245
246
247
248
249
250
251
252
253
254
# File 'lib/sdb/active_sdb.rb', line 245

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



365
366
367
368
369
370
371
372
# File 'lib/sdb/active_sdb.rb', line 365

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:



432
433
434
# File 'lib/sdb/active_sdb.rb', line 432

def generate_id # :nodoc:
  AwsUtils::generate_unique_token
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



423
424
425
426
427
428
429
430
# File 'lib/sdb/active_sdb.rb', line 423

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



302
303
304
305
# File 'lib/sdb/active_sdb.rb', line 302

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


262
263
264
# File 'lib/sdb/active_sdb.rb', line 262

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

.type_of(col_name) ⇒ Object



298
299
300
# File 'lib/sdb/active_sdb.rb', line 298

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"]


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

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"]


765
766
767
768
769
770
771
772
773
774
775
# File 'lib/sdb/active_sdb.rb', line 765

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



737
738
739
# File 'lib/sdb/active_sdb.rb', line 737

def columns
  self.class.columns
end

#connectionObject



741
742
743
# File 'lib/sdb/active_sdb.rb', line 741

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>


975
976
977
978
# File 'lib/sdb/active_sdb.rb', line 975

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"}>


955
956
957
958
959
960
961
962
963
964
# File 'lib/sdb/active_sdb.rb', line 955

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.right_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"]}>


926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
# File 'lib/sdb/active_sdb.rb', line 926

def delete_values(attrs)
  raise_on_id_absence
  attrs = uniq_values(attrs)
  attrs.delete('id')
  unless attrs.right_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.



746
747
748
# File 'lib/sdb/active_sdb.rb', line 746

def domain
  self.class.domain
end

#mark_as_oldObject

:nodoc:



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

def mark_as_old  # :nodoc:
  @new_record = false
end

#new_record?Boolean

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

Returns:

  • (Boolean)


986
987
988
# File 'lib/sdb/active_sdb.rb', line 986

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



838
839
840
841
842
843
844
845
846
847
# File 'lib/sdb/active_sdb.rb', line 838

def put
  @attributes = uniq_values(@attributes)
  prepare_for_update
  attrs = @attributes.dup
  attrs.delete('id')
  connection.put_attributes(domain, id, attrs) unless attrs.right_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



854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
# File 'lib/sdb/active_sdb.rb', line 854

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'].right_blank?
  attrs.delete('id')
  # add new values to all attributes from list
  connection.put_attributes(domain, id, attrs) unless attrs.right_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>


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

def reload
  raise_on_id_absence
  old_id = id
  attrs = connection.get_attributes(domain, id)[:attributes]
  @attributes = {}
  unless attrs.right_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"]}


805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
# File 'lib/sdb/active_sdb.rb', line 805

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.right_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



888
889
890
891
892
893
894
# File 'lib/sdb/active_sdb.rb', line 888

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



902
903
904
905
906
907
908
909
910
911
912
913
914
915
# File 'lib/sdb/active_sdb.rb', line 902

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'].right_blank?
    @attributes['id'] = attrs['id']
  else
    attrs['id'] = id
  end
  connection.put_attributes(domain, id, attrs, :replace) unless attrs.right_blank?
  attrs.each { |attribute, values| attrs[attribute] = values }
  mark_as_old
  attrs
end

#to_sObject

Item ID



981
982
983
# File 'lib/sdb/active_sdb.rb', line 981

def to_s
  @id
end