Created
December 29, 2009 13:18
-
-
Save lifo/265308 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# [] - 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