Class: DynamodbModel::Item
- Inherits:
-
Object
- Object
- DynamodbModel::Item
- Includes:
- DbConfig
- Defined in:
- lib/dynamodb_model/item.rb
Class Method Summary collapse
-
.delete(key_object, options = {}) ⇒ Object
Two ways to use the delete method:.
- .find(id) ⇒ Object
- .get_table_name ⇒ Object
-
.partition_key(*args) ⇒ Object
When called with an argument we’ll set the internal @partition_key value When called without an argument just retun it.
-
.query(params = {}) ⇒ Object
Adds very little wrapper logic to query.
- .replace(attrs) ⇒ Object
-
.scan(params = {}) ⇒ Object
Adds very little wrapper logic to scan.
- .set_table_name(value) ⇒ Object
- .table_name(*args) ⇒ Object
-
.where(attributes, options = {}) ⇒ Object
Translates simple query searches:.
Instance Method Summary collapse
- #attributes ⇒ Object
-
#attributes=(attributes) ⇒ Object
Longer hand methods for completeness.
-
#attrs(*args) ⇒ Object
Defining our own reader so we can do a deep merge if user passes in attrs.
- #delete ⇒ Object
- #find(id) ⇒ Object
-
#initialize(attrs = {}) ⇒ Item
constructor
A new instance of Item.
- #partition_key ⇒ Object
-
#replace ⇒ Object
The method is named replace to clearly indicate that the item is fully replaced.
- #table_name ⇒ Object
- #to_attrs ⇒ Object
Methods included from DbConfig
#db, included, #namespaced_table_name
Constructor Details
#initialize(attrs = {}) ⇒ Item
Returns a new instance of Item.
42 43 44 |
# File 'lib/dynamodb_model/item.rb', line 42 def initialize(attrs={}) @attrs = attrs end |
Class Method Details
.delete(key_object, options = {}) ⇒ Object
Two ways to use the delete method:
-
Specify the key as a String. In this case the key will is the partition_key
set on the model.
MyModel.delete("728e7b5df40b93c3ea6407da8ac3e520e00d7351")
-
Specify the key as a Hash, you can arbitrarily specific the key structure this way
MyModel.delete(“728e7b5df40b93c3ea6407da8ac3e520e00d7351”)
options is provided in case you want to specific condition_expression or expression_attribute_values.
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/dynamodb_model/item.rb', line 237 def self.delete(key_object, ={}) if key_object.is_a?(String) key = { partition_key => key_object } else # it should be a Hash key = key_object end params = { table_name: table_name, key: key } # In case you want to specify condition_expression or expression_attribute_values params = params.merge() resp = db.delete_item(params) end |
.find(id) ⇒ Object
217 218 219 220 221 222 223 224 |
# File 'lib/dynamodb_model/item.rb', line 217 def self.find(id) resp = db.get_item( table_name: table_name, key: {partition_key => id} ) attributes = resp.item # unwraps the item's attributes self.new(attributes) if attributes end |
.get_table_name ⇒ Object
279 280 281 282 |
# File 'lib/dynamodb_model/item.rb', line 279 def self.get_table_name @table_name ||= self.name.pluralize.underscore [table_namespace, @table_name].reject {|s| s.nil? || s.empty?}.join('-') end |
.partition_key(*args) ⇒ Object
When called with an argument we’ll set the internal @partition_key value When called without an argument just retun it. class Comment < DynamodbModel::Item
partition_key "post_id"
end
261 262 263 264 265 266 267 268 |
# File 'lib/dynamodb_model/item.rb', line 261 def self.partition_key(*args) case args.size when 0 @partition_key || "id" # defaults to id when 1 @partition_key = args[0].to_s end end |
.query(params = {}) ⇒ Object
Adds very little wrapper logic to query.
-
Automatically add table_name to options for convenience.
-
Decorates return value. Returns Array of [MyModel.new] instead of the dynamodb client response.
Other than that, usage is same was using the dynamodb client query method directly. Example:
MyModel.query(
index_name: 'category-index',
expression_attribute_names: { "#category_name" => "category" },
expression_attribute_values: { ":category_value" => "Entertainment" },
key_condition_expression: "#category_name = :category_value",
)
AWS Docs examples: docs.aws.amazon.com/amazondynamodb/latest/developerguide/GettingStarted.Ruby.04.html
146 147 148 149 150 |
# File 'lib/dynamodb_model/item.rb', line 146 def self.query(params={}) params = { table_name: table_name }.merge(params) resp = db.query(params) resp.items.map {|i| self.new(i) } end |
.replace(attrs) ⇒ Object
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/dynamodb_model/item.rb', line 195 def self.replace(attrs) # Automatically adds some attributes: # partition key unique id # created_at and updated_at timestamps. Timestamp format from AWS docs: http://amzn.to/2z98Bdc defaults = { partition_key => Digest::SHA1.hexdigest([Time.now, rand].join) } item = defaults.merge(attrs) item["created_at"] ||= Time.now.utc.strftime('%Y-%m-%dT%TZ') item["updated_at"] = Time.now.utc.strftime('%Y-%m-%dT%TZ') # put_item full replaces the item resp = db.put_item( table_name: table_name, item: item ) # The resp does not contain the attrs. So might as well return # the original item with the generated partition_key value item end |
.scan(params = {}) ⇒ Object
Adds very little wrapper logic to scan.
-
Automatically add table_name to options for convenience.
-
Decorates return value. Returns Array of [MyModel.new] instead of the dynamodb client response.
Other than that, usage is same was using the dynamodb client scan method directly. Example:
MyModel.scan(
expression_attribute_names: {"#updated_at"=>"updated_at"},
filter_expression: "#updated_at between :start_time and :end_time",
expression_attribute_values: {
":start_time" => "2010-01-01T00:00:00",
":end_time" => "2020-01-01T00:00:00"
}
)
AWS Docs examples: docs.aws.amazon.com/amazondynamodb/latest/developerguide/GettingStarted.Ruby.04.html
122 123 124 125 126 127 |
# File 'lib/dynamodb_model/item.rb', line 122 def self.scan(params={}) puts("It's recommended to not use scan for production. It can be slow and expensive. You can a LSI or GSI and query the index instead.") params = { table_name: table_name }.merge(params) resp = db.scan(params) resp.items.map {|i| self.new(i) } end |
.set_table_name(value) ⇒ Object
284 285 286 |
# File 'lib/dynamodb_model/item.rb', line 284 def self.set_table_name(value) @table_name = value end |
.table_name(*args) ⇒ Object
270 271 272 273 274 275 276 277 |
# File 'lib/dynamodb_model/item.rb', line 270 def self.table_name(*args) case args.size when 0 get_table_name when 1 set_table_name(args[0]) end end |
.where(attributes, options = {}) ⇒ Object
Translates simple query searches:
Post.where({category: "Drama"}, index_name: "category-index")
translates to
resp = db.query(
table_name: "demo-dev-post",
index_name: 'category-index',
expression_attribute_names: { "#category_name" => "category" },
expression_attribute_values: { ":category_value" => category },
key_condition_expression: "#category_name = :category_value",
)
TODO: Implement nicer where syntax with index_name as a chained method.
Post.where({category: "Drama"}, {index_name: "category-index"})
VS
Post.where(category: "Drama").index_name("category-index")
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/dynamodb_model/item.rb', line 171 def self.where(attributes, ={}) raise "attributes.size == 1 only supported for now" if attributes.size != 1 attr_name = attributes.keys.first attr_value = attributes[attr_name] # params = { # expression_attribute_names: { "#category_name" => "category" }, # expression_attribute_values: { ":category_value" => "Entertainment" }, # key_condition_expression: "#category_name = :category_value", # } name_key, value_key = "##{attr_name}_name", ":#{attr_name}_value" params = { expression_attribute_names: { name_key => attr_name }, expression_attribute_values: { value_key => attr_value }, key_condition_expression: "#{name_key} = #{value_key}", } # Allow direct access to override params passed to dynamodb query options. # This is is how index_name is passed: params = params.merge() query(params) end |
Instance Method Details
#attributes ⇒ Object
99 100 101 |
# File 'lib/dynamodb_model/item.rb', line 99 def attributes @attributes end |
#attributes=(attributes) ⇒ Object
Longer hand methods for completeness. Internallly encourage the shorter attrs method.
95 96 97 |
# File 'lib/dynamodb_model/item.rb', line 95 def attributes=(attributes) @attributes = attributes end |
#attrs(*args) ⇒ Object
Defining our own reader so we can do a deep merge if user passes in attrs
47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/dynamodb_model/item.rb', line 47 def attrs(*args) case args.size when 0 ActiveSupport::HashWithIndifferentAccess.new(@attrs) when 1 attributes = args[0] # Hash if attributes.empty? ActiveSupport::HashWithIndifferentAccess.new else @attrs = attrs.deep_merge!(attributes) end end end |
#delete ⇒ Object
77 78 79 |
# File 'lib/dynamodb_model/item.rb', line 77 def delete self.class.delete(@attrs[:id]) if @attrs[:id] end |
#find(id) ⇒ Object
73 74 75 |
# File 'lib/dynamodb_model/item.rb', line 73 def find(id) self.class.find(id) end |
#partition_key ⇒ Object
85 86 87 |
# File 'lib/dynamodb_model/item.rb', line 85 def partition_key self.class.partition_key end |
#replace ⇒ Object
The method is named replace to clearly indicate that the item is fully replaced.
68 69 70 71 |
# File 'lib/dynamodb_model/item.rb', line 68 def replace attrs = self.class.replace(@attrs) @attrs = attrs # refresh attrs because it now has the id end |
#table_name ⇒ Object
81 82 83 |
# File 'lib/dynamodb_model/item.rb', line 81 def table_name self.class.table_name end |
#to_attrs ⇒ Object
89 90 91 |
# File 'lib/dynamodb_model/item.rb', line 89 def to_attrs @attrs end |