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