lib/lotus/model/adapters/memory/query.rb in lotus-model-0.1.2 vs lib/lotus/model/adapters/memory/query.rb in lotus-model-0.2.0
- old
+ new
@@ -98,17 +98,47 @@
#
# query.where(language: 'ruby')
# .where(framework: 'lotus')
def where(condition)
column, value = _expand_condition(condition)
- conditions.push(Proc.new{ find_all{|r| r.fetch(column) == value} })
+ conditions.push([:where, Proc.new{ find_all{|r| r.fetch(column) == value} }])
self
end
alias_method :and, :where
- alias_method :or, :where
+ # Adds a condition that behaves like SQL `OR`.
+ #
+ # It accepts a `Hash` with only one pair.
+ # The key must be the name of the column expressed as a `Symbol`.
+ # The value is the one used by the SQL query
+ #
+ # This condition will be ignored if not used with WHERE.
+ #
+ # @param condition [Hash]
+ #
+ # @return self
+ #
+ # @since 0.1.0
+ #
+ # @example Fixed value
+ #
+ # query.where(language: 'ruby').or(framework: 'lotus')
+ #
+ # @example Array
+ #
+ # query.where(id: 1).or(author_id: [15, 23])
+ #
+ # @example Range
+ #
+ # query.where(country: 'italy').or(year: 1900..1982)
+ def or(condition=nil, &blk)
+ column, value = _expand_condition(condition)
+ conditions.push([:or, Proc.new{ find_all{|r| r.fetch(column) == value} }])
+ self
+ end
+
# Logical negation of a #where condition.
#
# It accepts a `Hash` with only one pair.
# The key must be the name of the column expressed as a `Symbol`.
# The value is the one used by the internal filtering logic.
@@ -135,11 +165,11 @@
#
# query.exclude(language: 'java')
# .exclude(company: 'enterprise')
def exclude(condition)
column, value = _expand_condition(condition)
- conditions.push(Proc.new{ reject! {|r| r.fetch(column) == value} })
+ conditions.push([:where, Proc.new{ reject {|r| r.fetch(column) == value} }])
self
end
alias_method :not, :exclude
@@ -159,11 +189,11 @@
#
# @example Multiple columns
#
# query.select(:name, :year)
def select(*columns)
- columns = Lotus::Utils::Kernel.Array(columns).uniq
+ columns = Lotus::Utils::Kernel.Array(columns)
modifiers.push(Proc.new{ flatten!; each {|r| r.delete_if {|k,_| !columns.include?(k)} } })
end
# Specify the ascending order of the records, sorted by the given
# columns.
@@ -187,11 +217,11 @@
# @example Multiple invokations
#
# query.order(:name).order(:year)
def order(*columns)
Lotus::Utils::Kernel.Array(columns).each do |column|
- conditions.push(Proc.new{ sort_by{|r| r.fetch(column)} })
+ modifiers.push(Proc.new{ sort_by!{|r| r.fetch(column)} })
end
self
end
@@ -219,11 +249,11 @@
# @example Multiple invokations
#
# query.desc(:name).desc(:year)
def desc(*columns)
Lotus::Utils::Kernel.Array(columns).each do |column|
- conditions.push(Proc.new{ sort_by{|r| r.fetch(column)}.reverse })
+ modifiers.push(Proc.new{ sort_by!{|r| r.fetch(column)}.reverse! })
end
self
end
@@ -253,11 +283,11 @@
#
# @example
#
# query.offset(10)
def offset(number)
- modifiers.unshift(Proc.new{ replace(flatten.last(number)) })
+ modifiers.unshift(Proc.new{ replace(flatten.drop(number)) })
self
end
# Returns the sum of the values for the given column.
#
@@ -430,12 +460,21 @@
# @api private
# @since 0.1.0
def run
result = @dataset.all.dup
- result = conditions.map do |condition|
- result.instance_exec(&condition)
- end if conditions.any?
+ if conditions.any?
+ prev_result = nil
+ conditions.each do |(type, condition)|
+ case type
+ when :where
+ prev_result = result
+ result = prev_result.instance_exec(&condition)
+ when :or
+ result |= prev_result.instance_exec(&condition)
+ end
+ end
+ end
modifiers.map do |modifier|
result.instance_exec(&modifier)
end