conditioner 0.0.3 → 0.0.4
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/Rakefile +2 -1
- data/lib/conditioner.rb +12 -1
- data/lib/conditioner/condition.rb +10 -9
- data/lib/conditioner/configurator.rb +27 -11
- data/lib/conditioner/fake_model.rb +27 -0
- data/test/conditioner_test.rb +52 -10
- metadata +10 -4
data/Rakefile
CHANGED
@@ -26,9 +26,10 @@ end
|
|
26
26
|
|
27
27
|
PKG_FILES = FileList[ '[a-zA-Z]*', 'generators/**/*', 'lib/**/*', 'rails/**/*', 'tasks/**/*', 'test/**/*' ]
|
28
28
|
|
29
|
+
require 'lib/conditioner.rb'
|
29
30
|
spec = Gem::Specification.new do |s|
|
30
31
|
s.name = "conditioner"
|
31
|
-
s.version =
|
32
|
+
s.version = Conditioner::VERSION
|
32
33
|
s.author = "niquola"
|
33
34
|
s.email = "niquola@gmail.com"
|
34
35
|
s.homepage = "http://github.com/niquola/conditioner"
|
data/lib/conditioner.rb
CHANGED
@@ -2,10 +2,11 @@ $:.unshift(File.dirname(__FILE__)) unless
|
|
2
2
|
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
3
|
|
4
4
|
module Conditioner
|
5
|
-
VERSION = '0.0.
|
5
|
+
VERSION = '0.0.4'
|
6
6
|
autoload :ActiveRecordMixin, 'conditioner/active_record_mixin'
|
7
7
|
autoload :Condition, 'conditioner/condition'
|
8
8
|
autoload :Configurator, 'conditioner/configurator'
|
9
|
+
autoload :FakeModel, 'conditioner/fake_model'
|
9
10
|
|
10
11
|
class << self
|
11
12
|
def enable
|
@@ -23,6 +24,16 @@ module Conditioner
|
|
23
24
|
def configure
|
24
25
|
yield config
|
25
26
|
end
|
27
|
+
|
28
|
+
def create(table_name_or_model, options = {})
|
29
|
+
if table_name_or_model.is_a?(String)
|
30
|
+
model = FakeModel.new(table_name_or_model, options)
|
31
|
+
else
|
32
|
+
model = table_name_or_model
|
33
|
+
end
|
34
|
+
|
35
|
+
Condition.new(model, options)
|
36
|
+
end
|
26
37
|
end
|
27
38
|
end
|
28
39
|
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module Conditioner
|
2
2
|
class Condition < String
|
3
|
-
def initialize(model)
|
4
|
-
@model=model
|
5
|
-
@
|
6
|
-
@
|
7
|
-
@first_condition=true
|
3
|
+
def initialize(model, options = {})
|
4
|
+
@model = model
|
5
|
+
@column_names = @model.column_names
|
6
|
+
@result = []
|
7
|
+
@first_condition = true
|
8
8
|
yield self if block_given?
|
9
9
|
end
|
10
10
|
|
@@ -28,12 +28,12 @@ module Conditioner
|
|
28
28
|
@condition_called_flag= true
|
29
29
|
result= []
|
30
30
|
unless @first_condition
|
31
|
-
result<<' '<<unit
|
31
|
+
result << ' ' << unit
|
32
32
|
else
|
33
|
-
@first_condition=false
|
33
|
+
@first_condition = false
|
34
34
|
end
|
35
|
-
result
|
36
|
-
self<< result.join(" ")
|
35
|
+
result << @model.send(:sanitize_sql_for_conditions, *args)
|
36
|
+
self << result.join(" ")
|
37
37
|
self
|
38
38
|
end
|
39
39
|
|
@@ -59,3 +59,4 @@ module Conditioner
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
end
|
62
|
+
|
@@ -16,17 +16,33 @@ module Conditioner
|
|
16
16
|
|
17
17
|
def activate_default_rules!
|
18
18
|
add_rule do |field, v, cnd|
|
19
|
-
|
20
|
-
cnd.
|
21
|
-
|
22
|
-
cnd.
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
cnd.
|
19
|
+
unless v.nil? || (v.respond_to?(:'empty?') && v.empty?)
|
20
|
+
if cnd.is_field?(field) && v =~ /(\*$|^\*)/
|
21
|
+
cnd.and(["#{cnd.with_table_name(field)} ILIKE ?",v.gsub(/(\*$|^\*)/,'%')])
|
22
|
+
elsif cnd.is_field?(field) && v =~ /(%$|^%)/
|
23
|
+
cnd.and(["upper(#{cnd.with_table_name(field)}) like upper(?)",v])
|
24
|
+
#FIXME: add logic for ranges
|
25
|
+
elsif field=~ /^from_(\w*_(datetime|at))/ and cnd.is_field?($1)
|
26
|
+
cnd.and(["#{cnd.with_table_name($1)} >= ?","#{v} 00:00:00.000"])
|
27
|
+
elsif field=~ /^to_(\w*_(datetime|at))/ and cnd.is_field?($1)
|
28
|
+
cnd.and(["#{cnd.with_table_name($1)} <= ?","#{v} 23:59:59.999"])
|
29
|
+
elsif cnd.is_field?(field) && (field.include?('_datetime') || field.include?('_at'))
|
30
|
+
cnd.and(["(#{cnd.with_table_name(field)} BETWEEN ? AND ?)","#{v} 00:00","#{v} 23:59:59.999"])
|
31
|
+
elsif field=~ /^(\w*)_(ltoe|gtoe|lt|gt)$/ and cnd.is_field?($1)
|
32
|
+
operator = { 'lt' => '<', 'gt' => '>', 'ltoe' => '<=', 'gtoe' => '>=' }[$2]
|
33
|
+
cnd.and(["#{cnd.with_table_name($1)} #{operator} ?", v])
|
34
|
+
elsif field=~ /^(\w*)_(begins_with|ends_with|contains)$/ and cnd.is_field?($1)
|
35
|
+
if $2 == 'begins_with'
|
36
|
+
like_expr = "#{v}%"
|
37
|
+
elsif $2 == 'ends_with'
|
38
|
+
like_expr = "%#{v}"
|
39
|
+
else
|
40
|
+
like_expr = "%#{v}%"
|
41
|
+
end
|
42
|
+
cnd.and(["#{cnd.with_table_name($1)} ILIKE ?", like_expr])
|
43
|
+
elsif field=~ /^(\w*)_in$/ and cnd.is_field?($1)
|
44
|
+
cnd.and(["#{cnd.with_table_name($1)} IN (?)", v])
|
45
|
+
end
|
30
46
|
end
|
31
47
|
end
|
32
48
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Conditioner
|
2
|
+
class FakeModel
|
3
|
+
|
4
|
+
def initialize(table_name, options = {})
|
5
|
+
@table_name = table_name
|
6
|
+
@options = options
|
7
|
+
end
|
8
|
+
|
9
|
+
def sanitize_sql_for_conditions(*args)
|
10
|
+
args << ActiveRecord::Base.connection.quote_table_name(@table_name)
|
11
|
+
ActiveRecord::Base.send(:sanitize_sql_for_conditions, *args)
|
12
|
+
end
|
13
|
+
|
14
|
+
def column_names
|
15
|
+
if @options[:columns]
|
16
|
+
@options[:columns]
|
17
|
+
else
|
18
|
+
@column_names ||= ActiveRecord::Base.connection.columns(@table_name).map { |c| c.name }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def table_name
|
23
|
+
@table_name
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
data/test/conditioner_test.rb
CHANGED
@@ -7,8 +7,8 @@ Conditioner.configure do |cfg|
|
|
7
7
|
#cfg.clear_rules!
|
8
8
|
|
9
9
|
cfg.add_rule do |key, value, cnd|
|
10
|
-
if /(.\w*)_gt/ =~ key.to_s && cnd.is_field?($1)
|
11
|
-
cnd.and(["#{key.gsub(/_gt$/,'')} > ?",value])
|
10
|
+
if /(.\w*)_gt/ =~ key.to_s && cnd.is_field?($1)
|
11
|
+
cnd.and(["#{key.gsub(/_gt$/,'')} > ? ", value])
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
@@ -25,25 +25,67 @@ class TestConditioner < Test::Unit::TestCase
|
|
25
25
|
|
26
26
|
def test_extraction
|
27
27
|
cnd=User.conditioner(:updated_at=>'2009-01-01', :email=>'nicola@mail.com',:unexisting=>'value')
|
28
|
-
assert_match(/"users"."email"\s*=\s*
|
29
|
-
assert_match(/users.updated_at BETWEEN
|
28
|
+
assert_match(/"users"."email"\s*=\s*'nicola@mail.com'/, cnd)
|
29
|
+
assert_match(/users.updated_at BETWEEN '2009-01-01 00:00' AND '2009-01-01 23:59:59.999'/, cnd)
|
30
30
|
assert_no_match(/unexisting/, cnd)
|
31
31
|
end
|
32
32
|
|
33
33
|
def test_extract_from_and_to_prefixed_date_fields
|
34
34
|
cnd = User.conditioner :to_updated_at =>'2010-02-02', :from_updated_at=>'2009-01-01'
|
35
|
-
assert_match(/updated_at <=
|
36
|
-
assert_match(/updated_at >=
|
35
|
+
assert_match(/updated_at <= '2010-02-02 23:59:59.999'/, cnd)
|
36
|
+
assert_match(/updated_at >= '2009-01-01 00:00:00.000'/, cnd)
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_extract_lt_and_gt_postfixed_fields
|
40
|
+
cnd = User.conditioner :id_lt => '5', :id_gt => 2
|
41
|
+
assert_match(/id < '5'/, cnd)
|
42
|
+
assert_match(/id > 2/, cnd)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_extract_ltoe_and_gtoe_postfixed_fields
|
46
|
+
cnd = User.conditioner :id_ltoe => '5', :id_gtoe => 2
|
47
|
+
assert_match(/id <= '5'/, cnd)
|
48
|
+
assert_match(/id >= 2/, cnd)
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_begins_ends_contains_rules
|
52
|
+
cnd = User.conditioner :email_begins_with => "a", :email_ends_with => "b", :email_contains => "c"
|
53
|
+
assert_match(/email ILIKE 'a%'/, cnd)
|
54
|
+
assert_match(/email ILIKE '%b'/, cnd)
|
55
|
+
assert_match(/email ILIKE '%c%'/, cnd)
|
56
|
+
cnd = User.conditioner :email_begins_with => ""
|
57
|
+
assert_no_match(/email ILIKE/, cnd,'must not empty values')
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_in_postfixed_field
|
61
|
+
cnd = User.conditioner :email_in => ['a', 'b', 'c']
|
62
|
+
assert_match(/email IN \('a','b','c'\)/, cnd)
|
37
63
|
end
|
38
64
|
|
39
65
|
def test_ilike
|
40
|
-
cnd = User.conditioner :name=>'*nicola*'
|
41
|
-
assert_match(/name ILIKE
|
42
|
-
assert_no_match(/\*nicola\*/, cnd,'Rule must work only once!')
|
66
|
+
cnd = User.conditioner :name=> '*nicola*'
|
67
|
+
assert_match(/name ILIKE '%nicola%'/, cnd)
|
68
|
+
assert_no_match(/\*nicola\*/, cnd, 'Rule must work only once!')
|
43
69
|
end
|
44
70
|
|
45
71
|
def test_configurator
|
46
72
|
cnd = User.conditioner :created_at_gt => '2010-01-01'
|
47
|
-
assert_match(/created_at >
|
73
|
+
assert_match(/created_at > '2010-01-01'/, cnd)
|
48
74
|
end
|
75
|
+
|
76
|
+
def test_conditioner_without_model
|
77
|
+
cnd = Conditioner.create('users', :columns => ['id', 'email']).extract(:email => "nicola", :foo => "bar")
|
78
|
+
assert_equal(%Q["users"."email" = 'nicola'], cnd)
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_conditioner_without_model_with_advanced_rules
|
82
|
+
cnd = Conditioner.create('users', :columns => ['id', 'email']).extract(:email => "*nicola*")
|
83
|
+
assert_match(/email ILIKE '%nicola%'/, cnd)
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_conditioner_without_model_and_without_hardcoded_columns
|
87
|
+
cnd = Conditioner.create('users').extract(:email => "nicola", :foo => "bar")
|
88
|
+
assert_equal(%Q["users"."email" = 'nicola'], cnd)
|
89
|
+
end
|
90
|
+
|
49
91
|
end
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: conditioner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
7
8
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
9
|
+
- 4
|
10
|
+
version: 0.0.4
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- niquola
|
@@ -14,7 +15,7 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date: 2010-
|
18
|
+
date: 2010-06-18 00:00:00 +04:00
|
18
19
|
default_executable:
|
19
20
|
dependencies: []
|
20
21
|
|
@@ -36,6 +37,7 @@ files:
|
|
36
37
|
- lib/conditioner.rb
|
37
38
|
- lib/conditioner/condition.rb
|
38
39
|
- lib/conditioner/active_record_mixin.rb
|
40
|
+
- lib/conditioner/fake_model.rb
|
39
41
|
- lib/conditioner/configurator.rb
|
40
42
|
- test/conditioner_test.rb
|
41
43
|
- test/test_helper.rb
|
@@ -49,23 +51,27 @@ rdoc_options: []
|
|
49
51
|
require_paths:
|
50
52
|
- lib
|
51
53
|
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
52
55
|
requirements:
|
53
56
|
- - ">="
|
54
57
|
- !ruby/object:Gem::Version
|
58
|
+
hash: 3
|
55
59
|
segments:
|
56
60
|
- 0
|
57
61
|
version: "0"
|
58
62
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
59
64
|
requirements:
|
60
65
|
- - ">="
|
61
66
|
- !ruby/object:Gem::Version
|
67
|
+
hash: 3
|
62
68
|
segments:
|
63
69
|
- 0
|
64
70
|
version: "0"
|
65
71
|
requirements: []
|
66
72
|
|
67
73
|
rubyforge_project:
|
68
|
-
rubygems_version: 1.3.
|
74
|
+
rubygems_version: 1.3.7
|
69
75
|
signing_key:
|
70
76
|
specification_version: 3
|
71
77
|
summary: Simple conditions builder for active_record
|