Class: AWS::Record::Base
- Inherits:
-
Object
- Object
- AWS::Record::Base
- Extended by:
- AttributeMacros, FinderMethods, Validations
- Includes:
- DirtyTracking
- Defined in:
- lib/aws/record/base.rb,
lib/aws/record/errors.rb
Overview
An ActiveRecord-like interface built ontop of AWS.
class Book < AWS::Record::Base
string_attr :title
string_attr :author
integer :number_of_pages
# adds a :created_at and :updated_at pair of timestamps
end
b = Book.new(:title => 'My Book', :author => 'Me', :pages => 1)
b.save
Attribute Macros
When extending AWS::Record::Base you should first consider what attributes your class should have. Unlike ActiveRecord, AWS::Record models are not backed by a database table/schema. You must choose what attributes (and what types) you need.
-
string_attr
-
boolean_attr
-
integer_attr
-
float_attr
-
datetime_attr
For more information about the various attribute macros available, and what options they accept, see AttributeMacros.
Usage
Normally you just call these methods inside your model class definition:
class Book < AWS::Record::Base
string_attr :title
boolean_attr :has_been_read
integer_attr :number_of_pages
float_attr :weight_in_pounds
datetime_attr :published_at
end
For each attribute macro a pair of setter/getter methods are added # to your class (and a few other useful methods).
b = Book.new
b.title = "My Book"
b.has_been_read = true
b.number_of_pages = 1000
b.weight_in_pounds = 1.1
b.published_at = Time.now
b.save
b.id #=> "0aa894ca-8223-4d34-831e-e5134b2bb71c"
b.attributes
#=> { 'title' => 'My Book', 'has_been_read' => true, ... }
Default Values
All attribute macros accept the :default_value
option. This sets a value that is populated onto all new instnaces of the class.
class Book < AWS::Record::Base
string_attr :author, :deafult_value => 'Me'
end
Book.new. #=> 'Me'
Multi-Valued (Set) Attributes
AWS::Record permits storing multiple values with a single attribute.
class Book < AWS::Record::Base
string_attr :tags, :set => true
end
b = Book.new
b. #=> #<Set: {}>
b. = ['fiction', 'fantasy']
b. #=> #<Set: {'fiction', 'fantasy'}>
These multi-valued attributes are treated as sets, not arrays. This means:
-
values are unordered
-
duplicate values are automatically omitted
Please consider these limitations when you choose to use the :set
option with the attribute macros.
Validations
It’s important to validate models before there are persisted to keep your data clean. AWS::Record supports most of the ActiveRecord style validators.
class Book < AWS::Record::Base
string_attr :title
validates_presence_of :title
end
b = Book.new
b.valid? #=> false
b.errors. #=> ['Title may not be blank']
Validations are checked before saving a record. If any of the validators adds an error, the the save will fail.
For more information about the available validation methods see Validations.
Finder Methods
You can find records by their ID. Each record gets a UUID when it is saved for the first time. You can use this ID to fetch the record at a latter time:
b = Book["0aa894ca-8223-4d34-831e-e5134b2bb71c"]
b = Book.find("0aa894ca-8223-4d34-831e-e5134b2bb71c")
If you try to find a record by ID that has no data an error will be raised.
All
You can enumerate all of your records using all
.
Book.all.each do |book|
puts book.id
end
Book.find(:all) do |book|
puts book.id
end
Be careful when enumerating all. Depending on the number of records and number of attributes each record has, this can take a while, causing quite a few requests.
First
If you only want a single record, you should use first
.
b = Book.first
Modifiers
Frequently you do not want ALL records or the very first record. You can pass options to find
, all
and first
.
my_books = Book.find(:all, :where => 'owner = "Me"')
book = Book.first(:where => { :has_been_read => false })
You can pass as find options:
-
:where
- Conditions that must be met to be returned -
:order
- The order to sort matched records by -
:limit
- The maximum number of records to return
Scopes
More useful than writing query fragments all over the place is to name your most common conditions for reuse.
class Book < AWS::Record::Base
scope :mine, where(:owner => 'Me')
scope :unread, where(:has_been_read => false)
scope :by_popularity, order(:score, :desc)
scope :top_10, by_popularity.limit(10)
end
# The following expression returns 10 books that belong
# to me, that are unread sorted by popularity.
next_good_reads = Book.mine.unread.top_10
There are 3 standard scope methods:
-
where
-
order
-
limit
Conditions (where)
Where accepts aruments in a number of forms:
-
As an sql-like fragment. If you need to escape values this form is not suggested.
Book.where('title = "My Book"')
-
An sql-like fragment, with placeholders. This escapes quoted arguments properly to avoid injection.
Book.where('title = ?', 'My Book')
-
A hash of key-value pairs. This is the simplest form, but also the least flexible. You can not use this form if you need more complex expressions that use or.
Book.where(:title => 'My Book')
Order
This orders the records as returned by AWS. Default ordering is ascending. Pass the value :desc as a second argument to sort in reverse ordering.
Book.order(:title) # alphabetical ordering
Book.order(:title, :desc) # reverse alphabetical ordering
You may only order by a single attribute. If you call order twice in the chain, the last call gets presedence:
Book.order(:title).order(:price)
In this example the books will be ordered by :price and the order(:title) is lost.
Limit
Just call limit
with an integer argument. This sets the maximum number of records to retrieve:
Book.limit(2)
Delayed Execution
It should be noted that all finds are lazy (except first
). This means the value returned is not an array of records, rather a handle to a Scope object that will return records when you enumerate over them.
This allows you to build an expression without making unecessary requests. In the following example no request is made until the call to each_with_index.
all_books = Books.all
ten_books = all_books.limit(10)
ten_books.each_with_index do |book,n|
puts "#{n + 1} : #{book.title}"
end
Instance Method Summary collapse
-
#attributes ⇒ Hash
A hash with attribute names as hash keys (strings) and attribute values (of mixed types) as hash values.
-
#delete ⇒ Object
Deletes the record.
-
#deleted? ⇒ Boolean
Returns true if this instance object has been deleted.
- #errors ⇒ Object
-
#id ⇒ String
The id for each record is auto-generated.
-
#initialize(attributes = {}) ⇒ Base
constructor
Constructs a new record for this class/domain.
-
#new_record? ⇒ Boolean
Returns true if this record has not been persisted to SimpleDB.
-
#persisted? ⇒ Boolean
Persistence indicates if the record has been saved previously or not.
-
#save ⇒ Boolean
Creates new records, updates existing records.
-
#save! ⇒ true
Creates new records, updates exsting records.
-
#update_attributes(attribute_hash) ⇒ Boolean
Bulk assigns the attributes and then saves the record.
-
#update_attributes!(attribute_hash) ⇒ true
Bulk assigns the attributes and then saves the record.
-
#valid? ⇒ Boolean
Returns true if this record has no validation errors.
Methods included from Validations
validates_acceptance_of, validates_confirmation_of, validates_count_of, validates_each, validates_exclusion_of, validates_format_of, validates_inclusion_of, validates_length_of, validates_numericality_of, validates_presence_of
Methods included from AttributeMacros
boolean_attr, datetime_attr, float_attr, integer_attr, sortable_float_attr, sortable_integer_attr, string_attr, timestamps
Methods included from FinderMethods
all, count, create_domain, domain_name, find, first, limit, optimistic_locking, order, scope, sdb_domain, set_domain_name, where
Methods included from DirtyTracking
Constructor Details
#initialize(attributes = {}) ⇒ Base
Constructs a new record for this class/domain.
299 300 301 302 303 |
# File 'lib/aws/record/base.rb', line 299 def initialize attributes = {} @_data = {} assign_default_values bulk_assign(attributes) end |
Instance Method Details
#attributes ⇒ Hash
Returns A hash with attribute names as hash keys (strings) and attribute values (of mixed types) as hash values.
315 316 317 318 319 320 321 322 |
# File 'lib/aws/record/base.rb', line 315 def attributes attributes = IndifferentHash.new attributes['id'] = id if persisted? self.class.attributes.keys.inject(attributes) do |hash,attr_name| hash[attr_name] = __send__(attr_name) hash end end |
#delete ⇒ Object
Deletes the record.
396 397 398 399 400 401 402 403 404 405 406 |
# File 'lib/aws/record/base.rb', line 396 def delete if persisted? if deleted? raise 'unable to delete, this object has already been deleted' else delete_item end else raise 'unable to delete, this object has not been saved yet' end end |
#deleted? ⇒ Boolean
Returns true if this instance object has been deleted.
409 410 411 |
# File 'lib/aws/record/base.rb', line 409 def deleted? persisted? ? !!@_deleted : false end |
#errors ⇒ Object
21 22 23 |
# File 'lib/aws/record/errors.rb', line 21 def errors @errors ||= Errors.new end |
#id ⇒ String
The id for each record is auto-generated. The default strategy generates uuid strings.
309 310 311 |
# File 'lib/aws/record/base.rb', line 309 def id @_id end |
#new_record? ⇒ Boolean
Returns true if this record has not been persisted to SimpleDB.
339 340 341 |
# File 'lib/aws/record/base.rb', line 339 def new_record? !persisted? end |
#persisted? ⇒ Boolean
Persistence indicates if the record has been saved previously or not.
333 334 335 |
# File 'lib/aws/record/base.rb', line 333 def persisted? !!@_persisted end |
#save ⇒ Boolean
Creates new records, updates existing records.
352 353 354 355 356 357 358 359 360 |
# File 'lib/aws/record/base.rb', line 352 def save if valid? persisted? ? update : create clear_changes! true else false end end |
#save! ⇒ true
Creates new records, updates exsting records. If there is a validation error then an exception is raised.
367 368 369 370 |
# File 'lib/aws/record/base.rb', line 367 def save! raise InvalidRecordError.new(self) unless save true end |
#update_attributes(attribute_hash) ⇒ Boolean
Bulk assigns the attributes and then saves the record.
376 377 378 379 |
# File 'lib/aws/record/base.rb', line 376 def update_attributes attribute_hash bulk_assign(attribute_hash) save end |
#update_attributes!(attribute_hash) ⇒ true
Bulk assigns the attributes and then saves the record. Raises an exception (AWS::Record::InvalidRecordError) if the record is not valid.
386 387 388 389 390 391 392 |
# File 'lib/aws/record/base.rb', line 386 def update_attributes! attribute_hash if update_attributes(attribute_hash) true else raise InvalidRecordError.new(self) end end |
#valid? ⇒ Boolean
Returns true if this record has no validation errors.
344 345 346 347 |
# File 'lib/aws/record/base.rb', line 344 def valid? validate errors.empty? end |