Module: ActiveMocker::Queries
Defined Under Namespace
Classes: Find, WhereNotChain
Instance Method Summary collapse
- #all ⇒ Object
-
#average(key) ⇒ Object
Calculates the average value on a given column.
-
#count(column_name = nil) ⇒ Object
Count the records.
-
#delete_all(conditions = nil) ⇒ Object
(also: #destroy_all)
Deletes the records matching
conditionsby instantiating each record and calling itsdeletemethod. -
#find(ids) ⇒ Object
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]).
-
#find_by(conditions = {}) ⇒ Object
Finds the first record matching the specified conditions.
-
#find_by!(conditions = {}) ⇒ Object
Like
find_by, except that if no record is found, raises anActiveMocker::RecordNotFounderror. -
#find_or_create_by(attributes, &block) ⇒ Object
(also: #find_or_create_by!)
Finds the first record with the given attributes, or creates a record with the attributes if one is not found:.
-
#find_or_initialize_by(attributes, &block) ⇒ Object
Like
find_or_create_by, but callsnewinstead ofcreate. -
#first_or_create(attributes = nil, &block) ⇒ Object
:nodoc:.
-
#first_or_create!(attributes = nil, &block) ⇒ Object
:nodoc:.
-
#first_or_initialize(attributes = nil, &block) ⇒ Object
:nodoc:.
-
#limit(num) ⇒ Object
Specifies a limit for the number of records to retrieve.
-
#maximum(key) ⇒ Object
Calculates the maximum value on a given column.
-
#minimum(key) ⇒ Object
Calculates the minimum value on a given column.
-
#none ⇒ Object
Returns a chainable relation with zero records.
-
#order(key) ⇒ Object
Allows to specify an order attribute:.
-
#reverse_order ⇒ Object
Reverse the existing order clause on the relation.
-
#sum(key) ⇒ Object
Calculates the sum of values on a given column.
-
#update(id, attributes) ⇒ Object
Updates an object (or multiple objects) and saves it.
-
#update_all(attributes) ⇒ Object
Updates all records with details given if they match a set of conditions supplied, limits and order can also be supplied.
-
#where(conditions = nil) ⇒ Object
Returns a new relation, which is the result of filtering the current relation according to the conditions in the arguments.
Instance Method Details
#all ⇒ Object
325 326 327 |
# File 'lib/active_mocker/mock/queries.rb', line 325 def all __new_relation__(to_a || []) end |
#average(key) ⇒ Object
Calculates the average value on a given column. Returns nil if there’s no row.
PersonMock.average(:age) # => 35.8
287 288 289 290 291 |
# File 'lib/active_mocker/mock/queries.rb', line 287 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) ⇒ Object
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
258 259 260 261 |
# File 'lib/active_mocker/mock/queries.rb', line 258 def count(column_name = nil) return all.size if column_name.nil? where.not(column_name => nil).size end |
#delete_all(conditions = nil) ⇒ Object Also known as: destroy_all
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
60 61 62 63 64 65 |
# File 'lib/active_mocker/mock/queries.rb', line 60 def delete_all(conditions = nil) check_for_limit_scope! collection = conditions.nil? ? to_a.each(&:delete).clear : where(conditions) collection.map(&:delete).count end |
#find(ids) ⇒ Object
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.
128 129 130 131 132 133 134 135 |
# File 'lib/active_mocker/mock/queries.rb', line 128 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 = {}) ⇒ Object
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
190 191 192 193 194 |
# File 'lib/active_mocker/mock/queries.rb', line 190 def find_by(conditions = {}) to_a.detect do |record| Find.new(record).is_of(conditions) end end |
#find_by!(conditions = {}) ⇒ Object
Like find_by, except that if no record is found, raises an ActiveMocker::RecordNotFound error.
198 199 200 201 202 203 204 |
# File 'lib/active_mocker/mock/queries.rb', line 198 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) ⇒ Object Also known as: find_or_create_by!
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">
228 229 230 |
# File 'lib/active_mocker/mock/queries.rb', line 228 def find_or_create_by(attributes, &block) find_by(attributes) || create(attributes, &block) end |
#find_or_initialize_by(attributes, &block) ⇒ Object
Like find_or_create_by, but calls new instead of create.
235 236 237 |
# File 'lib/active_mocker/mock/queries.rb', line 235 def find_or_initialize_by(attributes, &block) find_by(attributes) || new(attributes, &block) end |
#first_or_create(attributes = nil, &block) ⇒ Object
:nodoc:
239 240 241 |
# File 'lib/active_mocker/mock/queries.rb', line 239 def first_or_create(attributes = nil, &block) # :nodoc: first || create(attributes, &block) end |
#first_or_create!(attributes = nil, &block) ⇒ Object
:nodoc:
243 244 245 |
# File 'lib/active_mocker/mock/queries.rb', line 243 def first_or_create!(attributes = nil, &block) # :nodoc: first || create!(attributes, &block) end |
#first_or_initialize(attributes = nil, &block) ⇒ Object
:nodoc:
247 248 249 |
# File 'lib/active_mocker/mock/queries.rb', line 247 def first_or_initialize(attributes = nil, &block) # :nodoc: first || new(attributes, &block) end |
#limit(num) ⇒ Object
Specifies a limit for the number of records to retrieve.
User.limit(10)
266 267 268 269 270 |
# File 'lib/active_mocker/mock/queries.rb', line 266 def limit(num) relation = __new_relation__(all.take(num)) relation.send(:set_from_limit) relation end |
#maximum(key) ⇒ Object
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
305 306 307 |
# File 'lib/active_mocker/mock/queries.rb', line 305 def maximum(key) values_by_key(key).max_by { |i| i } end |
#minimum(key) ⇒ Object
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
297 298 299 |
# File 'lib/active_mocker/mock/queries.rb', line 297 def minimum(key) values_by_key(key).min_by { |i| i } end |
#none ⇒ Object
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
353 354 355 |
# File 'lib/active_mocker/mock/queries.rb', line 353 def none __new_relation__([]) end |
#order(key) ⇒ Object
Allows to specify an order attribute:
User.order('name')
User.order(:name)
314 315 316 |
# File 'lib/active_mocker/mock/queries.rb', line 314 def order(key) __new_relation__(all.sort_by { |item| item.send(key) }) end |
#reverse_order ⇒ Object
Reverse the existing order clause on the relation.
User.order('name').reverse_order
321 322 323 |
# File 'lib/active_mocker/mock/queries.rb', line 321 def reverse_order __new_relation__(to_a.reverse) end |
#sum(key) ⇒ Object
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
276 277 278 279 280 281 |
# File 'lib/active_mocker/mock/queries.rb', line 276 def sum(key) values = values_by_key(key) values.inject(0) do |sum, n| sum + (n || 0) end end |
#update(id, attributes) ⇒ Object
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)
173 174 175 176 177 178 179 180 181 |
# File 'lib/active_mocker/mock/queries.rb', line 173 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) ⇒ Object
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')
154 155 156 |
# File 'lib/active_mocker/mock/queries.rb', line 154 def update_all(attributes) all.each { |i| i.update(attributes) } end |
#where(conditions = nil) ⇒ Object
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: "[email protected]" })
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.find(1)
# The following queries will be equivalent:
Post.where(author: )
Post.where(author_id: )
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.
111 112 113 114 115 116 |
# File 'lib/active_mocker/mock/queries.rb', line 111 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 |