module ActiveMocker::Queries

Public Instance Methods

all() click to toggle source
# File lib/active_mocker/mock/queries.rb, line 369
def all
  __new_relation__(to_a || [])
end
average(key) click to toggle source

Calculates the average value on a given column. Returns nil if there's no row.

PersonMock.average(:age) # => 35.8
# File lib/active_mocker/mock/queries.rb, line 289
def average(key)
  values = values_by_key(key)
  total  = values.inject { |sum, n| sum + n }
  BigDecimal.new(total) / BigDecimal.new(values.count)
end
count(column_name = nil) click to toggle source

Count the records.

PersonMock.count
# => the total count of all people

PersonMock.count(:age)
# => returns the total count of all people whose age is present in database
# File lib/active_mocker/mock/queries.rb, line 260
def count(column_name = nil)
  return all.size if column_name.nil?
  where.not(column_name => nil).size
end
delete_all(conditions = nil) click to toggle source

Deletes the records matching conditions by instantiating each record and calling its delete method.

Parameters

  • conditions - A string, array, or hash that specifies which records to destroy. If omitted, all records are destroyed.

Examples

PersonMock.destroy_all(status: "inactive")
PersonMock.where(age: 0..18).destroy_all

If a limit scope is supplied, delete_all raises an ActiveMocker error:

Post.limit(100).delete_all
# => ActiveMocker::Error: delete_all doesn't support limit scope
# File lib/active_mocker/mock/queries.rb, line 62
def delete_all(conditions = nil)
  check_for_limit_scope!

  collection = conditions.nil? ? to_a.each(&:delete).clear : where(conditions)
  collection.map(&:delete).count
end
Also aliased as: destroy_all
destroy_all(conditions = nil)
Alias for: delete_all
find(ids) click to toggle source

Find by id - This can either be a specific id (1), a list of ids (1, 5, 6), or an array of ids ([5, 6, 10]). If no record can be found for all of the listed ids, then RecordNotFound will be raised. If the primary key is an integer, find by id coerces its arguments using to_i.

Person.find(1)          # returns the object for ID = 1
Person.find(1, 2, 6)    # returns an array for objects with IDs in (1, 2, 6)
Person.find([7, 17])    # returns an array for objects with IDs in (7, 17)
Person.find([1])        # returns an array for the object with ID = 1

ActiveMocker::RecordNotFound will be raised if one or more ids are not found.

# File lib/active_mocker/mock/queries.rb, line 130
def find(ids)
  raise RecordNotFound.new("Couldn't find #{name} without an ID") if ids.nil?
  results = [*ids].map do |id|
    find_by!(id: id.to_i)
  end
  return __new_relation__(results) if ids.class == Array
  results.first
end
find_by(conditions = {}) click to toggle source

Finds the first record matching the specified conditions. There is no implied ordering so if order matters, you should specify it yourself.

If no record is found, returns nil.

Post.find_by name: 'Spartacus', rating: 4
# File lib/active_mocker/mock/queries.rb, line 192
def find_by(conditions = {})
  to_a.detect do |record|
    Find.new(record).is_of(conditions)
  end
end
find_by!(conditions = {}) click to toggle source

Like find_by, except that if no record is found, raises an ActiveMocker::RecordNotFound error.

# File lib/active_mocker/mock/queries.rb, line 200
def find_by!(conditions = {})
  result = find_by(conditions)
  if result.nil?
    raise RecordNotFound.new("Couldn't find #{name} with '#{conditions.keys.first}'=#{conditions.values.first}")
  end
  result
end
find_or_create_by(attributes, &block) click to toggle source

Finds the first record with the given attributes, or creates a record with the attributes if one is not found:

# Find the first user named "Penélope" or create a new one.
UserMock.find_or_create_by(first_name: 'Penélope')
# => #<User id: 1, first_name: "Penélope", last_name: nil>

# Find the first user named "Penélope" or create a new one.
# We already have one so the existing record will be returned.
UserMock.find_or_create_by(first_name: 'Penélope')
# => #<User id: 1, first_name: "Penélope", last_name: nil>

This method accepts a block, which is passed down to create. The last example above can be alternatively written this way:

# Find the first user named "Scarlett" or create a new one with a
# different last name.
User.find_or_create_by(first_name: 'Scarlett') do |user|
  user.last_name = 'Johansson'
end
# => #<User id: 2, first_name: "Scarlett", last_name: "Johansson">
# File lib/active_mocker/mock/queries.rb, line 230
def find_or_create_by(attributes, &block)
  find_by(attributes) || create(attributes, &block)
end
Also aliased as: find_or_create_by!
find_or_create_by!(attributes, &block)
Alias for: find_or_create_by
find_or_initialize_by(attributes, &block) click to toggle source

Like find_or_create_by, but calls new instead of create.

# File lib/active_mocker/mock/queries.rb, line 237
def find_or_initialize_by(attributes, &block)
  find_by(attributes) || new(attributes, &block)
end
limit(num) click to toggle source

Specifies a limit for the number of records to retrieve.

User.limit(10)
# File lib/active_mocker/mock/queries.rb, line 268
def limit(num)
  relation = __new_relation__(all.take(num))
  relation.send(:set_from_limit)
  relation
end
maximum(key) click to toggle source

Calculates the maximum value on a given column. The value is returned with the same data type of the column, or nil if there's no row.

Person.maximum(:age) # => 93
# File lib/active_mocker/mock/queries.rb, line 307
def maximum(key)
  values_by_key(key).max_by { |i| i }
end
minimum(key) click to toggle source

Calculates the minimum value on a given column. The value is returned with the same data type of the column, or nil if there's no row.

Person.minimum(:age) # => 7
# File lib/active_mocker/mock/queries.rb, line 299
def minimum(key)
  values_by_key(key).min_by { |i| i }
end
none() click to toggle source

Returns a chainable relation with zero records.

Any subsequent condition chained to the returned relation will continue generating an empty relation.

Used in cases where a method or scope could return zero records but the result needs to be chainable.

For example:

@posts = current_user.visible_posts.where(name: params[:name])
# => the visible_posts method is expected to return a chainable Relation

def visible_posts
  case role
  when 'Country Manager'
    Post.where(country: country)
  when 'Reviewer'
    Post.published
  when 'Bad User'
    Post.none # It can't be chained if [] is returned.
  end
end
# File lib/active_mocker/mock/queries.rb, line 397
def none
  __new_relation__([])
end
order(*args) click to toggle source

Allows to specify an order attribute:

User.order('name')

User.order(:name)

User.order(email: :desc)

User.order(:name, email: :desc)
# File lib/active_mocker/mock/queries.rb, line 320
def order(*args)
  options = args.extract_options!
  if options.empty? && args.count == 1
    __new_relation__(all.sort_by { |item| item.send(args.first) })
  else
    __new_relation__(Sort.order_mixed_args(all, args, options))
  end
end
reverse_order() click to toggle source

Reverse the existing order clause on the relation.

User.order('name').reverse_order
# File lib/active_mocker/mock/queries.rb, line 365
def reverse_order
  __new_relation__(to_a.reverse)
end
sum(key) click to toggle source

Calculates the sum of values on a given column. The value is returned with the same data type of the column, 0 if there's no row.

Person.sum(:age) # => 4562
# File lib/active_mocker/mock/queries.rb, line 278
def sum(key)
  values = values_by_key(key)
  values.inject(0) do |sum, n|
    sum + (n || 0)
  end
end
update(id, attributes) click to toggle source

Updates an object (or multiple objects) and saves it.

Parameters

  • id - This should be the id or an array of ids to be updated.

  • attributes - This should be a hash of attributes or an array of hashes.

Examples

# Updates one record
Person.update(15, user_name: 'Samuel', group: 'expert')

# Updates multiple records
people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
Person.update(people.keys, people.values)
# File lib/active_mocker/mock/queries.rb, line 175
def update(id, attributes)
  if id.is_a?(Array)
    id.map.with_index { |one_id, idx| update(one_id, attributes[idx]) }
  else
    object = find(id)
    object.update(attributes)
    object
  end
end
update_all(attributes) click to toggle source

Updates all records with details given if they match a set of conditions supplied, limits and order can also be supplied.

Parameters

  • updates - A string, array, or hash.

Examples

# Update all customers with the given attributes
Customer.update_all wants_email: true

# Update all books with 'Rails' in their title
BookMock.where(title: 'Rails').update_all(author: 'David')

# Update all books that match conditions, but limit it to 5 ordered by date
BookMock.where(title: 'Rails').order(:created_at).limit(5).update_all(author: 'David')
# File lib/active_mocker/mock/queries.rb, line 156
def update_all(attributes)
  all.each { |i| i.update(attributes) }
end
where(conditions = nil) click to toggle source

Returns a new relation, which is the result of filtering the current relation according to the conditions in the arguments.

hash

where will accept a hash condition, in which the keys are fields and the values are values to be searched for.

Fields can be symbols or strings. Values can be single values, arrays, or ranges.

User.where({ name: "Joe", email: "joe@example.com" })

User.where({ name: ["Alice", "Bob"]})

User.where({ created_at: (Time.now.midnight - 1.day)..Time.now.midnight })

In the case of a belongs_to relationship, an association key can be used to specify the model if an ActiveRecord object is used as the value.

author = Author.find(1)

# The following queries will be equivalent:
Post.where(author: author)
Post.where(author_id: author)

This also works with polymorphic belongs_to relationships:

treasure = Treasure.create(name: 'gold coins')
treasure.price_estimates << PriceEstimate.create(price: 125)

# The following queries will be equivalent:
PriceEstimate.where(estimate_of: treasure)
PriceEstimate.where(estimate_of_type: 'Treasure', estimate_of_id: treasure)

no argument

If no argument is passed, where returns a new instance of WhereChain, that can be chained with not to return a new relation that negates the where clause.

User.where.not(name: "Jon")

See WhereChain for more details on not.

# File lib/active_mocker/mock/queries.rb, line 113
def where(conditions = nil)
  return WhereNotChain.new(all, method(:__new_relation__)) if conditions.nil?
  __new_relation__(to_a.select do |record|
    Find.new(record).is_of(conditions)
  end)
end

Private Instance Methods

__new_relation__(collection) click to toggle source
# File lib/active_mocker/mock/queries.rb, line 411
def __new_relation__(collection)
  duped            = dup
  duped.collection = collection
  duped
end
check_for_limit_scope!() click to toggle source
# File lib/active_mocker/mock/queries.rb, line 403
def check_for_limit_scope!
  raise ActiveMocker::Error.new("delete_all doesn't support limit scope") if from_limit?
end
values_by_key(key) click to toggle source
# File lib/active_mocker/mock/queries.rb, line 407
def values_by_key(key)
  all.map { |obj| obj.send(key) }
end