Module: Dynamoid::Finders::ClassMethods

Defined in:
lib/dynamoid/finders.rb

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args) ⇒ Dynamoid::Document/Array

Find using exciting method_missing finders attributes. Uses criteria chains under the hood to accomplish this neatness.

Examples:

find a user by a first name

User.find_by_first_name('Josh')

find all users by first and last name

User.find_all_by_first_name_and_last_name('Josh', 'Symonds')

Returns:

  • (Dynamoid::Document/Array)

    the found object, or an array of found objects if all was somewhere in the method

Since:

  • 0.2.0



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/dynamoid/finders.rb', line 177

def method_missing(method, *args)
  if method =~ /find/
    finder = method.to_s.split('_by_').first
    attributes = method.to_s.split('_by_').last.split('_and_')

    chain = Dynamoid::Criteria::Chain.new(self)
    chain.query = Hash.new.tap {|h| attributes.each_with_index {|attr, index| h[attr.to_sym] = args[index]}}

    if finder =~ /all/
      return chain.all
    else
      return chain.first
    end
  else
    super
  end
end

Instance Method Details

#find(*ids) ⇒ Dynamoid::Document

Find one or many objects, specified by one id or an array of ids.

Parameters:

  • *id (Array/String)

    an array of ids or one single id

Returns:

  • (Dynamoid::Document)

    one object or an array of objects, depending on whether the input was an array or not

Since:

  • 0.2.0



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/dynamoid/finders.rb', line 28

def find(*ids)
  options = if ids.last.is_a? Hash
              ids.slice!(-1)
            else
              {}
            end
  expects_array = ids.first.kind_of?(Array)

  ids = Array(ids.flatten.uniq)
  if ids.count == 1
    result = self.find_by_id(ids.first, options)
    expects_array ? Array(result) : result
  else
    find_all(ids)
  end
end

#find_all(ids, options = {}) ⇒ Object

Return objects found by the given array of ids, either hash keys, or hash/range key combinations using BatchGet. Returns empty array if no results found.

Examples:

find all the user with hash key
User.find_all(['1', '2', '3'])

find all the tweets using hash key and range key with consistent read
Tweet.find_all([['1', 'red'], ['1', 'green']], :consistent_read => true)

Parameters:

  • ids (Array<ID>)
  • options: (Hash)

    Passed to the underlying query.



57
58
59
60
# File 'lib/dynamoid/finders.rb', line 57

def find_all(ids, options = {})
  items = Dynamoid.adapter.read(self.table_name, ids, options)
  items ? items[self.table_name].map{|i| from_database(i)} : []
end

#find_all_by_composite_key(hash_key, options = {}) ⇒ Array

Find all objects by hash and range keys.

Examples:

find all ChamberTypes whose level is greater than 1

class ChamberType
  include Dynamoid::Document
  field :chamber_type,            :string
  range :level,                   :integer
  table :key => :chamber_type
end
ChamberType.find_all_by_composite_key('DustVault', range_greater_than: 1)

Parameters:

  • hash_key (String)

    of the objects to find

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

    the options for the range key

Options Hash (options):

  • :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



107
108
109
110
111
# File 'lib/dynamoid/finders.rb', line 107

def find_all_by_composite_key(hash_key, options = {})
  Dynamoid.adapter.query(self.table_name, options.merge({hash_value: hash_key})).collect do |item|
    from_database(item)
  end
end

#find_all_by_secondary_index(hash, options = {}) ⇒ Array

Find all objects by using local secondary or global secondary index

Examples:

class User
  include Dynamoid::Document
  field :email,          :string
  field :age,            :integer
  field :gender,         :string
  field :rank            :number
  table :key => :email
  global_secondary_index :hash_key => :age, :range_key => :gender
end
User.find_all_by_secondary_index(:age => 5, :range => {"rank.lte" => 10})

Parameters:

  • eg: (Hash)

    => 5

  • eg: (Hash)

    => 10

  • options (Hash) (defaults to: {})
    • @TODO support more options in future such as

    query filter, projected keys etc

Returns:

  • (Array)

    an array of all matching items

Raises:



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/dynamoid/finders.rb', line 132

def find_all_by_secondary_index(hash, options = {})
  range = options[:range] || {}
  hash_key_field, hash_key_value = hash.first
  range_key_field, range_key_value = range.first
  range_op_mapped = nil

  if range_key_field
    range_key_field = range_key_field.to_s
    range_key_op = "eq"
    if range_key_field.include?(".")
      range_key_field, range_key_op = range_key_field.split(".", 2)
    end
    range_op_mapped = RANGE_MAP.fetch(range_key_op)
  end

  # Find the index
  index = self.find_index(hash_key_field, range_key_field)
  raise Dynamoid::Errors::MissingIndex if index.nil?

  # query
  opts = {
    :hash_key => hash_key_field.to_s,
    :hash_value => hash_key_value,
    :index_name => index.name,
  }
  if range_key_field
    opts[:range_key] = range_key_field
    opts[range_op_mapped] = range_key_value
  end
  Dynamoid.adapter.query(self.table_name, opts).map do |item|
    from_database(item)
  end
end

#find_by_composite_key(hash_key, range_key, options = {}) ⇒ Object

Find one object directly by hash and range keys

Parameters:

  • hash_key (String)

    of the object to find

  • range_key (String/Number)

    of the object to find



82
83
84
# File 'lib/dynamoid/finders.rb', line 82

def find_by_composite_key(hash_key, range_key, options = {})
  find_by_id(hash_key, options.merge({:range_key => range_key}))
end

#find_by_id(id, options = {}) ⇒ Dynamoid::Document

Find one object directly by id.

Parameters:

  • id (String)

    the id of the object to find

Returns:

Since:

  • 0.2.0



69
70
71
72
73
74
75
# File 'lib/dynamoid/finders.rb', line 69

def find_by_id(id, options = {})
  if item = Dynamoid.adapter.read(self.table_name, id, options)
    from_database(item)
  else
    nil
  end
end