ryana-inequal_opportunity 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README ADDED
@@ -0,0 +1,36 @@
1
+ = Inequal Opportunity
2
+
3
+ ActiveRecord is a ruby ORM released with Ruby on Rails. It has a hash syntax
4
+ for specifying SQL conditions:
5
+
6
+ YourModel.count(:conditions => {:id => 5})
7
+ YourModel.all(:limit => 5, :order => :created_at, :conditions => {:user_id => 5})
8
+
9
+ But this hash format lacks inequalities. In order to generate:
10
+
11
+ SELECT * from your_models where id <> '42';
12
+
13
+ You have to write:
14
+
15
+ YourModel.count(:conditions => ['id <> ?', 42])
16
+
17
+ With Inequal Opportunity, you can write:
18
+
19
+ YourModel.count(:conditions => {:id => ne(42)})
20
+
21
+ Where Object#ne wraps 42 in a ActiveRecord::Inequality::NotEqual class,
22
+ which is then used to insert the proper operator into the generated SQL.
23
+
24
+ Test coverage is real sparse right now. I also am not completely satisfied with
25
+ the way I overwrite ActiveRecord.expand_range_bind_variables, but it works for now.
26
+
27
+
28
+ == License
29
+
30
+ Inequal Opportunity is released under the MIT license.
31
+
32
+
33
+ == Support
34
+
35
+ Just email me at ryan@angilly.com with questions, bugs,
36
+ or patches
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gemspec|
4
+ gemspec.name = "inequal_opportunity"
5
+ gemspec.summary = "Adds mergable, stackable inequality statements to ActiveRecord conditions"
6
+ gemspec.email = "ryan@angilly.com"
7
+ gemspec.homepage = "http://github.com/ryana/inequal_opportunity"
8
+ gemspec.description = "Adds mergable, stackable inequality statements to ActiveRecord conditions"
9
+ gemspec.authors = ["Ryan Angilly"]
10
+ end
11
+ end
@@ -0,0 +1,124 @@
1
+ module ActiveRecord
2
+ module Inequality
3
+
4
+ class Base
5
+ attr_accessor :value
6
+
7
+ def initialize(val)
8
+ self.value = val
9
+ end
10
+
11
+ def operator
12
+ raise('Nope')
13
+ end
14
+ end
15
+
16
+ class GreaterThanEqual < Base
17
+ def operator
18
+ '>='
19
+ end
20
+ end
21
+
22
+ class GreaterThan < Base
23
+ def operator
24
+ '>'
25
+ end
26
+ end
27
+
28
+ class LessThanEqual < Base
29
+ def operator
30
+ '<='
31
+ end
32
+ end
33
+
34
+ class LessThan < Base
35
+ def operator
36
+ '<'
37
+ end
38
+ end
39
+
40
+ class NotEqual < Base
41
+ def operator
42
+ '<>'
43
+ end
44
+ end
45
+
46
+ class Like < Base
47
+ def operator
48
+ 'LIKE'
49
+ end
50
+
51
+ def value
52
+ "%#{super}%"
53
+ end
54
+ end
55
+
56
+ module WrapperMethods
57
+
58
+ def lte(val)
59
+ ActiveRecord::Inequality::LessThanEqual.new(val)
60
+ end
61
+
62
+ def lt(val)
63
+ ActiveRecord::Inequality::LessThan.new(val)
64
+ end
65
+
66
+ def gte(val)
67
+ ActiveRecord::Inequality::GreaterThanEqual.new(val)
68
+ end
69
+
70
+ def gt(val)
71
+ ActiveRecord::Inequality::GreaterThan.new(val)
72
+ end
73
+
74
+ def ne(val)
75
+ ActiveRecord::Inequality::NotEqual.new(val)
76
+ end
77
+
78
+ def like(val)
79
+ ActiveRecord::Inequality::Like.new(val)
80
+ end
81
+
82
+ end
83
+
84
+ end
85
+
86
+ class Base
87
+ class << self
88
+ alias attribute_condition_orig attribute_condition
89
+ def attribute_condition(quoted_column_name, argument)
90
+ if argument.is_a? ActiveRecord::Inequality::Base
91
+ "#{quoted_column_name} #{argument.operator} ?"
92
+ else
93
+ attribute_condition_orig(quoted_column_name, argument)
94
+ end
95
+ end
96
+
97
+ # Copied this from AR. Not ideal.
98
+ alias expand_range_bind_variables_orig expand_range_bind_variables
99
+ def expand_range_bind_variables(bind_vars)
100
+ expanded = []
101
+
102
+ bind_vars.each do |var|
103
+ next if var.is_a?(Hash)
104
+
105
+ if var.is_a?(Range)
106
+ expanded << var.first
107
+ expanded << var.last
108
+ elsif var.is_a?(ActiveRecord::Inequality::Base)
109
+ expanded << var.value
110
+ else
111
+ expanded << var
112
+ end
113
+ end
114
+
115
+ expanded
116
+ end
117
+
118
+ end
119
+ end
120
+
121
+ end
122
+
123
+ include ActiveRecord::Inequality::WrapperMethods
124
+
@@ -0,0 +1,8 @@
1
+ source:
2
+ adapter: mysql
3
+ database:
4
+ host: localhost
5
+ port: 3306
6
+ username:
7
+ password:
8
+
@@ -0,0 +1,79 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+ require 'ruby-debug'
3
+
4
+ DB = YAML::load(File.open(File.join(File.dirname(__FILE__), 'database.yml'))).symbolize_keys!
5
+ ActiveRecord::Base.establish_connection(DB[:source])
6
+
7
+ TABLES = %w(mains seconds)
8
+
9
+ class Main < ActiveRecord::Base
10
+ belongs_to :seconds
11
+ named_scope :newer_than, lambda {|time| {:conditions => {:created_at => gte(time) }} }
12
+ end
13
+
14
+ class Second < ActiveRecord::Base
15
+ has_many :mains
16
+ end
17
+
18
+ #ActiveRecord::Base.logger = Logger.new(STDOUT)
19
+
20
+ class InequalOpportunityTest < Test::Unit::TestCase
21
+
22
+ def setup
23
+ TABLES.each do |t|
24
+ ActiveRecord::Base.connection.execute("create table #{t} (id integer, val integer, seconds_id integer, mains_id integer, created_at datetime default null);")
25
+ end
26
+ end
27
+
28
+ def teardown
29
+ TABLES.each do |t|
30
+ ActiveRecord::Base.connection.execute("drop table #{t};")
31
+ end
32
+ end
33
+
34
+ context "a model" do
35
+ setup do
36
+ @model = Main
37
+ end
38
+
39
+ should "respond to gte" do
40
+ assert @model.respond_to?(:gte)
41
+ end
42
+
43
+ should "should work with a named_scope" do
44
+ assert_equal Main.newer_than(2.days.ago), []
45
+ end
46
+
47
+ should "properly scope based on gte" do
48
+ time = 2.days.ago
49
+ num = 3
50
+ num.times { Main.create(:val => 3) }
51
+ num.times { Main.create(:val => 1) }
52
+
53
+ assert_equal Main.count(:conditions => {:val => gte(2)}), num
54
+ end
55
+
56
+ end
57
+
58
+ context "an instance" do
59
+ setup do
60
+ @main = Main.new
61
+ end
62
+
63
+ should "respond to gte" do
64
+ assert @main.respond_to?(:gte)
65
+ end
66
+
67
+ end
68
+
69
+ context "a parent" do
70
+ setup do
71
+ @second = Second.new
72
+ end
73
+
74
+ should "see through assocaitions" do
75
+ assert @second.mains.respond_to?(:gte)
76
+ end
77
+ end
78
+
79
+ end
@@ -0,0 +1,4 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require File.dirname(__FILE__) + '/../init'
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ryana-inequal_opportunity
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ryan Angilly
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-04-16 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Adds mergable, stackable inequality statements to ActiveRecord conditions
17
+ email: ryan@angilly.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ files:
25
+ - Rakefile
26
+ - lib/inequal_opportunity.rb
27
+ - test/database.example.yml
28
+ - test/inequal_opportunity_test.rb
29
+ - test/test_helper.rb
30
+ - README
31
+ has_rdoc: true
32
+ homepage: http://github.com/ryana/inequal_opportunity
33
+ post_install_message:
34
+ rdoc_options:
35
+ - --charset=UTF-8
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: "0"
43
+ version:
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ requirements: []
51
+
52
+ rubyforge_project:
53
+ rubygems_version: 1.2.0
54
+ signing_key:
55
+ specification_version: 2
56
+ summary: Adds mergable, stackable inequality statements to ActiveRecord conditions
57
+ test_files:
58
+ - test/inequal_opportunity_test.rb
59
+ - test/test_helper.rb