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
# >, >=, <, <= 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
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
def self.[](column, value, operation)
SuperCondition.new(column, value, operation)
end
def initialize(column, value, operation)
@column = column
@value = value
@operation = operation
end
def column
@column.to_s
end
end
class Symbol
def *(value)
SuperCondition[self, value, :eq]
end
def /(value)
SuperCondition[self, value, :neq]
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
conditions << case super_condition.operation
when :eq
where_clause = @klass.send(:attribute_condition, quoted_column_name, value)
replace_bind_variable(where_clause, value)
when :neq
replace_bind_variable("#{quoted_column_name} <> ?", value)
when :gt
replace_bind_variable("#{quoted_column_name} > ?", value)
when :gte
replace_bind_variable("#{quoted_column_name} >= ?", value)
when :lt
replace_bind_variable("#{quoted_column_name} < ?", value)
when :lte
replace_bind_variable("#{quoted_column_name} <= ?", value)
end
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
puts Author.where(:name * 'David', :author_address_id > 2).to_sql
puts Post.where(:comments_count >= 1, :taggings_count < 5).to_sql
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment