aub-record_filter 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION.yml +1 -1
- data/lib/record_filter.rb +3 -1
- data/lib/record_filter/conjunctions.rb +19 -4
- data/lib/record_filter/dsl.rb +1 -1
- data/lib/record_filter/dsl/conjunction.rb +4 -0
- data/lib/record_filter/dsl/dsl.rb +5 -0
- data/lib/record_filter/dsl/group_by.rb +11 -0
- data/lib/record_filter/dsl/restriction.rb +2 -0
- data/lib/record_filter/group_by.rb +23 -0
- data/lib/record_filter/order.rb +4 -0
- data/lib/record_filter/query.rb +3 -1
- data/lib/record_filter/table.rb +12 -6
- data/spec/exception_spec.rb +50 -0
- data/spec/implicit_join_spec.rb +9 -9
- data/spec/limits_and_ordering_spec.rb +26 -0
- data/spec/restrictions_spec.rb +9 -0
- data/spec/test.db +0 -0
- metadata +5 -1
data/VERSION.yml
CHANGED
data/lib/record_filter.rb
CHANGED
@@ -2,9 +2,11 @@ require 'rubygems'
|
|
2
2
|
gem 'activerecord', '~> 2.2'
|
3
3
|
require 'active_record'
|
4
4
|
|
5
|
-
%w(active_record query table conjunctions restrictions filter join order dsl).each do |file|
|
5
|
+
%w(active_record query table conjunctions restrictions filter join order group_by dsl).each do |file|
|
6
6
|
require File.join(File.dirname(__FILE__), 'record_filter', file)
|
7
7
|
end
|
8
8
|
|
9
9
|
module RecordFilter
|
10
|
+
class AssociationNotFoundException < Exception; end
|
11
|
+
class ColumnNotFoundException < Exception; end
|
10
12
|
end
|
@@ -5,8 +5,8 @@ module RecordFilter
|
|
5
5
|
|
6
6
|
def self.create_from(dsl_conjunction, table)
|
7
7
|
result = case dsl_conjunction.type
|
8
|
-
when :any_of
|
9
|
-
when :all_of
|
8
|
+
when :any_of then AnyOf.new(table)
|
9
|
+
when :all_of then AllOf.new(table)
|
10
10
|
end
|
11
11
|
|
12
12
|
dsl_conjunction.steps.each do |step|
|
@@ -22,6 +22,8 @@ module RecordFilter
|
|
22
22
|
result.add_limit_and_offset(step.limit, step.offset)
|
23
23
|
when DSL::Order
|
24
24
|
result.add_order(step.column, step.direction)
|
25
|
+
when DSL::GroupBy
|
26
|
+
result.add_group_by(step.column)
|
25
27
|
end
|
26
28
|
end
|
27
29
|
result
|
@@ -35,6 +37,7 @@ module RecordFilter
|
|
35
37
|
end
|
36
38
|
|
37
39
|
def add_restriction(column_name, operator, value, options={})
|
40
|
+
check_column_exists!(column_name)
|
38
41
|
restriction_class = "RecordFilter::Restrictions::#{operator.to_s.camelize}".constantize
|
39
42
|
restriction = restriction_class.new("#{@table_name}.#{column_name}", value, options)
|
40
43
|
self << restriction
|
@@ -50,8 +53,12 @@ module RecordFilter
|
|
50
53
|
@table.join_association(association_name)
|
51
54
|
end
|
52
55
|
|
53
|
-
def add_order(
|
54
|
-
@table.order_column(
|
56
|
+
def add_order(column_name, direction)
|
57
|
+
@table.order_column(column_name, direction)
|
58
|
+
end
|
59
|
+
|
60
|
+
def add_group_by(column_name)
|
61
|
+
@table.group_by_column(column_name)
|
55
62
|
end
|
56
63
|
|
57
64
|
def add_limit_and_offset(limit, offset)
|
@@ -79,6 +86,14 @@ module RecordFilter
|
|
79
86
|
end
|
80
87
|
end
|
81
88
|
end
|
89
|
+
|
90
|
+
protected
|
91
|
+
|
92
|
+
def check_column_exists!(column_name)
|
93
|
+
if (!@table.has_column(column_name))
|
94
|
+
raise ColumnNotFoundException.new("The column #{column_name} was not found in #{@table.table_name}.")
|
95
|
+
end
|
96
|
+
end
|
82
97
|
end
|
83
98
|
|
84
99
|
class AnyOf < Base
|
data/lib/record_filter/dsl.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
%w(conjunction conjunction_dsl dsl join limit order restriction).each { |file| require File.join(File.dirname(__FILE__), 'dsl', file) }
|
1
|
+
%w(conjunction conjunction_dsl dsl group_by join limit order restriction).each { |file| require File.join(File.dirname(__FILE__), 'dsl', file) }
|
2
2
|
|
3
3
|
module RecordFilter
|
4
4
|
module DSL
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module RecordFilter
|
2
|
+
class GroupBy
|
3
|
+
attr_reader :column, :table
|
4
|
+
|
5
|
+
def initialize(column, table)
|
6
|
+
@column, @table = column, table
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_sql
|
10
|
+
table, column = @table, @column
|
11
|
+
while column.is_a?(Hash)
|
12
|
+
table = table.join_association(column.keys[0]).right_table
|
13
|
+
column = column.values[0]
|
14
|
+
end
|
15
|
+
|
16
|
+
if (!table.has_column(column))
|
17
|
+
raise ColumnNotFoundException.new("The column #{column} was not found in #{table.table_name}.")
|
18
|
+
end
|
19
|
+
|
20
|
+
"#{table.table_name}.#{column}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/record_filter/order.rb
CHANGED
@@ -18,6 +18,10 @@ module RecordFilter
|
|
18
18
|
column = column.values[0]
|
19
19
|
end
|
20
20
|
|
21
|
+
if (!table.has_column(column))
|
22
|
+
raise ColumnNotFoundException.new("The column #{column} was not found in #{table.table_name}.")
|
23
|
+
end
|
24
|
+
|
21
25
|
"#{table.table_name}.#{column} #{dir}"
|
22
26
|
end
|
23
27
|
end
|
data/lib/record_filter/query.rb
CHANGED
@@ -10,8 +10,10 @@ module RecordFilter
|
|
10
10
|
params = { :conditions => @conjunction.to_conditions }
|
11
11
|
joins = @table.all_joins
|
12
12
|
params[:joins] = joins.map { |join| join.to_sql } * ' ' unless joins.empty?
|
13
|
-
orders = @table.
|
13
|
+
orders = @table.orders
|
14
14
|
params[:order] = orders.map { |order| order.to_sql } * ', ' unless orders.empty?
|
15
|
+
group_bys = @table.group_bys
|
16
|
+
params[:group] = group_bys.map { |group_by| group_by.to_sql } * ', ' unless group_bys.empty?
|
15
17
|
params[:limit] = @conjunction.limit if @conjunction.limit
|
16
18
|
params[:offset] = @conjunction.offset if @conjunction.offset
|
17
19
|
params
|
data/lib/record_filter/table.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module RecordFilter
|
2
2
|
class Table
|
3
|
-
attr_reader :table_alias
|
3
|
+
attr_reader :table_alias, :orders, :group_bys
|
4
4
|
|
5
5
|
def initialize(model_class, table_alias = nil)
|
6
6
|
@model_class = model_class
|
@@ -9,6 +9,7 @@ module RecordFilter
|
|
9
9
|
@joins_cache = {}
|
10
10
|
@joins = []
|
11
11
|
@orders = []
|
12
|
+
@group_bys = []
|
12
13
|
end
|
13
14
|
|
14
15
|
def table_name
|
@@ -19,6 +20,9 @@ module RecordFilter
|
|
19
20
|
@joins_cache[association_name] ||=
|
20
21
|
begin
|
21
22
|
association = @model_class.reflect_on_association(association_name)
|
23
|
+
if association.nil?
|
24
|
+
raise AssociationNotFoundException.new("The association #{association_name} was not found on #{@model_class.name}.")
|
25
|
+
end
|
22
26
|
case association.macro
|
23
27
|
when :belongs_to, :has_many, :has_one
|
24
28
|
simple_join(association)
|
@@ -39,11 +43,12 @@ module RecordFilter
|
|
39
43
|
@orders << Order.new(column, direction, self)
|
40
44
|
end
|
41
45
|
|
42
|
-
def
|
43
|
-
@
|
44
|
-
|
45
|
-
|
46
|
-
|
46
|
+
def group_by_column(column)
|
47
|
+
@group_bys << GroupBy.new(column, self)
|
48
|
+
end
|
49
|
+
|
50
|
+
def has_column(column_name)
|
51
|
+
@model_class.column_names.include?(column_name.to_s)
|
47
52
|
end
|
48
53
|
|
49
54
|
private
|
@@ -88,6 +93,7 @@ module RecordFilter
|
|
88
93
|
@joins_cache = {}
|
89
94
|
@joins = []
|
90
95
|
@orders = []
|
96
|
+
@group_bys = []
|
91
97
|
end
|
92
98
|
end
|
93
99
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe 'raising exceptions' do
|
4
|
+
|
5
|
+
describe 'on missing associations' do
|
6
|
+
it 'should get AssociationNotFoundException' do
|
7
|
+
lambda {
|
8
|
+
Post.filter do
|
9
|
+
having(:something_that_does_not_exist) do
|
10
|
+
with(:something_bad)
|
11
|
+
end
|
12
|
+
end.inspect
|
13
|
+
}.should raise_error(RecordFilter::AssociationNotFoundException)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'on missing columns' do
|
18
|
+
it 'should get ColumnNotFoundException for with' do
|
19
|
+
lambda {
|
20
|
+
Post.filter do
|
21
|
+
with(:this_is_not_there, 2)
|
22
|
+
end.inspect
|
23
|
+
}.should raise_error(RecordFilter::ColumnNotFoundException)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should get ColumnNotFoundException for without' do
|
27
|
+
lambda {
|
28
|
+
Post.filter do
|
29
|
+
without(:this_is_not_there, 2)
|
30
|
+
end.inspect
|
31
|
+
}.should raise_error(RecordFilter::ColumnNotFoundException)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should get ColumnNotFoundException for order' do
|
35
|
+
lambda {
|
36
|
+
Post.filter do
|
37
|
+
order(:this_is_not_there, :asc)
|
38
|
+
end.inspect
|
39
|
+
}.should raise_error(RecordFilter::ColumnNotFoundException)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should get AssociationNotFoundException for orders on bad associations' do
|
43
|
+
lambda {
|
44
|
+
Post.filter do
|
45
|
+
order({ :this_is_not_there => :eh }, :asc)
|
46
|
+
end.inspect
|
47
|
+
}.should raise_error(RecordFilter::AssociationNotFoundException)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/spec/implicit_join_spec.rb
CHANGED
@@ -9,7 +9,7 @@ describe 'implicit joins' do
|
|
9
9
|
describe 'with single condition inline' do
|
10
10
|
before do
|
11
11
|
Post.filter do
|
12
|
-
having(:blog).with :
|
12
|
+
having(:blog).with :name, 'Test Name'
|
13
13
|
end.inspect
|
14
14
|
end
|
15
15
|
|
@@ -18,7 +18,7 @@ describe 'implicit joins' do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'should query against condition on join table' do
|
21
|
-
Post.last_find[:conditions].should == ['posts__blog.
|
21
|
+
Post.last_find[:conditions].should == ['posts__blog.name = ?', 'Test Name']
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
@@ -28,14 +28,14 @@ describe 'implicit joins' do
|
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'should query against conditions on join table' do
|
31
|
-
Post.last_find[:conditions].should == [%q((posts__blog.
|
31
|
+
Post.last_find[:conditions].should == [%q((posts__blog.name = ?) AND (posts__blog.published = ?)), 'Test Name', true]
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
35
|
describe 'with multiple conditions on single join inline' do
|
36
36
|
before do
|
37
37
|
Post.filter do
|
38
|
-
having(:blog).with :
|
38
|
+
having(:blog).with :name, 'Test Name'
|
39
39
|
having(:blog).with :published, true
|
40
40
|
end.inspect
|
41
41
|
end
|
@@ -47,7 +47,7 @@ describe 'implicit joins' do
|
|
47
47
|
before do
|
48
48
|
Post.filter do
|
49
49
|
having :blog do
|
50
|
-
with :
|
50
|
+
with :name, 'Test Name'
|
51
51
|
with :published, true
|
52
52
|
end
|
53
53
|
end.inspect
|
@@ -154,13 +154,13 @@ describe 'implicit joins' do
|
|
154
154
|
describe 'with nil conditions' do
|
155
155
|
before do
|
156
156
|
Comment.filter do
|
157
|
-
with :
|
157
|
+
with :contents, nil
|
158
158
|
with :offensive, true
|
159
159
|
end.inspect
|
160
160
|
end
|
161
161
|
|
162
162
|
it 'should create the correct IS NULL condition' do
|
163
|
-
Comment.last_find[:conditions].should == [%q(("comments".
|
163
|
+
Comment.last_find[:conditions].should == [%q(("comments".contents IS NULL) AND ("comments".offensive = ?)), true]
|
164
164
|
end
|
165
165
|
end
|
166
166
|
|
@@ -179,13 +179,13 @@ describe 'implicit joins' do
|
|
179
179
|
describe 'with negated nil conditions' do
|
180
180
|
before do
|
181
181
|
Comment.filter do
|
182
|
-
without :
|
182
|
+
without :contents, nil
|
183
183
|
with :offensive, true
|
184
184
|
end.inspect
|
185
185
|
end
|
186
186
|
|
187
187
|
it 'should create the correct IS NOT NULL condition' do
|
188
|
-
Comment.last_find[:conditions].should == [%q(("comments".
|
188
|
+
Comment.last_find[:conditions].should == [%q(("comments".contents IS NOT NULL) AND ("comments".offensive = ?)), true]
|
189
189
|
end
|
190
190
|
end
|
191
191
|
end
|
@@ -161,4 +161,30 @@ describe 'filter qualifiers' do
|
|
161
161
|
end
|
162
162
|
end
|
163
163
|
end
|
164
|
+
|
165
|
+
describe 'group_by' do
|
166
|
+
it 'should add the group for a simple column' do
|
167
|
+
Post.filter do
|
168
|
+
group_by(:created_at)
|
169
|
+
end.inspect
|
170
|
+
Post.last_find[:group].should == %q("posts".created_at)
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'should add the group for multiple column' do
|
174
|
+
Post.filter do
|
175
|
+
group_by(:created_at)
|
176
|
+
group_by(:published)
|
177
|
+
end.inspect
|
178
|
+
Post.last_find[:group].should == %q("posts".created_at, "posts".published)
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'should add the group for joined columns' do
|
182
|
+
Post.filter do
|
183
|
+
having(:photo)
|
184
|
+
group_by(:created_at)
|
185
|
+
group_by(:photo => :format)
|
186
|
+
end.inspect
|
187
|
+
Post.last_find[:group].should == %q("posts".created_at, "photos".format)
|
188
|
+
end
|
189
|
+
end
|
164
190
|
end
|
data/spec/restrictions_spec.rb
CHANGED
@@ -75,4 +75,13 @@ describe 'RecordFilter restrictions' do
|
|
75
75
|
Post.last_find.should == { :conditions => [%q{(("posts".blog_id = ?) AND ("posts".permalink = ?)) OR ("posts".permalink = ?)},
|
76
76
|
1, 'my-post', 'another-post'] }
|
77
77
|
end
|
78
|
+
|
79
|
+
it 'should filter for nil' do
|
80
|
+
[:is_null, :null, :nil].each do |method|
|
81
|
+
Post.filter do
|
82
|
+
with(:permalink).send(method)
|
83
|
+
end.inspect
|
84
|
+
Post.last_find.should == { :conditions => [%q("posts".permalink IS NULL)] }
|
85
|
+
end
|
86
|
+
end
|
78
87
|
end
|
data/spec/test.db
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aub-record_filter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mat Brown
|
@@ -32,17 +32,20 @@ files:
|
|
32
32
|
- lib/record_filter/dsl/conjunction.rb
|
33
33
|
- lib/record_filter/dsl/conjunction_dsl.rb
|
34
34
|
- lib/record_filter/dsl/dsl.rb
|
35
|
+
- lib/record_filter/dsl/group_by.rb
|
35
36
|
- lib/record_filter/dsl/join.rb
|
36
37
|
- lib/record_filter/dsl/limit.rb
|
37
38
|
- lib/record_filter/dsl/order.rb
|
38
39
|
- lib/record_filter/dsl/restriction.rb
|
39
40
|
- lib/record_filter/filter.rb
|
41
|
+
- lib/record_filter/group_by.rb
|
40
42
|
- lib/record_filter/join.rb
|
41
43
|
- lib/record_filter/join_table.rb
|
42
44
|
- lib/record_filter/order.rb
|
43
45
|
- lib/record_filter/query.rb
|
44
46
|
- lib/record_filter/restrictions.rb
|
45
47
|
- lib/record_filter/table.rb
|
48
|
+
- spec/exception_spec.rb
|
46
49
|
- spec/implicit_join_spec.rb
|
47
50
|
- spec/limits_and_ordering_spec.rb
|
48
51
|
- spec/models/blog.rb
|
@@ -81,6 +84,7 @@ signing_key:
|
|
81
84
|
specification_version: 3
|
82
85
|
summary: Pure-ruby criteria API for building complex queries in ActiveRecord
|
83
86
|
test_files:
|
87
|
+
- spec/exception_spec.rb
|
84
88
|
- spec/implicit_join_spec.rb
|
85
89
|
- spec/limits_and_ordering_spec.rb
|
86
90
|
- spec/models/blog.rb
|