Module: Dynamoid::Adapter::Local

Extended by:
Local
Included in:
Local
Defined in:
lib/dynamoid/adapter/local.rb

Overview

This gimpy hash construct should be equivalent to Amazon's actual DynamoDB, for offline development. All tests pass with either this or connecting to the real DynamoDB, and that's good enough for me.

Instance Method Summary (collapse)

Instance Method Details

- (Hash) batch_get_item(options)

Get many items at once from the hash.

Examples:

Retrieve IDs 1 and 2 from the table testtable

Dynamoid::Adapter::Local.batch_get_item('table1' => ['1', '2'])

Parameters:

  • options (Hash)

    the hash of tables and IDs to retrieve

Returns:

  • (Hash)

    a hash where keys are the table names and the values are the retrieved items

Since:

  • 0.2.0



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/dynamoid/adapter/local.rb', line 35

def batch_get_item(options)
  Hash.new { |h, k| h[k] = Array.new }.tap do |hash|
    options.each do |table_name, keys|
      table = data[table_name]
      if table[:range_key]
        Array(keys).each do |hash_key, range_key|
          hash[table_name] << get_item(table_name, hash_key, :range_key => range_key)
        end
      else
        Array(keys).each do |key|
          hash[table_name] << get_item(table_name, key)
        end
      end
    end
  end
end

- (Object) create_table(table_name, key, options = {})

Create a table.

Parameters:

  • table_name (String)

    the name of the table to create

  • key (Symbol)

    the table's primary key (defaults to :id)

  • options (Hash) (defaults to: {})

    provide a range_key here if you want one for the table

Since:

  • 0.2.0



59
60
61
62
# File 'lib/dynamoid/adapter/local.rb', line 59

def create_table(table_name, key, options = {})
  range_key = options[:range_key] && options[:range_key].keys.first
  data[table_name] = {:hash_key => key, :range_key => range_key, :data => {}}
end

- (Hash) data

The hash holding all of our data.

Returns:

  • (Hash)

    a hash of raw values

Since:

  • 0.2.0



14
15
16
# File 'lib/dynamoid/adapter/local.rb', line 14

def data
  @data ||= {}
end

- (Object) delete_item(table_name, key, options = {})

Removes an item from the hash.

Parameters:

  • table_name (String)

    the name of the table

  • key (String)

    the hash key of the item to delete

  • range_key (Number)

    the range key of the item to delete, required if the table has a composite key

Since:

  • 0.2.0



71
72
73
74
# File 'lib/dynamoid/adapter/local.rb', line 71

def delete_item(table_name, key, options = {})
  range_key = options.delete(:range_key)
  data[table_name][:data].delete("#{key}.#{range_key}")
end

- (Object) delete_table(table_name)

Deletes an entire table from the hash.

Parameters:

  • table_name (String)

    the name of the table to destroy

Since:

  • 0.2.0



81
82
83
# File 'lib/dynamoid/adapter/local.rb', line 81

def delete_table(table_name)
  data.delete(table_name)
end

- (Object) drop_till_start(results, next_token, range_key, hash_key)



180
181
182
183
184
185
186
187
188
189
# File 'lib/dynamoid/adapter/local.rb', line 180

def drop_till_start(results, next_token, range_key, hash_key)
  return results unless next_token

  hash_value = next_token[:hash_key_element].values.first
  range_value = next_token[:range_key_element].values.first if next_token[:range_key_element]

  results = results.drop_while do |r|
    (r[hash_key] != hash_value or r[range_key] != range_value)
  end.drop(1)
end

- (Hash) get_item(table_name, key, options = {})

Fetches an item from the hash.

Parameters:

  • table_name (String)

    the name of the table

  • key (String)

    the hash key of the item to find

  • range_key (Number)

    the range key of the item to find, required if the table has a composite key

Returns:

  • (Hash)

    a hash representing the raw item

Since:

  • 0.2.0



96
97
98
99
100
101
102
103
# File 'lib/dynamoid/adapter/local.rb', line 96

def get_item(table_name, key, options = {})
  range_key = options[:range_key]
  if data[table_name][:data]
    data[table_name][:data]["#{key}.#{range_key}"]
  else
    nil
  end
end

- (Object) list_tables

List all tables on DynamoDB.

Since:

  • 0.2.0



108
109
110
# File 'lib/dynamoid/adapter/local.rb', line 108

def list_tables
  data.keys
end

- (Object) put_item(table_name, object)

Persists an item in the hash.

Parameters:

  • table_name (String)

    the name of the table

  • object (Object)

    a hash or Dynamoid object to persist

Since:

  • 0.2.0



118
119
120
121
122
123
124
# File 'lib/dynamoid/adapter/local.rb', line 118

def put_item(table_name, object)
  table = data[table_name]
  table[:data][object[table[:hash_key]]]
  table[:data]["#{object[table[:hash_key]]}.#{object[table[:range_key]]}"] = object.delete_if{|k, v| v.nil? || (v.respond_to?(:empty?) && v.empty?)}
rescue
  raise data.inspect
end

- (Array) query(table_name, opts = {})

Query the hash.

Parameters:

  • table_name (String)

    the name of the table

  • opts (Hash) (defaults to: {})

    the options to query the table with

Options Hash (opts):

  • :hash_value (String)

    the value of the hash key to find

  • :range_value (Range)

    find the range key within this range

  • :range_greater_than (Number)

    find range keys greater than this

  • :range_less_than (Number)

    find range keys less than this

  • :range_gte (Number)

    find range keys greater than or equal to this

  • :range_lte (Number)

    find range keys less than or equal to this

Returns:

  • (Array)

    an array of all matching items

Since:

  • 0.2.0



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/dynamoid/adapter/local.rb', line 140

def query(table_name, opts = {})
  id = opts[:hash_value]
  hash_key = data[table_name][:hash_key]
  range_key = data[table_name][:range_key]

  results = if opts[:range_value]
    data[table_name][:data].values.find_all{|v| v[hash_key] == id && !v[range_key].nil? && opts[:range_value].include?(v[range_key])}
  elsif opts[:range_greater_than]
    data[table_name][:data].values.find_all{|v| v[hash_key] == id && !v[range_key].nil? && v[range_key] > opts[:range_greater_than]}
  elsif opts[:range_less_than]
    data[table_name][:data].values.find_all{|v| v[hash_key] == id && !v[range_key].nil? && v[range_key] < opts[:range_less_than]}
  elsif opts[:range_gte]
    data[table_name][:data].values.find_all{|v| v[hash_key] == id && !v[range_key].nil? && v[range_key] >= opts[:range_gte]}
  elsif opts[:range_lte]  
    data[table_name][:data].values.find_all{|v| v[hash_key] == id && !v[range_key].nil? && v[range_key] <= opts[:range_lte]}
  else
    data[table_name][:data].values.find_all{|v| v[hash_key] == id}
  end

  results = drop_till_start(results, opts[:next_token], range_key, hash_key)
  results = results.take(opts[:limit]) if opts[:limit]
  results
end

- (Object) reset_data

A convenience method for testing that destroys all table data without destroying their structure.

Since:

  • 0.2.0



21
22
23
# File 'lib/dynamoid/adapter/local.rb', line 21

def reset_data
  self.data.each {|k, v| v[:data] = {}}
end

- (Array) scan(table_name, scan_hash, opts = {})

Scan the hash.

Parameters:

  • table_name (String)

    the name of the table

  • scan_hash (Hash)

    a hash of attributes: matching records will be returned by the scan

Returns:

  • (Array)

    an array of all matching items

Since:

  • 0.2.0



172
173
174
175
176
177
178
# File 'lib/dynamoid/adapter/local.rb', line 172

def scan(table_name, scan_hash, opts = {})
  return [] if data[table_name].nil?
  results = data[table_name][:data].values.flatten.select{|d| scan_hash.all?{|k, v| !d[k].nil? && d[k] == v}}
  results = drop_till_start(results, opts[:next_token], data[table_name][:range_key], data[table_name][:hash_key])
  results = results.take(opts[:limit]) if opts[:limit]
  results
end