Skip to content

Instantly share code, notes, and snippets.

@lifo
Created December 29, 2009 13:18
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save lifo/265308 to your computer and use it in GitHub Desktop.
Save lifo/265308 to your computer and use it in GitHub Desktop.
# [] - Eqauls to
# ^ - Not equals to
# =~ - LIKE
# >, >=, <, <= works as expected
#
# Examples :
#
# Item.where(:colour['Red'], :quanity > 10, :price <= 200)
# Post.where(:comments_count >= 1, :taggings_count < 5)
# User.where(:country ^ 'US') # Non american users
# User.where(:age > 18, :age <= 60)
# Comment.where(:body =~ "%p0rn%")
require "cases/helper"
require 'models/tag'
require 'models/tagging'
require 'models/post'
require 'models/topic'
require 'models/comment'
require 'models/reply'
require 'models/author'
require 'models/comment'
require 'models/entrant'
require 'models/developer'
require 'models/company'
class SuperCondition
attr_reader :operation, :value, :column
def self.[](column, value, operation)
SuperCondition.new(column, value, operation)
end
def initialize(column, value, operation)
@column = column.to_s
@value = value
@operation = operation
end
end
class Symbol
def [](value)
SuperCondition[self, value, :eq]
end
def ^(value)
SuperCondition[self, value, :neq]
end
def =~(value)
SuperCondition[self, value, :like]
end
def >(value)
SuperCondition[self, value, :gt]
end
def >=(value)
SuperCondition[self, value, :gte]
end
def <(value)
SuperCondition[self, value, :lt]
end
def <=(value)
SuperCondition[self, value, :lte]
end
end
module SuperWhere
extend ActiveSupport::Concern
included do
alias_method_chain :where, :power
end
def where_with_power(*args)
if Array.wrap(args).all? {|x| x.kind_of?(SuperCondition) }
conditions = []
args.each do |super_condition|
if super_condition.column.include?('.')
table, column = attr.split('.', 2)
table = @klass.connection.quote_table_name(table)
else
table, column = @klass.table_name, super_condition.column
end
quoted_column_name = "#{table}.#{@klass.connection.quote_column_name(column)}"
value = super_condition.value
clause = case super_condition.operation
when :eq
@klass.send(:attribute_condition, quoted_column_name, value)
when :neq
"#{quoted_column_name} <> ?"
when :like
"#{quoted_column_name} LIKE ?"
when :gt
"#{quoted_column_name} > ?"
when :gte
"#{quoted_column_name} >= ?"
when :lt
"#{quoted_column_name} < ?"
when :lte
"#{quoted_column_name} <= ?"
end
conditions << replace_bind_variable(clause, value)
end
relation = spawn
conditions.each {|c| relation = relation.where(c) }
relation
else
where_without_power(*args)
end
end
private
def replace_bind_variable(clause, value)
@klass.send(:replace_bind_variables, clause, [value])
end
end
class ActiveRecord::Relation
include SuperWhere
end
class SuperRelationsTest < ActiveRecord::TestCase
fixtures :authors, :topics, :entrants, :developers, :companies, :developers_projects, :accounts, :categories, :categorizations, :posts, :comments,
:taggings
def test_sanity
assert_equal ["David"], Author.where(:name => 'David').map(&:name)
assert_equal ['Mary'], Author.where(["name = ?", 'Mary']).map(&:name)
assert_equal ['Mary'], Author.where("name = ?", 'Mary').map(&:name)
end
def test_super
assert_equal authors(:david), Author.where(:name['David'], :author_address_id > 0).first
assert_equal authors(:david), Author.where(:name ^ 'Mary').first
assert_equal [posts(:welcome)], Post.where(:comments_count <= 5, :comments_count > 1).all
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment